xref: /haiku/src/system/libroot/os/locks/recursive_lock.cpp (revision 258b34c594867f4447c4e3b5ce9240075f48b7f4)
1*258b34c5SIngo Weinhold /*
2*258b34c5SIngo Weinhold  * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3*258b34c5SIngo Weinhold  * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4*258b34c5SIngo Weinhold  * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
5*258b34c5SIngo Weinhold  * Distributed under the terms of the MIT License.
6*258b34c5SIngo Weinhold  *
7*258b34c5SIngo Weinhold  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
8*258b34c5SIngo Weinhold  * Distributed under the terms of the NewOS License.
9*258b34c5SIngo Weinhold  */
10*258b34c5SIngo Weinhold 
11*258b34c5SIngo Weinhold 
12*258b34c5SIngo Weinhold #include <locks.h>
13*258b34c5SIngo Weinhold 
14*258b34c5SIngo Weinhold #include <OS.h>
15*258b34c5SIngo Weinhold 
16*258b34c5SIngo Weinhold 
17*258b34c5SIngo Weinhold // #pragma mark - recursive lock
18*258b34c5SIngo Weinhold 
19*258b34c5SIngo Weinhold 
20*258b34c5SIngo Weinhold int32
21*258b34c5SIngo Weinhold recursive_lock_get_recursion(recursive_lock *lock)
22*258b34c5SIngo Weinhold {
23*258b34c5SIngo Weinhold 	if (lock->holder == find_thread(NULL))
24*258b34c5SIngo Weinhold 		return lock->recursion;
25*258b34c5SIngo Weinhold 
26*258b34c5SIngo Weinhold 	return -1;
27*258b34c5SIngo Weinhold }
28*258b34c5SIngo Weinhold 
29*258b34c5SIngo Weinhold 
30*258b34c5SIngo Weinhold status_t
31*258b34c5SIngo Weinhold recursive_lock_init(recursive_lock *lock, const char *name)
32*258b34c5SIngo Weinhold {
33*258b34c5SIngo Weinhold 	lock->holder = -1;
34*258b34c5SIngo Weinhold 	lock->recursion = 0;
35*258b34c5SIngo Weinhold 	return mutex_init(&lock->lock, name != NULL ? name : "recursive lock");
36*258b34c5SIngo Weinhold }
37*258b34c5SIngo Weinhold 
38*258b34c5SIngo Weinhold 
39*258b34c5SIngo Weinhold void
40*258b34c5SIngo Weinhold recursive_lock_destroy(recursive_lock *lock)
41*258b34c5SIngo Weinhold {
42*258b34c5SIngo Weinhold 	if (lock == NULL)
43*258b34c5SIngo Weinhold 		return;
44*258b34c5SIngo Weinhold 
45*258b34c5SIngo Weinhold 	mutex_destroy(&lock->lock);
46*258b34c5SIngo Weinhold }
47*258b34c5SIngo Weinhold 
48*258b34c5SIngo Weinhold 
49*258b34c5SIngo Weinhold status_t
50*258b34c5SIngo Weinhold recursive_lock_lock(recursive_lock *lock)
51*258b34c5SIngo Weinhold {
52*258b34c5SIngo Weinhold 	thread_id thread = find_thread(NULL);
53*258b34c5SIngo Weinhold 
54*258b34c5SIngo Weinhold 	if (thread != lock->holder) {
55*258b34c5SIngo Weinhold 		mutex_lock(&lock->lock);
56*258b34c5SIngo Weinhold 		lock->holder = thread;
57*258b34c5SIngo Weinhold 	}
58*258b34c5SIngo Weinhold 
59*258b34c5SIngo Weinhold 	lock->recursion++;
60*258b34c5SIngo Weinhold 	return B_OK;
61*258b34c5SIngo Weinhold }
62*258b34c5SIngo Weinhold 
63*258b34c5SIngo Weinhold 
64*258b34c5SIngo Weinhold void
65*258b34c5SIngo Weinhold recursive_lock_unlock(recursive_lock *lock)
66*258b34c5SIngo Weinhold {
67*258b34c5SIngo Weinhold 	if (find_thread(NULL) != lock->holder) {
68*258b34c5SIngo Weinhold 		debugger("recursive_lock unlocked by non-holder thread!\n");
69*258b34c5SIngo Weinhold 		return;
70*258b34c5SIngo Weinhold 	}
71*258b34c5SIngo Weinhold 
72*258b34c5SIngo Weinhold 	if (--lock->recursion == 0) {
73*258b34c5SIngo Weinhold 		lock->holder = -1;
74*258b34c5SIngo Weinhold 		mutex_unlock(&lock->lock);
75*258b34c5SIngo Weinhold 	}
76*258b34c5SIngo Weinhold }
77*258b34c5SIngo Weinhold 
78*258b34c5SIngo Weinhold 
79*258b34c5SIngo Weinhold // #pragma mark - lazy recursive lock
80*258b34c5SIngo Weinhold 
81*258b34c5SIngo Weinhold 
82*258b34c5SIngo Weinhold int32
83*258b34c5SIngo Weinhold lazy_recursive_lock_get_recursion(lazy_recursive_lock *lock)
84*258b34c5SIngo Weinhold {
85*258b34c5SIngo Weinhold 	if (lock->holder == find_thread(NULL))
86*258b34c5SIngo Weinhold 		return lock->recursion;
87*258b34c5SIngo Weinhold 
88*258b34c5SIngo Weinhold 	return -1;
89*258b34c5SIngo Weinhold }
90*258b34c5SIngo Weinhold 
91*258b34c5SIngo Weinhold 
92*258b34c5SIngo Weinhold status_t
93*258b34c5SIngo Weinhold lazy_recursive_lock_init(lazy_recursive_lock *lock, const char *name)
94*258b34c5SIngo Weinhold {
95*258b34c5SIngo Weinhold 	lock->holder = -1;
96*258b34c5SIngo Weinhold 	lock->recursion = 0;
97*258b34c5SIngo Weinhold 	return lazy_mutex_init(&lock->lock, name != NULL ? name : "recursive lock");
98*258b34c5SIngo Weinhold }
99*258b34c5SIngo Weinhold 
100*258b34c5SIngo Weinhold 
101*258b34c5SIngo Weinhold void
102*258b34c5SIngo Weinhold lazy_recursive_lock_destroy(lazy_recursive_lock *lock)
103*258b34c5SIngo Weinhold {
104*258b34c5SIngo Weinhold 	if (lock == NULL)
105*258b34c5SIngo Weinhold 		return;
106*258b34c5SIngo Weinhold 
107*258b34c5SIngo Weinhold 	lazy_mutex_destroy(&lock->lock);
108*258b34c5SIngo Weinhold }
109*258b34c5SIngo Weinhold 
110*258b34c5SIngo Weinhold 
111*258b34c5SIngo Weinhold status_t
112*258b34c5SIngo Weinhold lazy_recursive_lock_lock(lazy_recursive_lock *lock)
113*258b34c5SIngo Weinhold {
114*258b34c5SIngo Weinhold 	thread_id thread = find_thread(NULL);
115*258b34c5SIngo Weinhold 
116*258b34c5SIngo Weinhold 	if (thread != lock->holder) {
117*258b34c5SIngo Weinhold 		lazy_mutex_lock(&lock->lock);
118*258b34c5SIngo Weinhold 		lock->holder = thread;
119*258b34c5SIngo Weinhold 	}
120*258b34c5SIngo Weinhold 
121*258b34c5SIngo Weinhold 	lock->recursion++;
122*258b34c5SIngo Weinhold 	return B_OK;
123*258b34c5SIngo Weinhold }
124*258b34c5SIngo Weinhold 
125*258b34c5SIngo Weinhold 
126*258b34c5SIngo Weinhold void
127*258b34c5SIngo Weinhold lazy_recursive_lock_unlock(lazy_recursive_lock *lock)
128*258b34c5SIngo Weinhold {
129*258b34c5SIngo Weinhold 	if (find_thread(NULL) != lock->holder) {
130*258b34c5SIngo Weinhold 		debugger("lazy_recursive_lock unlocked by non-holder thread!\n");
131*258b34c5SIngo Weinhold 		return;
132*258b34c5SIngo Weinhold 	}
133*258b34c5SIngo Weinhold 
134*258b34c5SIngo Weinhold 	if (--lock->recursion == 0) {
135*258b34c5SIngo Weinhold 		lock->holder = -1;
136*258b34c5SIngo Weinhold 		lazy_mutex_unlock(&lock->lock);
137*258b34c5SIngo Weinhold 	}
138*258b34c5SIngo Weinhold }
139