headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / libroot / os / locks / mutex.cpp
blobac074a6bdaf17e50aa8453175a0f3c42a0c10a99
1 /*
2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
5 * Distributed under the terms of the MIT License.
7 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
8 * Distributed under the terms of the NewOS License.
9 */
12 #include <locks.h>
14 #include <stdlib.h>
15 #include <string.h>
17 #include <syscalls.h>
18 #include <user_mutex_defs.h>
21 #define MAX_UNSUCCESSFUL_SPINS 100
24 extern int32 __gCPUCount;
27 // #pragma mark - mutex
30 void
31 __mutex_init(mutex *lock, const char *name)
33 lock->name = name;
34 lock->lock = 0;
35 lock->flags = 0;
39 void
40 __mutex_init_etc(mutex *lock, const char *name, uint32 flags)
42 lock->name = (flags & MUTEX_FLAG_CLONE_NAME) != 0 ? strdup(name) : name;
43 lock->lock = 0;
44 lock->flags = flags;
46 if (__gCPUCount < 2)
47 lock->flags &= ~uint32(MUTEX_FLAG_ADAPTIVE);
51 void
52 __mutex_destroy(mutex *lock)
54 if ((lock->flags & MUTEX_FLAG_CLONE_NAME) != 0)
55 free(const_cast<char*>(lock->name));
59 status_t
60 __mutex_lock(mutex *lock)
62 uint32 count = 0;
63 const uint32 kMaxCount
64 = (lock->flags & MUTEX_FLAG_ADAPTIVE) != 0 ? MAX_UNSUCCESSFUL_SPINS : 1;
66 int32 oldValue;
67 do {
68 // set the locked flag
69 oldValue = atomic_or(&lock->lock, B_USER_MUTEX_LOCKED);
71 if ((oldValue & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) == 0
72 || (oldValue & B_USER_MUTEX_DISABLED) != 0) {
73 // No one has the lock or is waiting for it, or the mutex has been
74 // disabled.
75 return B_OK;
77 } while (count++ < kMaxCount && (oldValue & B_USER_MUTEX_WAITING) != 0);
79 // we have to call the kernel
80 status_t error;
81 do {
82 error = _kern_mutex_lock(&lock->lock, lock->name, 0, 0);
83 } while (error == B_INTERRUPTED);
85 return error;
89 void
90 __mutex_unlock(mutex *lock)
92 // clear the locked flag
93 int32 oldValue = atomic_and(&lock->lock, ~(int32)B_USER_MUTEX_LOCKED);
94 if ((oldValue & B_USER_MUTEX_WAITING) != 0
95 && (oldValue & B_USER_MUTEX_DISABLED) == 0) {
96 _kern_mutex_unlock(&lock->lock, 0);