1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2/******************************************************************************
3 *
4 * Module Name: utlock - Reader/Writer lock interfaces
5 *
6 * Copyright (C) 2000 - 2023, Intel Corp.
7 *
8 *****************************************************************************/
9
10#include <acpi/acpi.h>
11#include "accommon.h"
12
13#define _COMPONENT ACPI_UTILITIES
14ACPI_MODULE_NAME("utlock")
15
16/*******************************************************************************
17 *
18 * FUNCTION: acpi_ut_create_rw_lock
19 * acpi_ut_delete_rw_lock
20 *
21 * PARAMETERS: lock - Pointer to a valid RW lock
22 *
23 * RETURN: Status
24 *
25 * DESCRIPTION: Reader/writer lock creation and deletion interfaces.
26 *
27 ******************************************************************************/
28acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock)
29{
30 acpi_status status;
31
32 lock->num_readers = 0;
33 status = acpi_os_create_mutex(&lock->reader_mutex);
34 if (ACPI_FAILURE(status)) {
35 return (status);
36 }
37
38 status = acpi_os_create_mutex(&lock->writer_mutex);
39 return (status);
40}
41
42void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock)
43{
44
45 acpi_os_delete_mutex(lock->reader_mutex);
46 acpi_os_delete_mutex(lock->writer_mutex);
47
48 lock->num_readers = 0;
49 lock->reader_mutex = NULL;
50 lock->writer_mutex = NULL;
51}
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ut_acquire_read_lock
56 * acpi_ut_release_read_lock
57 *
58 * PARAMETERS: lock - Pointer to a valid RW lock
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition,
63 * only the first reader acquires the write mutex. On release,
64 * only the last reader releases the write mutex. Although this
65 * algorithm can in theory starve writers, this should not be a
66 * problem with ACPICA since the subsystem is infrequently used
67 * in comparison to (for example) an I/O system.
68 *
69 ******************************************************************************/
70
71acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock)
72{
73 acpi_status status;
74
75 status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
76 if (ACPI_FAILURE(status)) {
77 return (status);
78 }
79
80 /* Acquire the write lock only for the first reader */
81
82 lock->num_readers++;
83 if (lock->num_readers == 1) {
84 status =
85 acpi_os_acquire_mutex(lock->writer_mutex,
86 ACPI_WAIT_FOREVER);
87 }
88
89 acpi_os_release_mutex(lock->reader_mutex);
90 return (status);
91}
92
93acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock)
94{
95 acpi_status status;
96
97 status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
98 if (ACPI_FAILURE(status)) {
99 return (status);
100 }
101
102 /* Release the write lock only for the very last reader */
103
104 lock->num_readers--;
105 if (lock->num_readers == 0) {
106 acpi_os_release_mutex(lock->writer_mutex);
107 }
108
109 acpi_os_release_mutex(lock->reader_mutex);
110 return (status);
111}
112
113/*******************************************************************************
114 *
115 * FUNCTION: acpi_ut_acquire_write_lock
116 * acpi_ut_release_write_lock
117 *
118 * PARAMETERS: lock - Pointer to a valid RW lock
119 *
120 * RETURN: Status
121 *
122 * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or
123 * release the writer mutex associated with the lock. Acquisition
124 * of the lock is fully exclusive and will block all readers and
125 * writers until it is released.
126 *
127 ******************************************************************************/
128
129acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock)
130{
131 acpi_status status;
132
133 status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER);
134 return (status);
135}
136
137void acpi_ut_release_write_lock(struct acpi_rw_lock *lock)
138{
139
140 acpi_os_release_mutex(lock->writer_mutex);
141}
142

source code of linux/drivers/acpi/acpica/utlock.c