1258b34c5SIngo Weinhold /* 2258b34c5SIngo Weinhold * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. 3*f7127458SIngo Weinhold * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 4258b34c5SIngo Weinhold * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 5258b34c5SIngo Weinhold * Distributed under the terms of the MIT License. 6258b34c5SIngo Weinhold * 7258b34c5SIngo Weinhold * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 8258b34c5SIngo Weinhold * Distributed under the terms of the NewOS License. 9258b34c5SIngo Weinhold */ 10258b34c5SIngo Weinhold 11258b34c5SIngo Weinhold 12258b34c5SIngo Weinhold #include <locks.h> 13258b34c5SIngo Weinhold 14*f7127458SIngo Weinhold #include <stdlib.h> 15*f7127458SIngo Weinhold #include <string.h> 16*f7127458SIngo Weinhold 17*f7127458SIngo Weinhold #include <syscalls.h> 18*f7127458SIngo Weinhold #include <user_mutex_defs.h> 19258b34c5SIngo Weinhold 20258b34c5SIngo Weinhold 21258b34c5SIngo Weinhold // #pragma mark - mutex 22258b34c5SIngo Weinhold 23258b34c5SIngo Weinhold 24*f7127458SIngo Weinhold void 25258b34c5SIngo Weinhold mutex_init(mutex *lock, const char *name) 26258b34c5SIngo Weinhold { 27*f7127458SIngo Weinhold lock->name = name; 28*f7127458SIngo Weinhold lock->lock = 0; 29*f7127458SIngo Weinhold lock->flags = 0; 30*f7127458SIngo Weinhold } 31258b34c5SIngo Weinhold 32258b34c5SIngo Weinhold 33*f7127458SIngo Weinhold void 34*f7127458SIngo Weinhold mutex_init_etc(mutex *lock, const char *name, uint32 flags) 35*f7127458SIngo Weinhold { 36*f7127458SIngo Weinhold lock->name = (flags & MUTEX_FLAG_CLONE_NAME) != 0 ? strdup(name) : name; 37*f7127458SIngo Weinhold lock->lock = 0; 38*f7127458SIngo Weinhold lock->flags = flags; 39258b34c5SIngo Weinhold } 40258b34c5SIngo Weinhold 41258b34c5SIngo Weinhold 42258b34c5SIngo Weinhold void 43258b34c5SIngo Weinhold mutex_destroy(mutex *lock) 44258b34c5SIngo Weinhold { 45*f7127458SIngo Weinhold if ((lock->flags & MUTEX_FLAG_CLONE_NAME) != 0) 46*f7127458SIngo Weinhold free(const_cast<char*>(lock->name)); 47258b34c5SIngo Weinhold } 48258b34c5SIngo Weinhold 49258b34c5SIngo Weinhold 50258b34c5SIngo Weinhold status_t 51258b34c5SIngo Weinhold mutex_lock(mutex *lock) 52258b34c5SIngo Weinhold { 53*f7127458SIngo Weinhold // set the locked flag 54*f7127458SIngo Weinhold int32 oldValue = atomic_or(&lock->lock, B_USER_MUTEX_LOCKED); 55*f7127458SIngo Weinhold 56*f7127458SIngo Weinhold if ((oldValue & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) == 0 57*f7127458SIngo Weinhold || (oldValue & B_USER_MUTEX_DISABLED) != 0) { 58*f7127458SIngo Weinhold // No one has the lock or is waiting for it, or the mutex has been 59*f7127458SIngo Weinhold // disabled. 60258b34c5SIngo Weinhold return B_OK; 61*f7127458SIngo Weinhold } 62258b34c5SIngo Weinhold 63*f7127458SIngo Weinhold // we have to call the kernel 64*f7127458SIngo Weinhold status_t error; 65258b34c5SIngo Weinhold do { 66*f7127458SIngo Weinhold error = _kern_mutex_lock(&lock->lock, lock->name, 0, 0); 67*f7127458SIngo Weinhold } while (error == B_INTERRUPTED); 68258b34c5SIngo Weinhold 69*f7127458SIngo Weinhold return error; 70258b34c5SIngo Weinhold } 71258b34c5SIngo Weinhold 72258b34c5SIngo Weinhold 73258b34c5SIngo Weinhold void 74258b34c5SIngo Weinhold mutex_unlock(mutex *lock) 75258b34c5SIngo Weinhold { 76*f7127458SIngo Weinhold // clear the locked flag 77*f7127458SIngo Weinhold int32 oldValue = atomic_and(&lock->lock, ~(int32)B_USER_MUTEX_LOCKED); 78*f7127458SIngo Weinhold if ((oldValue & B_USER_MUTEX_WAITING) != 0 79*f7127458SIngo Weinhold && (oldValue & B_USER_MUTEX_DISABLED) == 0) { 80*f7127458SIngo Weinhold _kern_mutex_unlock(&lock->lock, 0); 81258b34c5SIngo Weinhold } 82258b34c5SIngo Weinhold } 83