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.
6 *
7 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
8 * Distributed under the terms of the NewOS License.
9 */
10
11
12#include <locks.h>
13
14#include <stdlib.h>
15#include <string.h>
16
17#include <syscalls.h>
18#include <user_mutex_defs.h>
19
20
21// #pragma mark - mutex
22
23
24void
25mutex_init(mutex *lock, const char *name)
26{
27	lock->name = name;
28	lock->lock = 0;
29	lock->flags = 0;
30}
31
32
33void
34mutex_init_etc(mutex *lock, const char *name, uint32 flags)
35{
36	lock->name = (flags & MUTEX_FLAG_CLONE_NAME) != 0 ? strdup(name) : name;
37	lock->lock = 0;
38	lock->flags = flags;
39}
40
41
42void
43mutex_destroy(mutex *lock)
44{
45	if ((lock->flags & MUTEX_FLAG_CLONE_NAME) != 0)
46		free(const_cast<char*>(lock->name));
47}
48
49
50status_t
51mutex_lock(mutex *lock)
52{
53	// set the locked flag
54	int32 oldValue = atomic_or(&lock->lock, B_USER_MUTEX_LOCKED);
55
56	if ((oldValue & (B_USER_MUTEX_LOCKED | B_USER_MUTEX_WAITING)) == 0
57			|| (oldValue & B_USER_MUTEX_DISABLED) != 0) {
58		// No one has the lock or is waiting for it, or the mutex has been
59		// disabled.
60		return B_OK;
61	}
62
63	// we have to call the kernel
64	status_t error;
65	do {
66		error = _kern_mutex_lock(&lock->lock, lock->name, 0, 0);
67	} while (error == B_INTERRUPTED);
68
69	return error;
70}
71
72
73void
74mutex_unlock(mutex *lock)
75{
76	// clear the locked flag
77	int32 oldValue = atomic_and(&lock->lock, ~(int32)B_USER_MUTEX_LOCKED);
78	if ((oldValue & B_USER_MUTEX_WAITING) != 0
79			&& (oldValue & B_USER_MUTEX_DISABLED) == 0) {
80		_kern_mutex_unlock(&lock->lock, 0);
81	}
82}
83