xref: /openbmc/linux/drivers/acpi/acpica/utlock.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
28a335a23SBob Moore /******************************************************************************
38a335a23SBob Moore  *
48a335a23SBob Moore  * Module Name: utlock - Reader/Writer lock interfaces
58a335a23SBob Moore  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
78a335a23SBob Moore  *
895857638SErik Schmauss  *****************************************************************************/
98a335a23SBob Moore 
108a335a23SBob Moore #include <acpi/acpi.h>
118a335a23SBob Moore #include "accommon.h"
128a335a23SBob Moore 
138a335a23SBob Moore #define _COMPONENT          ACPI_UTILITIES
148a335a23SBob Moore ACPI_MODULE_NAME("utlock")
158a335a23SBob Moore 
168a335a23SBob Moore /*******************************************************************************
178a335a23SBob Moore  *
188a335a23SBob Moore  * FUNCTION:    acpi_ut_create_rw_lock
198a335a23SBob Moore  *              acpi_ut_delete_rw_lock
208a335a23SBob Moore  *
21ba494beeSBob Moore  * PARAMETERS:  lock                - Pointer to a valid RW lock
228a335a23SBob Moore  *
238a335a23SBob Moore  * RETURN:      Status
248a335a23SBob Moore  *
258a335a23SBob Moore  * DESCRIPTION: Reader/writer lock creation and deletion interfaces.
268a335a23SBob Moore  *
278a335a23SBob Moore  ******************************************************************************/
acpi_ut_create_rw_lock(struct acpi_rw_lock * lock)288a335a23SBob Moore acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock)
298a335a23SBob Moore {
308a335a23SBob Moore 	acpi_status status;
318a335a23SBob Moore 
328a335a23SBob Moore 	lock->num_readers = 0;
338a335a23SBob Moore 	status = acpi_os_create_mutex(&lock->reader_mutex);
348a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
359c0d7939SLv Zheng 		return (status);
368a335a23SBob Moore 	}
378a335a23SBob Moore 
388a335a23SBob Moore 	status = acpi_os_create_mutex(&lock->writer_mutex);
399c0d7939SLv Zheng 	return (status);
408a335a23SBob Moore }
418a335a23SBob Moore 
acpi_ut_delete_rw_lock(struct acpi_rw_lock * lock)428a335a23SBob Moore void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock)
438a335a23SBob Moore {
448a335a23SBob Moore 
458a335a23SBob Moore 	acpi_os_delete_mutex(lock->reader_mutex);
468a335a23SBob Moore 	acpi_os_delete_mutex(lock->writer_mutex);
478a335a23SBob Moore 
488a335a23SBob Moore 	lock->num_readers = 0;
498a335a23SBob Moore 	lock->reader_mutex = NULL;
508a335a23SBob Moore 	lock->writer_mutex = NULL;
518a335a23SBob Moore }
528a335a23SBob Moore 
538a335a23SBob Moore /*******************************************************************************
548a335a23SBob Moore  *
558a335a23SBob Moore  * FUNCTION:    acpi_ut_acquire_read_lock
568a335a23SBob Moore  *              acpi_ut_release_read_lock
578a335a23SBob Moore  *
58ba494beeSBob Moore  * PARAMETERS:  lock                - Pointer to a valid RW lock
598a335a23SBob Moore  *
608a335a23SBob Moore  * RETURN:      Status
618a335a23SBob Moore  *
628a335a23SBob Moore  * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition,
638a335a23SBob Moore  *              only the first reader acquires the write mutex. On release,
648a335a23SBob Moore  *              only the last reader releases the write mutex. Although this
658a335a23SBob Moore  *              algorithm can in theory starve writers, this should not be a
668a335a23SBob Moore  *              problem with ACPICA since the subsystem is infrequently used
678a335a23SBob Moore  *              in comparison to (for example) an I/O system.
688a335a23SBob Moore  *
698a335a23SBob Moore  ******************************************************************************/
708a335a23SBob Moore 
acpi_ut_acquire_read_lock(struct acpi_rw_lock * lock)718a335a23SBob Moore acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock)
728a335a23SBob Moore {
738a335a23SBob Moore 	acpi_status status;
748a335a23SBob Moore 
758a335a23SBob Moore 	status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
768a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
779c0d7939SLv Zheng 		return (status);
788a335a23SBob Moore 	}
798a335a23SBob Moore 
808a335a23SBob Moore 	/* Acquire the write lock only for the first reader */
818a335a23SBob Moore 
828a335a23SBob Moore 	lock->num_readers++;
838a335a23SBob Moore 	if (lock->num_readers == 1) {
848a335a23SBob Moore 		status =
858a335a23SBob Moore 		    acpi_os_acquire_mutex(lock->writer_mutex,
868a335a23SBob Moore 					  ACPI_WAIT_FOREVER);
878a335a23SBob Moore 	}
888a335a23SBob Moore 
898a335a23SBob Moore 	acpi_os_release_mutex(lock->reader_mutex);
909c0d7939SLv Zheng 	return (status);
918a335a23SBob Moore }
928a335a23SBob Moore 
acpi_ut_release_read_lock(struct acpi_rw_lock * lock)938a335a23SBob Moore acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock)
948a335a23SBob Moore {
958a335a23SBob Moore 	acpi_status status;
968a335a23SBob Moore 
978a335a23SBob Moore 	status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
988a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
999c0d7939SLv Zheng 		return (status);
1008a335a23SBob Moore 	}
1018a335a23SBob Moore 
1028a335a23SBob Moore 	/* Release the write lock only for the very last reader */
1038a335a23SBob Moore 
1048a335a23SBob Moore 	lock->num_readers--;
1058a335a23SBob Moore 	if (lock->num_readers == 0) {
1068a335a23SBob Moore 		acpi_os_release_mutex(lock->writer_mutex);
1078a335a23SBob Moore 	}
1088a335a23SBob Moore 
1098a335a23SBob Moore 	acpi_os_release_mutex(lock->reader_mutex);
1109c0d7939SLv Zheng 	return (status);
1118a335a23SBob Moore }
1128a335a23SBob Moore 
1138a335a23SBob Moore /*******************************************************************************
1148a335a23SBob Moore  *
1158a335a23SBob Moore  * FUNCTION:    acpi_ut_acquire_write_lock
1168a335a23SBob Moore  *              acpi_ut_release_write_lock
1178a335a23SBob Moore  *
118ba494beeSBob Moore  * PARAMETERS:  lock                - Pointer to a valid RW lock
1198a335a23SBob Moore  *
1208a335a23SBob Moore  * RETURN:      Status
1218a335a23SBob Moore  *
1228a335a23SBob Moore  * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or
1238a335a23SBob Moore  *              release the writer mutex associated with the lock. Acquisition
1248a335a23SBob Moore  *              of the lock is fully exclusive and will block all readers and
1258a335a23SBob Moore  *              writers until it is released.
1268a335a23SBob Moore  *
1278a335a23SBob Moore  ******************************************************************************/
1288a335a23SBob Moore 
acpi_ut_acquire_write_lock(struct acpi_rw_lock * lock)1298a335a23SBob Moore acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock)
1308a335a23SBob Moore {
1318a335a23SBob Moore 	acpi_status status;
1328a335a23SBob Moore 
1338a335a23SBob Moore 	status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER);
1349c0d7939SLv Zheng 	return (status);
1358a335a23SBob Moore }
1368a335a23SBob Moore 
acpi_ut_release_write_lock(struct acpi_rw_lock * lock)1378a335a23SBob Moore void acpi_ut_release_write_lock(struct acpi_rw_lock *lock)
1388a335a23SBob Moore {
1398a335a23SBob Moore 
1408a335a23SBob Moore 	acpi_os_release_mutex(lock->writer_mutex);
1418a335a23SBob Moore }
142