VirtualBox

source: vbox/trunk/src/VBox/Additions/haiku/include/lock.h@ 48435

Last change on this file since 48435 was 43363, checked in by vboxsync, 12 years ago

Haiku Additions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/* $Id: lock.h 43363 2012-09-20 09:56:07Z vboxsync $ */
2/** @file
3 * Lock.h - Haiku, private locking internals.
4 */
5
6/*
7 * Copyright (C) 2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*
19 * This code is based on:
20 *
21 * VirtualBox Guest Additions for Haiku.
22 *
23 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
24 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
25 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
26 * Distributed under the terms of the MIT License.
27 */
28
29/** @todo r=ramshankar: Eventually this file should be shipped by Haiku and
30 * should be removed from the VBox tree. */
31
32#ifndef _KERNEL_LOCK_H
33#define _KERNEL_LOCK_H
34
35#include <OS.h>
36
37
38struct mutex_waiter;
39
40typedef struct mutex {
41 const char* name;
42 struct mutex_waiter* waiters;
43#if KDEBUG
44 thread_id holder;
45#else
46 int32 count;
47 uint16 ignore_unlock_count;
48#endif
49 uint8 flags;
50} mutex;
51
52#define MUTEX_FLAG_CLONE_NAME 0x1
53
54
55typedef struct recursive_lock {
56 mutex lock;
57#if !KDEBUG
58 thread_id holder;
59#endif
60 int recursion;
61} recursive_lock;
62
63
64struct rw_lock_waiter;
65
66typedef struct rw_lock {
67 const char* name;
68 struct rw_lock_waiter* waiters;
69 thread_id holder;
70 vint32 count;
71 int32 owner_count;
72 int16 active_readers;
73 // Only > 0 while a writer is waiting: number
74 // of active readers when the first waiting
75 // writer started waiting.
76 int16 pending_readers;
77 // Number of readers that have already
78 // incremented "count", but have not yet started
79 // to wait at the time the last writer unlocked.
80 uint32 flags;
81} rw_lock;
82
83#define RW_LOCK_WRITER_COUNT_BASE 0x10000
84
85#define RW_LOCK_FLAG_CLONE_NAME 0x1
86
87
88#if KDEBUG
89# define KDEBUG_RW_LOCK_DEBUG 0
90 // Define to 1 if you want to use ASSERT_READ_LOCKED_RW_LOCK().
91 // The rw_lock will just behave like a recursive locker then.
92# define ASSERT_LOCKED_RECURSIVE(r) \
93 { ASSERT(find_thread(NULL) == (r)->lock.holder); }
94# define ASSERT_LOCKED_MUTEX(m) { ASSERT(find_thread(NULL) == (m)->holder); }
95# define ASSERT_WRITE_LOCKED_RW_LOCK(l) \
96 { ASSERT(find_thread(NULL) == (l)->holder); }
97# if KDEBUG_RW_LOCK_DEBUG
98# define ASSERT_READ_LOCKED_RW_LOCK(l) \
99 { ASSERT(find_thread(NULL) == (l)->holder); }
100# else
101# define ASSERT_READ_LOCKED_RW_LOCK(l) do {} while (false)
102# endif
103#else
104# define ASSERT_LOCKED_RECURSIVE(r) do {} while (false)
105# define ASSERT_LOCKED_MUTEX(m) do {} while (false)
106# define ASSERT_WRITE_LOCKED_RW_LOCK(m) do {} while (false)
107# define ASSERT_READ_LOCKED_RW_LOCK(l) do {} while (false)
108#endif
109
110
111// static initializers
112#if KDEBUG
113# define MUTEX_INITIALIZER(name) { name, NULL, -1, 0 }
114# define RECURSIVE_LOCK_INITIALIZER(name) { MUTEX_INITIALIZER(name), 0 }
115#else
116# define MUTEX_INITIALIZER(name) { name, NULL, 0, 0, 0 }
117# define RECURSIVE_LOCK_INITIALIZER(name) { MUTEX_INITIALIZER(name), -1, 0 }
118#endif
119
120#define RW_LOCK_INITIALIZER(name) { name, NULL, -1, 0, 0, 0 }
121
122
123#if KDEBUG
124# define RECURSIVE_LOCK_HOLDER(recursiveLock) ((recursiveLock)->lock.holder)
125#else
126# define RECURSIVE_LOCK_HOLDER(recursiveLock) ((recursiveLock)->holder)
127#endif
128
129
130#ifdef __cplusplus
131extern "C" {
132#endif
133
134extern void recursive_lock_init(recursive_lock *lock, const char *name);
135 // name is *not* cloned nor freed in recursive_lock_destroy()
136extern void recursive_lock_init_etc(recursive_lock *lock, const char *name,
137 uint32 flags);
138extern void recursive_lock_destroy(recursive_lock *lock);
139extern status_t recursive_lock_lock(recursive_lock *lock);
140extern status_t recursive_lock_trylock(recursive_lock *lock);
141extern void recursive_lock_unlock(recursive_lock *lock);
142extern int32 recursive_lock_get_recursion(recursive_lock *lock);
143
144extern void rw_lock_init(rw_lock* lock, const char* name);
145 // name is *not* cloned nor freed in rw_lock_destroy()
146extern void rw_lock_init_etc(rw_lock* lock, const char* name, uint32 flags);
147extern void rw_lock_destroy(rw_lock* lock);
148extern status_t rw_lock_write_lock(rw_lock* lock);
149
150extern void mutex_init(mutex* lock, const char* name);
151 // name is *not* cloned nor freed in mutex_destroy()
152extern void mutex_init_etc(mutex* lock, const char* name, uint32 flags);
153extern void mutex_destroy(mutex* lock);
154extern status_t mutex_switch_lock(mutex* from, mutex* to);
155 // Unlocks "from" and locks "to" such that unlocking and starting to wait
156 // for the lock is atomically. I.e. if "from" guards the object "to" belongs
157 // to, the operation is safe as long as "from" is held while destroying
158 // "to".
159extern status_t mutex_switch_from_read_lock(rw_lock* from, mutex* to);
160 // Like mutex_switch_lock(), just for a switching from a read-locked
161 // rw_lock.
162
163
164// implementation private:
165
166extern status_t _rw_lock_read_lock(rw_lock* lock);
167extern status_t _rw_lock_read_lock_with_timeout(rw_lock* lock,
168 uint32 timeoutFlags, bigtime_t timeout);
169extern void _rw_lock_read_unlock(rw_lock* lock, bool threadsLocked);
170extern void _rw_lock_write_unlock(rw_lock* lock, bool threadsLocked);
171
172extern status_t _mutex_lock(mutex* lock, bool threadsLocked);
173extern void _mutex_unlock(mutex* lock, bool threadsLocked);
174extern status_t _mutex_trylock(mutex* lock);
175extern status_t _mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags,
176 bigtime_t timeout);
177
178
179static inline status_t
180rw_lock_read_lock(rw_lock* lock)
181{
182#if KDEBUG_RW_LOCK_DEBUG
183 return rw_lock_write_lock(lock);
184#else
185 int32 oldCount = atomic_add(&lock->count, 1);
186 if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
187 return _rw_lock_read_lock(lock);
188 return B_OK;
189#endif
190}
191
192
193static inline status_t
194rw_lock_read_lock_with_timeout(rw_lock* lock, uint32 timeoutFlags,
195 bigtime_t timeout)
196{
197#if KDEBUG_RW_LOCK_DEBUG
198 return mutex_lock_with_timeout(lock, timeoutFlags, timeout);
199#else
200 int32 oldCount = atomic_add(&lock->count, 1);
201 if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
202 return _rw_lock_read_lock_with_timeout(lock, timeoutFlags, timeout);
203 return B_OK;
204#endif
205}
206
207
208static inline void
209rw_lock_read_unlock(rw_lock* lock)
210{
211#if KDEBUG_RW_LOCK_DEBUG
212 rw_lock_write_unlock(lock);
213#else
214 int32 oldCount = atomic_add(&lock->count, -1);
215 if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
216 _rw_lock_read_unlock(lock, false);
217#endif
218}
219
220
221static inline void
222rw_lock_write_unlock(rw_lock* lock)
223{
224 _rw_lock_write_unlock(lock, false);
225}
226
227
228static inline status_t
229mutex_lock(mutex* lock)
230{
231#if KDEBUG
232 return _mutex_lock(lock, false);
233#else
234 if (atomic_add(&lock->count, -1) < 0)
235 return _mutex_lock(lock, false);
236 return B_OK;
237#endif
238}
239
240
241static inline status_t
242mutex_lock_threads_locked(mutex* lock)
243{
244#if KDEBUG
245 return _mutex_lock(lock, true);
246#else
247 if (atomic_add(&lock->count, -1) < 0)
248 return _mutex_lock(lock, true);
249 return B_OK;
250#endif
251}
252
253
254static inline status_t
255mutex_trylock(mutex* lock)
256{
257#if KDEBUG
258 return _mutex_trylock(lock);
259#else
260 if (atomic_test_and_set(&lock->count, -1, 0) != 0)
261 return B_WOULD_BLOCK;
262 return B_OK;
263#endif
264}
265
266
267static inline status_t
268mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout)
269{
270#if KDEBUG
271 return _mutex_lock_with_timeout(lock, timeoutFlags, timeout);
272#else
273 if (atomic_add(&lock->count, -1) < 0)
274 return _mutex_lock_with_timeout(lock, timeoutFlags, timeout);
275 return B_OK;
276#endif
277}
278
279
280static inline void
281mutex_unlock(mutex* lock)
282{
283#if !KDEBUG
284 if (atomic_add(&lock->count, 1) < -1)
285#endif
286 _mutex_unlock(lock, false);
287}
288
289
290static inline void
291mutex_transfer_lock(mutex* lock, thread_id thread)
292{
293#if KDEBUG
294 lock->holder = thread;
295#endif
296}
297
298
299extern void lock_debug_init();
300
301#ifdef __cplusplus
302}
303#endif
304
305#endif /* _KERNEL_LOCK_H */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette