ObjFW
Loading...
Searching...
No Matches
OFPlainMutex.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
3 *
4 * All rights reserved.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License version 3.0 only,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * version 3.0 for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * version 3.0 along with this program. If not, see
17 * <https://www.gnu.org/licenses/>.
18 */
19
20#include "objfw-defs.h"
21
22#include <errno.h>
23
24#include "platform.h"
25
26#if !defined(OF_HAVE_THREADS) || \
27 (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
28# error No mutexes available!
29#endif
30
31#import "macros.h"
32
35#if defined(OF_HAVE_PTHREADS)
36# include <pthread.h>
37typedef pthread_mutex_t OFPlainMutex;
38#elif defined(OF_WINDOWS)
39# include <windows.h>
40typedef CRITICAL_SECTION OFPlainMutex;
41#elif defined(OF_AMIGAOS)
42# include <exec/semaphores.h>
43typedef struct SignalSemaphore OFPlainMutex;
44#endif
45
46#if defined(OF_HAVE_ATOMIC_OPS)
47# import "OFAtomic.h"
48typedef volatile int OFSpinlock;
49#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
50typedef pthread_spinlock_t OFSpinlock;
51#else
52typedef OFPlainMutex OFSpinlock;
53#endif
54
55#ifdef OF_HAVE_SCHED_YIELD
56# include <sched.h>
57#endif
58
59#if defined(OF_HAVE_RECURSIVE_PTHREAD_MUTEXES) || defined(OF_WINDOWS) || \
60 defined(OF_AMIGAOS)
61# define OFPlainRecursiveMutex OFPlainMutex
62#else
63# import "OFTLSKey.h"
64typedef struct {
65 OFPlainMutex mutex;
66 OFTLSKey count;
67} OFPlainRecursiveMutex;
68#endif
69
70#ifdef __cplusplus
71extern "C" {
72#endif
82extern int OFPlainMutexNew(OFPlainMutex *mutex);
83
90extern int OFPlainMutexLock(OFPlainMutex *mutex);
91
98extern int OFPlainMutexTryLock(OFPlainMutex *mutex);
99
106extern int OFPlainMutexUnlock(OFPlainMutex *mutex);
107
114extern int OFPlainMutexFree(OFPlainMutex *mutex);
115
127extern int OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex);
128
135extern int OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex);
136
143extern int OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex);
144
151extern int OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex);
152
159extern int OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex);
160#ifdef __cplusplus
161}
162#endif
163
164/* Spinlocks are inlined for performance. */
165
170static OF_INLINE void
172{
173#if defined(OF_HAVE_SCHED_YIELD)
174 sched_yield();
175#elif defined(OF_WINDOWS)
176 Sleep(0);
177#endif
178}
179
186static OF_INLINE int
187OFSpinlockNew(OFSpinlock *spinlock)
188{
189#if defined(OF_HAVE_ATOMIC_OPS)
190 *spinlock = 0;
191 return 0;
192#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
193 return pthread_spin_init(spinlock, 0);
194#else
195 return OFPlainMutexNew(spinlock);
196#endif
197}
198
205static OF_INLINE int
206OFSpinlockTryLock(OFSpinlock *spinlock)
207{
208#if defined(OF_HAVE_ATOMIC_OPS)
209 if (OFAtomicIntCompareAndSwap(spinlock, 0, 1)) {
210 OFAcquireMemoryBarrier();
211 return 0;
212 }
213
214 return EBUSY;
215#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
216 return pthread_spin_trylock(spinlock);
217#else
218 return OFPlainMutexTryLock(spinlock);
219#endif
220}
221
228static OF_INLINE int
229OFSpinlockLock(OFSpinlock *spinlock)
230{
231#if defined(OF_HAVE_ATOMIC_OPS)
232 size_t i;
233
234 for (i = 0; i < 10; i++)
235 if (OFSpinlockTryLock(spinlock) == 0)
236 return 0;
237
238 while (OFSpinlockTryLock(spinlock) == EBUSY)
240
241 return 0;
242#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
243 return pthread_spin_lock(spinlock);
244#else
245 return OFPlainMutexLock(spinlock);
246#endif
247}
248
255static OF_INLINE int
256OFSpinlockUnlock(OFSpinlock *spinlock)
257{
258#if defined(OF_HAVE_ATOMIC_OPS)
259 bool ret = OFAtomicIntCompareAndSwap(spinlock, 1, 0);
260
261 OFReleaseMemoryBarrier();
262
263 return (ret ? 0 : EINVAL);
264#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
265 return pthread_spin_unlock(spinlock);
266#else
267 return OFPlainMutexUnlock(spinlock);
268#endif
269}
270
277static OF_INLINE int
278OFSpinlockFree(OFSpinlock *spinlock)
279{
280#if defined(OF_HAVE_ATOMIC_OPS)
281 return 0;
282#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
283 return pthread_spin_destroy(spinlock);
284#else
285 return OFPlainMutexFree(spinlock);
286#endif
287}
int OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex)
Unlocks the specified recursive mutex.
static OF_INLINE int OFSpinlockFree(OFSpinlock *spinlock)
Destroys a spinlock.
Definition OFPlainMutex.h:278
static OF_INLINE int OFSpinlockUnlock(OFSpinlock *spinlock)
Unlocks a spinlock.
Definition OFPlainMutex.h:256
int OFPlainMutexTryLock(OFPlainMutex *mutex)
Tries to lock the specified mutex without blocking.
int OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex)
Destroys the specified recursive mutex.
int OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex)
Tries to lock the specified recursive mutex without blocking.
static OF_INLINE int OFSpinlockNew(OFSpinlock *spinlock)
Creates a new spinlock.
Definition OFPlainMutex.h:187
int OFPlainMutexLock(OFPlainMutex *mutex)
Locks the specified mutex.
int OFPlainMutexNew(OFPlainMutex *mutex)
Creates a new plain mutex.
static OF_INLINE int OFSpinlockTryLock(OFSpinlock *spinlock)
Tries to lock a spinlock.
Definition OFPlainMutex.h:206
static OF_INLINE int OFSpinlockLock(OFSpinlock *spinlock)
Locks a spinlock.
Definition OFPlainMutex.h:229
int OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex)
Creates a new plain recursive mutex.
int OFPlainMutexUnlock(OFPlainMutex *mutex)
Unlocks the specified mutex.
int OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex)
Locks the specified recursive mutex.
static OF_INLINE void OFYieldThread(void)
Yield the current thread, indicating to the OS that another thread should execute instead.
Definition OFPlainMutex.h:171
int OFPlainMutexFree(OFPlainMutex *mutex)
Destroys the specified mutex.