xref: /haiku/src/tools/fs_shell/lock.cpp (revision 93a78ecaa45114d68952d08c4778f073515102f2)
1 /*
2  * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 /* Mutex and recursive_lock code */
10 
11 #include "lock.h"
12 
13 #include "fssh_kernel_export.h"
14 
15 
16 namespace FSShell {
17 
18 
19 int32_t
20 recursive_lock_get_recursion(recursive_lock *lock)
21 {
22 	if (lock->holder == fssh_find_thread(NULL))
23 		return lock->recursion;
24 
25 	return -1;
26 }
27 
28 
29 fssh_status_t
30 recursive_lock_init(recursive_lock *lock, const char *name)
31 {
32 	if (lock == NULL)
33 		return FSSH_B_BAD_VALUE;
34 
35 	if (name == NULL)
36 		name = "recursive lock";
37 
38 	lock->holder = -1;
39 	lock->recursion = 0;
40 	lock->sem = fssh_create_sem(1, name);
41 
42 	if (lock->sem >= FSSH_B_OK)
43 		return FSSH_B_OK;
44 
45 	return lock->sem;
46 }
47 
48 
49 void
50 recursive_lock_destroy(recursive_lock *lock)
51 {
52 	if (lock == NULL)
53 		return;
54 
55 	fssh_delete_sem(lock->sem);
56 	lock->sem = -1;
57 }
58 
59 
60 fssh_status_t
61 recursive_lock_lock(recursive_lock *lock)
62 {
63 	fssh_thread_id thread = fssh_find_thread(NULL);
64 
65 	if (thread != lock->holder) {
66 		fssh_status_t status = fssh_acquire_sem(lock->sem);
67 		if (status < FSSH_B_OK)
68 			return status;
69 
70 		lock->holder = thread;
71 	}
72 	lock->recursion++;
73 	return FSSH_B_OK;
74 }
75 
76 
77 void
78 recursive_lock_unlock(recursive_lock *lock)
79 {
80 	if (fssh_find_thread(NULL) != lock->holder)
81 		fssh_panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
82 
83 	if (--lock->recursion == 0) {
84 		lock->holder = -1;
85 		fssh_release_sem(lock->sem);
86 	}
87 }
88 
89 
90 //	#pragma mark -
91 
92 
93 fssh_status_t
94 mutex_init(mutex *m, const char *name)
95 {
96 	if (m == NULL)
97 		return FSSH_EINVAL;
98 
99 	if (name == NULL)
100 		name = "mutex_sem";
101 
102 	m->holder = -1;
103 
104 	m->sem = fssh_create_sem(1, name);
105 	if (m->sem >= FSSH_B_OK)
106 		return FSSH_B_OK;
107 
108 	return m->sem;
109 }
110 
111 
112 void
113 mutex_destroy(mutex *mutex)
114 {
115 	if (mutex == NULL)
116 		return;
117 
118 	if (mutex->sem >= 0) {
119 		fssh_delete_sem(mutex->sem);
120 		mutex->sem = -1;
121 	}
122 	mutex->holder = -1;
123 }
124 
125 
126 fssh_status_t
127 mutex_lock(mutex *mutex)
128 {
129 	fssh_thread_id me = fssh_find_thread(NULL);
130 	fssh_status_t status;
131 
132 	status = fssh_acquire_sem(mutex->sem);
133 	if (status < FSSH_B_OK)
134 		return status;
135 
136 	if (me == mutex->holder)
137 		fssh_panic("mutex_lock failure: mutex %p (sem = 0x%x) acquired twice by thread 0x%x\n", mutex, (int)mutex->sem, (int)me);
138 
139 	mutex->holder = me;
140 	return FSSH_B_OK;
141 }
142 
143 
144 void
145 mutex_unlock(mutex *mutex)
146 {
147 	fssh_thread_id me = fssh_find_thread(NULL);
148 
149 	if (me != mutex->holder) {
150 		fssh_panic("mutex_unlock failure: thread 0x%x is trying to release mutex %p (current holder 0x%x)\n",
151 			(int)me, mutex, (int)mutex->holder);
152 	}
153 
154 	mutex->holder = -1;
155 	fssh_release_sem(mutex->sem);
156 }
157 
158 
159 //	#pragma mark -
160 
161 
162 fssh_status_t
163 benaphore_init(benaphore *ben, const char *name)
164 {
165 	if (ben == NULL || name == NULL)
166 		return FSSH_B_BAD_VALUE;
167 
168 	ben->count = 1;
169 	ben->sem = fssh_create_sem(0, name);
170 	if (ben->sem >= FSSH_B_OK)
171 		return FSSH_B_OK;
172 
173 	return ben->sem;
174 }
175 
176 
177 void
178 benaphore_destroy(benaphore *ben)
179 {
180 	fssh_delete_sem(ben->sem);
181 	ben->sem = -1;
182 }
183 
184 
185 //	#pragma mark -
186 
187 
188 fssh_status_t
189 rw_lock_init(rw_lock *lock, const char *name)
190 {
191 	if (lock == NULL)
192 		return FSSH_B_BAD_VALUE;
193 
194 	if (name == NULL)
195 		name = "r/w lock";
196 
197 	lock->sem = fssh_create_sem(FSSH_RW_MAX_READERS, name);
198 	if (lock->sem >= FSSH_B_OK)
199 		return FSSH_B_OK;
200 
201 	return lock->sem;
202 }
203 
204 
205 void
206 rw_lock_destroy(rw_lock *lock)
207 {
208 	if (lock == NULL)
209 		return;
210 
211 	fssh_delete_sem(lock->sem);
212 }
213 
214 
215 fssh_status_t
216 rw_lock_read_lock(rw_lock *lock)
217 {
218 	return fssh_acquire_sem(lock->sem);
219 }
220 
221 
222 fssh_status_t
223 rw_lock_read_unlock(rw_lock *lock)
224 {
225 	return fssh_release_sem(lock->sem);
226 }
227 
228 
229 fssh_status_t
230 rw_lock_write_lock(rw_lock *lock)
231 {
232 	return fssh_acquire_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 0, 0);
233 }
234 
235 
236 fssh_status_t
237 rw_lock_write_unlock(rw_lock *lock)
238 {
239 	return fssh_release_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 0);
240 }
241 
242 
243 }	// namespace FSShell
244