VirtualBox

source: vbox/trunk/src/VBox/Additions/haiku/SharedFolders/lock.h

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use