193b63126SMichael Lotz/*
293b63126SMichael Lotz * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
393b63126SMichael Lotz * Distributed under the terms of the MIT License.
493b63126SMichael Lotz */
593b63126SMichael Lotz#ifndef _LOCKS_H_
693b63126SMichael Lotz#define _LOCKS_H_
793b63126SMichael Lotz
893b63126SMichael Lotz#include <OS.h>
993b63126SMichael Lotz
1093b63126SMichael Lotz#ifdef __cplusplus
1193b63126SMichael Lotzextern "C" {
1293b63126SMichael Lotz#endif
1393b63126SMichael Lotz
1493b63126SMichael Lotztypedef struct mutex {
15f7127458SIngo Weinhold	const char*	name;
16f7127458SIngo Weinhold	int32		lock;
17f7127458SIngo Weinhold	uint32		flags;
1893b63126SMichael Lotz} mutex;
1993b63126SMichael Lotz
20f7127458SIngo Weinhold#define MUTEX_FLAG_CLONE_NAME		0x1
217e1c4534SPawel Dziepak#define MUTEX_FLAG_ADAPTIVE			0x2
22f7127458SIngo Weinhold#define MUTEX_INITIALIZER(name)		{ name, 0, 0 }
23f7127458SIngo Weinhold
24b916156aSJulian Harnath#define mutex_init(lock, name)            __mutex_init(lock, name)
25b916156aSJulian Harnath#define mutex_init_etc(lock, name, flags) __mutex_init_etc(lock, name, flags)
26b916156aSJulian Harnath#define mutex_destroy(lock)               __mutex_destroy(lock)
27b916156aSJulian Harnath#define mutex_lock(lock)                  __mutex_lock(lock)
28b916156aSJulian Harnath#define mutex_unlock(lock)                __mutex_unlock(lock)
29b916156aSJulian Harnath
30b916156aSJulian Harnathvoid		__mutex_init(mutex *lock, const char *name);
31b916156aSJulian Harnathvoid		__mutex_init_etc(mutex *lock, const char *name, uint32 flags);
32b916156aSJulian Harnathvoid		__mutex_destroy(mutex *lock);
33b916156aSJulian Harnathstatus_t	__mutex_lock(mutex *lock);
34b916156aSJulian Harnathvoid		__mutex_unlock(mutex *lock);
3593b63126SMichael Lotz
3693b63126SMichael Lotz
3793b63126SMichael Lotztypedef struct rw_lock {
3893b63126SMichael Lotz	mutex					lock;
3993b63126SMichael Lotz	struct rw_lock_waiter *	waiters;
4093b63126SMichael Lotz	struct rw_lock_waiter *	last_waiter;
4193b63126SMichael Lotz	thread_id				holder;
4293b63126SMichael Lotz	int32					reader_count;
4393b63126SMichael Lotz	int32					writer_count;
4493b63126SMichael Lotz	int32					owner_count;
4593b63126SMichael Lotz} rw_lock;
4693b63126SMichael Lotz
47f7127458SIngo Weinhold#define RW_LOCK_FLAG_CLONE_NAME			MUTEX_FLAG_CLONE_NAME
48f7127458SIngo Weinhold#define RW_LOCK_INITIALIZER(name)		{ MUTEX_INITIALIZER(name), NULL, \
49f7127458SIngo Weinhold											NULL, -1, 0, 0, 0 }
50f7127458SIngo Weinhold
51b916156aSJulian Harnath#define rw_lock_init(lock, name)   __rw_lock_init(lock, name)
52b916156aSJulian Harnath#define rw_lock_init_etc(lock, name, flags) \
53b916156aSJulian Harnath      __rw_lock_init_etc(lock, name, flags)
54b916156aSJulian Harnath#define rw_lock_destroy(lock)      __rw_lock_destroy(lock)
55b916156aSJulian Harnath#define rw_lock_read_lock(lock)    __rw_lock_read_lock(lock)
56b916156aSJulian Harnath#define rw_lock_read_unlock(lock)  __rw_lock_read_unlock(lock)
57b916156aSJulian Harnath#define rw_lock_write_lock(lock)   __rw_lock_write_lock(lock)
58b916156aSJulian Harnath#define rw_lock_write_unlock(lock) __rw_lock_write_unlock(lock)
59b916156aSJulian Harnath
60b916156aSJulian Harnathvoid		__rw_lock_init(rw_lock *lock, const char *name);
61b916156aSJulian Harnathvoid		__rw_lock_init_etc(rw_lock *lock, const char *name, uint32 flags);
62b916156aSJulian Harnathvoid		__rw_lock_destroy(rw_lock *lock);
63b916156aSJulian Harnathstatus_t	__rw_lock_read_lock(rw_lock *lock);
64b916156aSJulian Harnathstatus_t	__rw_lock_read_unlock(rw_lock *lock);
65b916156aSJulian Harnathstatus_t	__rw_lock_write_lock(rw_lock *lock);
66b916156aSJulian Harnathstatus_t	__rw_lock_write_unlock(rw_lock *lock);
6793b63126SMichael Lotz
6893b9f213SIngo Weinhold
6993b9f213SIngo Weinholdtypedef struct recursive_lock {
7093b9f213SIngo Weinhold	mutex		lock;
7193b9f213SIngo Weinhold	thread_id	holder;
72f7127458SIngo Weinhold	int32		recursion;
7393b9f213SIngo Weinhold} recursive_lock;
7493b9f213SIngo Weinhold
75f7127458SIngo Weinhold#define RECURSIVE_LOCK_FLAG_CLONE_NAME		MUTEX_FLAG_CLONE_NAME
76f7127458SIngo Weinhold#define RECURSIVE_LOCK_INITIALIZER(name)	{ MUTEX_INITIALIZER(name), -1, 0 }
77f7127458SIngo Weinhold
78b916156aSJulian Harnath#define recursive_lock_init(lock, name)    __recursive_lock_init(lock, name)
79b916156aSJulian Harnath#define recursive_lock_init_etc(lock, name, flags) \
80b916156aSJulian Harnath      __recursive_lock_init_etc(lock, name, flags)
81b916156aSJulian Harnath#define recursive_lock_destroy(lock)       __recursive_lock_destroy(lock)
82b916156aSJulian Harnath#define recursive_lock_lock(lock)          __recursive_lock_lock(lock)
83b916156aSJulian Harnath#define recursive_lock_unlock(lock)        __recursive_lock_unlock(lock)
84b916156aSJulian Harnath#define recursive_lock_get_recursion(lock) __recursive_lock_get_recursion(lock)
85b916156aSJulian Harnath
86b916156aSJulian Harnathvoid		__recursive_lock_init(recursive_lock *lock, const char *name);
87b916156aSJulian Harnathvoid		__recursive_lock_init_etc(recursive_lock *lock, const char *name,
88f7127458SIngo Weinhold				uint32 flags);
89b916156aSJulian Harnathvoid		__recursive_lock_destroy(recursive_lock *lock);
90b916156aSJulian Harnathstatus_t	__recursive_lock_lock(recursive_lock *lock);
91b916156aSJulian Harnathvoid		__recursive_lock_unlock(recursive_lock *lock);
92b916156aSJulian Harnathint32		__recursive_lock_get_recursion(recursive_lock *lock);
938bef2310SIngo Weinhold
948bef2310SIngo Weinhold
95840be9d6SIngo Weinhold#define		INIT_ONCE_UNINITIALIZED	-1
96840be9d6SIngo Weinhold#define		INIT_ONCE_INITIALIZED	-4
97840be9d6SIngo Weinhold
98077c84ebSPawel Dziepakstatus_t	__init_once(int32* control, status_t (*initRoutine)(void*),
99840be9d6SIngo Weinhold				void* data);
100840be9d6SIngo Weinhold
10193b63126SMichael Lotz#ifdef __cplusplus
10293b63126SMichael Lotz} // extern "C"
10393b63126SMichael Lotz
10493b63126SMichael Lotz
10593b63126SMichael Lotz#include <AutoLocker.h>
10693b63126SMichael Lotz
10793b63126SMichael Lotzclass MutexLocking {
10893b63126SMichael Lotzpublic:
10993b63126SMichael Lotz	inline bool Lock(struct mutex *lock)
11093b63126SMichael Lotz	{
11193b63126SMichael Lotz		return mutex_lock(lock) == B_OK;
11293b63126SMichael Lotz	}
11393b63126SMichael Lotz
11493b63126SMichael Lotz	inline void Unlock(struct mutex *lock)
11593b63126SMichael Lotz	{
11693b63126SMichael Lotz		mutex_unlock(lock);
11793b63126SMichael Lotz	}
11893b63126SMichael Lotz};
11993b63126SMichael Lotz
120da31c585SAugustin Cavaliertypedef AutoLocker<mutex, MutexLocking> MutexLocker;
121da31c585SAugustin Cavalier
122da31c585SAugustin Cavalier
123da31c585SAugustin Cavalierclass RecursiveLockLocking {
124da31c585SAugustin Cavalierpublic:
125da31c585SAugustin Cavalier	inline bool Lock(recursive_lock *lockable)
126da31c585SAugustin Cavalier	{
127da31c585SAugustin Cavalier		return recursive_lock_lock(lockable) == B_OK;
128da31c585SAugustin Cavalier	}
129da31c585SAugustin Cavalier
130da31c585SAugustin Cavalier	inline void Unlock(recursive_lock *lockable)
131da31c585SAugustin Cavalier	{
132da31c585SAugustin Cavalier		recursive_lock_unlock(lockable);
133da31c585SAugustin Cavalier	}
134da31c585SAugustin Cavalier};
135da31c585SAugustin Cavalier
136da31c585SAugustin Cavaliertypedef AutoLocker<recursive_lock, RecursiveLockLocking> RecursiveLocker;
137da31c585SAugustin Cavalier
13893b63126SMichael Lotz
13993b63126SMichael Lotzclass RWLockReadLocking {
14093b63126SMichael Lotzpublic:
14193b63126SMichael Lotz	inline bool Lock(struct rw_lock *lock)
14293b63126SMichael Lotz	{
14393b63126SMichael Lotz		return rw_lock_read_lock(lock) == B_OK;
14493b63126SMichael Lotz	}
14593b63126SMichael Lotz
14693b63126SMichael Lotz	inline void Unlock(struct rw_lock *lock)
14793b63126SMichael Lotz	{
14893b63126SMichael Lotz		rw_lock_read_unlock(lock);
14993b63126SMichael Lotz	}
15093b63126SMichael Lotz};
15193b63126SMichael Lotz
15293b63126SMichael Lotz
15393b63126SMichael Lotzclass RWLockWriteLocking {
15493b63126SMichael Lotzpublic:
15593b63126SMichael Lotz	inline bool Lock(struct rw_lock *lock)
15693b63126SMichael Lotz	{
15793b63126SMichael Lotz		return rw_lock_write_lock(lock) == B_OK;
15893b63126SMichael Lotz	}
15993b63126SMichael Lotz
16093b63126SMichael Lotz	inline void Unlock(struct rw_lock *lock)
16193b63126SMichael Lotz	{
16293b63126SMichael Lotz		rw_lock_write_unlock(lock);
16393b63126SMichael Lotz	}
16493b63126SMichael Lotz};
16593b63126SMichael Lotz
16693b63126SMichael Lotz
16793b63126SMichael Lotztypedef AutoLocker<rw_lock, RWLockReadLocking> ReadLocker;
16893b63126SMichael Lotztypedef AutoLocker<rw_lock, RWLockWriteLocking> WriteLocker;
16993b63126SMichael Lotz
17093b63126SMichael Lotz#endif // __cplusplus
17193b63126SMichael Lotz
17293b63126SMichael Lotz#endif // _LOCKS_H_
173