xref: /haiku/headers/private/kernel/util/AutoLock.h (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
1 /*
2  * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2005-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
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 #include <thread.h>
18 
19 
20 namespace BPrivate {
21 
22 
23 class MutexLocking {
24 public:
25 	inline bool Lock(mutex *lockable)
26 	{
27 		return mutex_lock(lockable) == B_OK;
28 	}
29 
30 	inline void Unlock(mutex *lockable)
31 	{
32 		mutex_unlock(lockable);
33 	}
34 };
35 
36 typedef AutoLocker<mutex, MutexLocking> MutexLocker;
37 
38 
39 class RecursiveLockLocking {
40 public:
41 	inline bool Lock(recursive_lock *lockable)
42 	{
43 		return recursive_lock_lock(lockable) == B_OK;
44 	}
45 
46 	inline void Unlock(recursive_lock *lockable)
47 	{
48 		recursive_lock_unlock(lockable);
49 	}
50 };
51 
52 typedef AutoLocker<recursive_lock, RecursiveLockLocking> RecursiveLocker;
53 
54 
55 class ReadWriteLockReadLocking {
56 public:
57 	inline bool Lock(rw_lock *lockable)
58 	{
59 		return rw_lock_read_lock(lockable) == B_OK;
60 	}
61 
62 	inline void Unlock(rw_lock *lockable)
63 	{
64 		rw_lock_read_unlock(lockable);
65 	}
66 };
67 
68 class ReadWriteLockWriteLocking {
69 public:
70 	inline bool Lock(rw_lock *lockable)
71 	{
72 		return rw_lock_write_lock(lockable) == B_OK;
73 	}
74 
75 	inline void Unlock(rw_lock *lockable)
76 	{
77 		rw_lock_write_unlock(lockable);
78 	}
79 };
80 
81 typedef AutoLocker<rw_lock, ReadWriteLockReadLocking> ReadLocker;
82 typedef AutoLocker<rw_lock, ReadWriteLockWriteLocking> WriteLocker;
83 
84 
85 class InterruptsLocking {
86 public:
87 	inline bool Lock(int* lockable)
88 	{
89 		*lockable = disable_interrupts();
90 		return true;
91 	}
92 
93 	inline void Unlock(int* lockable)
94 	{
95 		restore_interrupts(*lockable);
96 	}
97 };
98 
99 
100 class InterruptsLocker : public AutoLocker<int, InterruptsLocking> {
101 public:
102 	inline InterruptsLocker(bool alreadyLocked = false,
103 		bool lockIfNotLocked = true)
104 		: AutoLocker<int, InterruptsLocking>(&fState, alreadyLocked,
105 			lockIfNotLocked)
106 	{
107 	}
108 
109 private:
110 	int	fState;
111 };
112 
113 
114 class SpinLocking {
115 public:
116 	inline bool Lock(spinlock* lockable)
117 	{
118 		acquire_spinlock(lockable);
119 		return true;
120 	}
121 
122 	inline void Unlock(spinlock* lockable)
123 	{
124 		release_spinlock(lockable);
125 	}
126 };
127 
128 typedef AutoLocker<spinlock, SpinLocking> SpinLocker;
129 
130 
131 class InterruptsSpinLocking {
132 public:
133 // NOTE: work-around for annoying GCC 4 "fState may be used uninitialized"
134 // warning.
135 #if __GNUC__ == 4
136 	InterruptsSpinLocking()
137 		:
138 		fState(0)
139 	{
140 	}
141 #endif
142 
143 	inline bool Lock(spinlock* lockable)
144 	{
145 		fState = disable_interrupts();
146 		acquire_spinlock(lockable);
147 		return true;
148 	}
149 
150 	inline void Unlock(spinlock* lockable)
151 	{
152 		release_spinlock(lockable);
153 		restore_interrupts(fState);
154 	}
155 
156 private:
157 	int	fState;
158 };
159 
160 typedef AutoLocker<spinlock, InterruptsSpinLocking> InterruptsSpinLocker;
161 
162 
163 class ThreadCPUPinLocking {
164 public:
165 	inline bool Lock(struct thread* thread)
166 	{
167 		thread_pin_to_current_cpu(thread);
168 		return true;
169 	}
170 
171 	inline void Unlock(struct thread* thread)
172 	{
173 		thread_unpin_from_current_cpu(thread);
174 	}
175 };
176 
177 typedef AutoLocker<struct thread, ThreadCPUPinLocking> ThreadCPUPinner;
178 
179 
180 }	// namespace BPrivate
181 
182 using BPrivate::AutoLocker;
183 using BPrivate::MutexLocker;
184 using BPrivate::RecursiveLocker;
185 using BPrivate::ReadLocker;
186 using BPrivate::WriteLocker;
187 using BPrivate::InterruptsLocker;
188 using BPrivate::SpinLocker;
189 using BPrivate::InterruptsSpinLocker;
190 using BPrivate::ThreadCPUPinner;
191 
192 #endif	// KERNEL_UTIL_AUTO_LOCKER_H
193