1/*
2 * Copyright 2008-2009, Axel D��rfler, axeld@pinc-software.de.
3 * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7#ifndef KERNEL_UTIL_AUTO_LOCKER_H
8#define KERNEL_UTIL_AUTO_LOCKER_H
9
10
11#include <KernelExport.h>
12
13#include <shared/AutoLocker.h>
14
15#include <int.h>
16#include <lock.h>
17
18
19namespace BPrivate {
20
21
22class MutexLocking {
23public:
24	inline bool Lock(mutex *lockable)
25	{
26		return mutex_lock(lockable) == B_OK;
27	}
28
29	inline void Unlock(mutex *lockable)
30	{
31		mutex_unlock(lockable);
32	}
33};
34
35typedef AutoLocker<mutex, MutexLocking> MutexLocker;
36
37
38class RecursiveLockLocking {
39public:
40	inline bool Lock(recursive_lock *lockable)
41	{
42		return recursive_lock_lock(lockable) == B_OK;
43	}
44
45	inline void Unlock(recursive_lock *lockable)
46	{
47		recursive_lock_unlock(lockable);
48	}
49};
50
51typedef AutoLocker<recursive_lock, RecursiveLockLocking> RecursiveLocker;
52
53
54class ReadWriteLockReadLocking {
55public:
56	inline bool Lock(rw_lock *lockable)
57	{
58		return rw_lock_read_lock(lockable) == B_OK;
59	}
60
61	inline void Unlock(rw_lock *lockable)
62	{
63		rw_lock_read_unlock(lockable);
64	}
65};
66
67class ReadWriteLockWriteLocking {
68public:
69	inline bool Lock(rw_lock *lockable)
70	{
71		return rw_lock_write_lock(lockable) == B_OK;
72	}
73
74	inline void Unlock(rw_lock *lockable)
75	{
76		rw_lock_write_unlock(lockable);
77	}
78};
79
80typedef AutoLocker<rw_lock, ReadWriteLockReadLocking> ReadLocker;
81typedef AutoLocker<rw_lock, ReadWriteLockWriteLocking> WriteLocker;
82
83
84class InterruptsLocking {
85public:
86	inline bool Lock(int* lockable)
87	{
88		*lockable = disable_interrupts();
89		return true;
90	}
91
92	inline void Unlock(int* lockable)
93	{
94		restore_interrupts(*lockable);
95	}
96};
97
98
99class InterruptsLocker : public AutoLocker<int, InterruptsLocking> {
100public:
101	inline InterruptsLocker(bool alreadyLocked = false,
102		bool lockIfNotLocked = true)
103		: AutoLocker<int, InterruptsLocking>(&fState, alreadyLocked,
104			lockIfNotLocked)
105	{
106	}
107
108private:
109	int	fState;
110};
111
112
113class SpinLocking {
114public:
115	inline bool Lock(spinlock* lockable)
116	{
117		acquire_spinlock(lockable);
118		return true;
119	}
120
121	inline void Unlock(spinlock* lockable)
122	{
123		release_spinlock(lockable);
124	}
125};
126
127typedef AutoLocker<spinlock, SpinLocking> SpinLocker;
128
129
130class InterruptsSpinLocking {
131public:
132// NOTE: work-around for annoying GCC 4+ "fState may be used uninitialized"
133// warning.
134#if __GNUC__ >= 4
135	InterruptsSpinLocking()
136		:
137		fState(0)
138	{
139	}
140#endif
141
142	inline bool Lock(spinlock* lockable)
143	{
144		fState = disable_interrupts();
145		acquire_spinlock(lockable);
146		return true;
147	}
148
149	inline void Unlock(spinlock* lockable)
150	{
151		release_spinlock(lockable);
152		restore_interrupts(fState);
153	}
154
155private:
156	int	fState;
157};
158
159typedef AutoLocker<spinlock, InterruptsSpinLocking> InterruptsSpinLocker;
160
161
162class ReadSpinLocking {
163public:
164	inline bool Lock(rw_spinlock* lockable)
165	{
166		acquire_read_spinlock(lockable);
167		return true;
168	}
169
170	inline void Unlock(rw_spinlock* lockable)
171	{
172		release_read_spinlock(lockable);
173	}
174};
175
176typedef AutoLocker<rw_spinlock, ReadSpinLocking> ReadSpinLocker;
177
178
179class InterruptsReadSpinLocking {
180public:
181	InterruptsReadSpinLocking()
182		:
183		fState(0)
184	{
185	}
186
187	inline bool Lock(rw_spinlock* lockable)
188	{
189		fState = disable_interrupts();
190		acquire_read_spinlock(lockable);
191		return true;
192	}
193
194	inline void Unlock(rw_spinlock* lockable)
195	{
196		release_read_spinlock(lockable);
197		restore_interrupts(fState);
198	}
199
200private:
201	int	fState;
202};
203
204typedef AutoLocker<rw_spinlock, InterruptsReadSpinLocking>
205	InterruptsReadSpinLocker;
206
207
208class WriteSpinLocking {
209public:
210	inline bool Lock(rw_spinlock* lockable)
211	{
212		acquire_write_spinlock(lockable);
213		return true;
214	}
215
216	inline void Unlock(rw_spinlock* lockable)
217	{
218		release_write_spinlock(lockable);
219	}
220};
221
222typedef AutoLocker<rw_spinlock, WriteSpinLocking> WriteSpinLocker;
223
224
225class InterruptsWriteSpinLocking {
226public:
227	InterruptsWriteSpinLocking()
228		:
229		fState(0)
230	{
231	}
232
233	inline bool Lock(rw_spinlock* lockable)
234	{
235		fState = disable_interrupts();
236		acquire_write_spinlock(lockable);
237		return true;
238	}
239
240	inline void Unlock(rw_spinlock* lockable)
241	{
242		release_write_spinlock(lockable);
243		restore_interrupts(fState);
244	}
245
246private:
247	int	fState;
248};
249
250typedef AutoLocker<rw_spinlock, InterruptsWriteSpinLocking>
251	InterruptsWriteSpinLocker;
252
253
254class WriteSequentialLocking {
255public:
256	inline bool Lock(seqlock* lockable)
257	{
258		acquire_write_seqlock(lockable);
259		return true;
260	}
261
262	inline void Unlock(seqlock* lockable)
263	{
264		release_write_seqlock(lockable);
265	}
266};
267
268typedef AutoLocker<seqlock, WriteSequentialLocking> WriteSequentialLocker;
269
270
271class InterruptsWriteSequentialLocking {
272public:
273	InterruptsWriteSequentialLocking()
274		:
275		fState(0)
276	{
277	}
278
279	inline bool Lock(seqlock* lockable)
280	{
281		fState = disable_interrupts();
282		acquire_write_seqlock(lockable);
283		return true;
284	}
285
286	inline void Unlock(seqlock* lockable)
287	{
288		release_write_seqlock(lockable);
289		restore_interrupts(fState);
290	}
291
292private:
293	int	fState;
294};
295
296typedef AutoLocker<seqlock, InterruptsWriteSequentialLocking>
297	InterruptsWriteSequentialLocker;
298
299
300}	// namespace BPrivate
301
302using BPrivate::AutoLocker;
303using BPrivate::MutexLocker;
304using BPrivate::RecursiveLocker;
305using BPrivate::ReadLocker;
306using BPrivate::WriteLocker;
307using BPrivate::InterruptsLocker;
308using BPrivate::SpinLocker;
309using BPrivate::InterruptsSpinLocker;
310using BPrivate::ReadSpinLocker;
311using BPrivate::InterruptsReadSpinLocker;
312using BPrivate::WriteSpinLocker;
313using BPrivate::InterruptsWriteSpinLocker;
314using BPrivate::WriteSequentialLocker;
315using BPrivate::InterruptsWriteSequentialLocker;
316
317
318#endif	// KERNEL_UTIL_AUTO_LOCKER_H
319