1258b34c5SIngo Weinhold /* 2258b34c5SIngo Weinhold * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. 3f7127458SIngo 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 14f7127458SIngo Weinhold #include <stdlib.h> 15f7127458SIngo Weinhold #include <string.h> 16f7127458SIngo Weinhold 17f7127458SIngo Weinhold #include <syscalls.h> 18f7127458SIngo Weinhold #include <user_mutex_defs.h> 19258b34c5SIngo Weinhold 20258b34c5SIngo Weinhold 217e1c4534SPawel Dziepak #define MAX_UNSUCCESSFUL_SPINS 100 227e1c4534SPawel Dziepak 237e1c4534SPawel Dziepak 247e1c4534SPawel Dziepak extern int32 __gCPUCount; 257e1c4534SPawel Dziepak 267e1c4534SPawel Dziepak 27258b34c5SIngo Weinhold // #pragma mark - mutex 28258b34c5SIngo Weinhold 29258b34c5SIngo Weinhold 30f7127458SIngo Weinhold void 31b916156aSJulian Harnath __mutex_init(mutex *lock, const char *name) 32258b34c5SIngo Weinhold { 33f7127458SIngo Weinhold lock->name = name; 34f7127458SIngo Weinhold lock->lock = 0; 35f7127458SIngo Weinhold lock->flags = 0; 36f7127458SIngo Weinhold } 37258b34c5SIngo Weinhold 38258b34c5SIngo Weinhold 39f7127458SIngo Weinhold void 40b916156aSJulian Harnath __mutex_init_etc(mutex *lock, const char *name, uint32 flags) 41f7127458SIngo Weinhold { 42f7127458SIngo Weinhold lock->name = (flags & MUTEX_FLAG_CLONE_NAME) != 0 ? strdup(name) : name; 43f7127458SIngo Weinhold lock->lock = 0; 44f7127458SIngo Weinhold lock->flags = flags; 457e1c4534SPawel Dziepak 467e1c4534SPawel Dziepak if (__gCPUCount < 2) 477e1c4534SPawel Dziepak lock->flags &= ~uint32(MUTEX_FLAG_ADAPTIVE); 48258b34c5SIngo Weinhold } 49258b34c5SIngo Weinhold 50258b34c5SIngo Weinhold 51258b34c5SIngo Weinhold void 52b916156aSJulian Harnath __mutex_destroy(mutex *lock) 53258b34c5SIngo Weinhold { 54f7127458SIngo Weinhold if ((lock->flags & MUTEX_FLAG_CLONE_NAME) != 0) 55f7127458SIngo Weinhold free(const_cast<char*>(lock->name)); 56258b34c5SIngo Weinhold } 57258b34c5SIngo Weinhold 58258b34c5SIngo Weinhold 59258b34c5SIngo Weinhold status_t 60b916156aSJulian Harnath __mutex_lock(mutex *lock) 61258b34c5SIngo Weinhold { 6282727571SPawel Dziepak uint32 count = 0; 637e1c4534SPawel Dziepak const uint32 kMaxCount 647e1c4534SPawel Dziepak = (lock->flags & MUTEX_FLAG_ADAPTIVE) != 0 ? MAX_UNSUCCESSFUL_SPINS : 1; 657e1c4534SPawel Dziepak 667e1c4534SPawel Dziepak int32 oldValue; 677e1c4534SPawel Dziepak do { 68*6f3f29c7SAugustin Cavalier oldValue = atomic_test_and_set(&lock->lock, B_USER_MUTEX_LOCKED, 0); 69*6f3f29c7SAugustin Cavalier if (oldValue == 0 || (oldValue & B_USER_MUTEX_DISABLED) != 0) 70258b34c5SIngo Weinhold return B_OK; 717e1c4534SPawel Dziepak } while (count++ < kMaxCount && (oldValue & B_USER_MUTEX_WAITING) != 0); 72258b34c5SIngo Weinhold 73f7127458SIngo Weinhold // we have to call the kernel 74f7127458SIngo Weinhold status_t error; 75258b34c5SIngo Weinhold do { 76f7127458SIngo Weinhold error = _kern_mutex_lock(&lock->lock, lock->name, 0, 0); 77f7127458SIngo Weinhold } while (error == B_INTERRUPTED); 78258b34c5SIngo Weinhold 79f7127458SIngo Weinhold return error; 80258b34c5SIngo Weinhold } 81258b34c5SIngo Weinhold 82258b34c5SIngo Weinhold 83258b34c5SIngo Weinhold void 84b916156aSJulian Harnath __mutex_unlock(mutex *lock) 85258b34c5SIngo Weinhold { 86f7127458SIngo Weinhold // clear the locked flag 87f7127458SIngo Weinhold int32 oldValue = atomic_and(&lock->lock, ~(int32)B_USER_MUTEX_LOCKED); 88f7127458SIngo Weinhold if ((oldValue & B_USER_MUTEX_WAITING) != 0 89f7127458SIngo Weinhold && (oldValue & B_USER_MUTEX_DISABLED) == 0) { 90*6f3f29c7SAugustin Cavalier _kern_mutex_unblock(&lock->lock, 0); 91258b34c5SIngo Weinhold } 9265a76a0fSAugustin Cavalier 9365a76a0fSAugustin Cavalier if ((oldValue & B_USER_MUTEX_LOCKED) == 0) 9465a76a0fSAugustin Cavalier debugger("mutex was not actually locked!"); 95258b34c5SIngo Weinhold } 96