diff --git a/headers/private/shared/locks.h b/headers/private/shared/locks.h index 08ab06bea5..20afa28526 100644 --- a/headers/private/shared/locks.h +++ b/headers/private/shared/locks.h @@ -40,6 +40,20 @@ status_t rw_lock_read_unlock(rw_lock *lock); status_t rw_lock_write_lock(rw_lock *lock); status_t rw_lock_write_unlock(rw_lock *lock); + +typedef struct recursive_lock { + mutex lock; + thread_id holder; + int recursion; +} recursive_lock; + +extern status_t recursive_lock_init(recursive_lock *lock, const char *name); +extern void recursive_lock_destroy(recursive_lock *lock); +extern status_t recursive_lock_lock(recursive_lock *lock); +extern status_t recursive_lock_trylock(recursive_lock *lock); +extern void recursive_lock_unlock(recursive_lock *lock); +extern int32 recursive_lock_get_recursion(recursive_lock *lock); + #ifdef __cplusplus } // extern "C" diff --git a/src/system/libroot/os/locks.cpp b/src/system/libroot/os/locks.cpp index c6f4c4b6ad..1972c9c88b 100644 --- a/src/system/libroot/os/locks.cpp +++ b/src/system/libroot/os/locks.cpp @@ -2,6 +2,15 @@ * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. * Distributed under the terms of the MIT License. */ +/* + * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + #include #include @@ -10,6 +19,9 @@ #include +// #pragma mark - mutex + + status_t mutex_init(mutex *lock, const char *name) { @@ -55,6 +67,9 @@ mutex_unlock(mutex *lock) } +// #pragma mark - R/W lock + + typedef struct rw_lock_waiter { rw_lock_waiter * next; thread_id thread; @@ -248,3 +263,65 @@ rw_lock_write_unlock(rw_lock *lock) rw_lock_unblock(lock); return B_OK; } + + +// #pragma mark - recursive lock + + +int32 +recursive_lock_get_recursion(recursive_lock *lock) +{ + if (lock->holder == find_thread(NULL)) + return lock->recursion; + + return -1; +} + + +status_t +recursive_lock_init(recursive_lock *lock, const char *name) +{ + lock->holder = -1; + lock->recursion = 0; + return mutex_init(&lock->lock, name != NULL ? name : "recursive lock"); +} + + +void +recursive_lock_destroy(recursive_lock *lock) +{ + if (lock == NULL) + return; + + mutex_destroy(&lock->lock); +} + + +status_t +recursive_lock_lock(recursive_lock *lock) +{ + thread_id thread = find_thread(NULL); + + if (thread != lock->holder) { + mutex_lock(&lock->lock); + lock->holder = thread; + } + + lock->recursion++; + return B_OK; +} + + +void +recursive_lock_unlock(recursive_lock *lock) +{ + if (find_thread(NULL) != lock->holder) { + debugger("recursive_lock unlocked by non-holder thread!\n"); + return; + } + + if (--lock->recursion == 0) { + lock->holder = -1; + mutex_unlock(&lock->lock); + } +}