1/*
2 * Copyright 2002-2008, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 *
5 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
6 * Distributed under the terms of the NewOS License.
7 */
8#ifndef _LIBROOT_LOCK_H
9#define _LIBROOT_LOCK_H
10
11#include <OS.h>
12
13
14// TODO: Copied from the kernel private lock.h/lock.c. We should somehow make
15// that code reusable.
16
17
18namespace BPrivate {
19
20
21typedef struct benaphore {
22	sem_id	sem;
23	int32	count;
24} benaphore;
25
26
27static inline status_t
28benaphore_init(benaphore *ben, const char *name)
29{
30	if (ben == NULL || name == NULL)
31		return B_BAD_VALUE;
32
33	ben->count = 1;
34	ben->sem = create_sem(0, name);
35	if (ben->sem >= B_OK)
36		return B_OK;
37
38	return ben->sem;
39}
40
41
42static inline status_t
43benaphore_lock_etc(benaphore *ben, uint32 flags, bigtime_t timeout)
44{
45// TODO: This function really shouldn't be used, since timeouts screw the
46// benaphore behavior.
47	if (atomic_add(&ben->count, -1) <= 0)
48		return acquire_sem_etc(ben->sem, 1, flags, timeout);
49
50	return B_OK;
51}
52
53
54static inline status_t
55benaphore_lock(benaphore *ben)
56{
57	if (atomic_add(&ben->count, -1) <= 0) {
58		status_t error;
59		do {
60			error = acquire_sem(ben->sem);
61		} while (error == B_INTERRUPTED);
62
63		return error;
64	}
65
66	return B_OK;
67}
68
69
70static inline status_t
71benaphore_unlock(benaphore *ben)
72{
73	if (atomic_add(&ben->count, 1) < 0)
74		return release_sem(ben->sem);
75
76	return B_OK;
77}
78
79
80}	// namespace BPrivate
81
82
83using BPrivate::benaphore;
84using BPrivate::benaphore_init;
85using BPrivate::benaphore_lock_etc;
86using BPrivate::benaphore_lock;
87using BPrivate::benaphore_unlock;
88
89
90#endif	// _LIBROOT_LOCK_H
91