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
14 ACPI_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  ******************************************************************************/
acpi_ut_create_rw_lock(struct acpi_rw_lock * lock)28 acpi_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 
acpi_ut_delete_rw_lock(struct acpi_rw_lock * lock)42 void 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 
acpi_ut_acquire_read_lock(struct acpi_rw_lock * lock)71 acpi_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 
acpi_ut_release_read_lock(struct acpi_rw_lock * lock)93 acpi_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 
acpi_ut_acquire_write_lock(struct acpi_rw_lock * lock)129 acpi_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 
acpi_ut_release_write_lock(struct acpi_rw_lock * lock)137 void acpi_ut_release_write_lock(struct acpi_rw_lock *lock)
138 {
139 
140 	acpi_os_release_mutex(lock->writer_mutex);
141 }
142