xref: /xnu-8019.80.24/osfmk/kern/simple_lock.h (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*
2  * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * Copyright (C) 1998 Apple Computer
30  * All Rights Reserved
31  */
32 /*
33  * @OSF_COPYRIGHT@
34  */
35 /*
36  * Mach Operating System
37  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
38  * All Rights Reserved.
39  *
40  * Permission to use, copy, modify and distribute this software and its
41  * documentation is hereby granted, provided that both the copyright
42  * notice and this permission notice appear in all copies of the
43  * software, derivative works or modified versions, and any portions
44  * thereof, and that both notices appear in supporting documentation.
45  *
46  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
48  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49  *
50  * Carnegie Mellon requests users of this software to return to
51  *
52  *  Software Distribution Coordinator  or  [email protected]
53  *  School of Computer Science
54  *  Carnegie Mellon University
55  *  Pittsburgh PA 15213-3890
56  *
57  * any improvements or extensions that they make and grant Carnegie Mellon
58  * the rights to redistribute these changes.
59  */
60 /*
61  *	File:	kern/simple_lock.h (derived from kern/lock.h)
62  *	Author:	Avadis Tevanian, Jr., Michael Wayne Young
63  *	Date:	1985
64  *
65  *	Atomic primitives and Simple Locking primitives definitions
66  */
67 
68 #ifdef  KERNEL_PRIVATE
69 
70 #ifndef _KERN_SIMPLE_LOCK_H_
71 #define _KERN_SIMPLE_LOCK_H_
72 
73 #include <mach/boolean.h>
74 #include <kern/lock_types.h>
75 #include <kern/lock_group.h>
76 #include <machine/simple_lock.h>
77 
78 #ifdef XNU_KERNEL_PRIVATE
79 
80 #if MACH_KERNEL_PRIVATE
81 #include <machine/atomic.h>
82 #include <mach_ldebug.h>
83 #endif
84 
85 __BEGIN_DECLS
86 
87 #pragma GCC visibility push(hidden)
88 
89 #ifdef MACH_KERNEL_PRIVATE
90 extern void                     hw_lock_init(
91 	hw_lock_t);
92 
93 extern void                     hw_lock_lock(
94 	hw_lock_t
95 	LCK_GRP_ARG(lck_grp_t*));
96 
97 extern void                     hw_lock_lock_nopreempt(
98 	hw_lock_t
99 	LCK_GRP_ARG(lck_grp_t*));
100 
101 extern unsigned int             hw_lock_to(
102 	hw_lock_t,
103 	uint64_t,
104 	hw_lock_timeout_handler_t
105 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
106 
107 extern unsigned int             hw_lock_to_nopreempt(
108 	hw_lock_t,
109 	uint64_t,
110 	hw_lock_timeout_handler_t
111 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
112 
113 extern unsigned int             hw_lock_try(
114 	hw_lock_t
115 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
116 
117 extern unsigned int             hw_lock_try_nopreempt(
118 	hw_lock_t
119 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
120 
121 #if !LOCK_STATS
122 #define hw_lock_lock(lck, grp) \
123 	hw_lock_lock(lck)
124 
125 #define hw_lock_lock_nopreempt(lck, grp) \
126 	hw_lock_lock_nopreempt(lck)
127 
128 #define hw_lock_to(lck, timeout, handler, grp) \
129 	hw_lock_to(lck, timeout, handler)
130 
131 #define hw_lock_to_nopreempt(lck, timeout, handler, grp) \
132 	hw_lock_to_nopreempt(lck, timeout, handler)
133 
134 #define hw_lock_try(lck, grp) \
135 	hw_lock_try(lck)
136 
137 #define hw_lock_try_nopreempt(lck, grp) \
138 	hw_lock_try_nopreempt(lck)
139 #endif /* !LOCK_STATS */
140 
141 extern void                     hw_lock_unlock(
142 	hw_lock_t);
143 
144 extern void                     hw_lock_unlock_nopreempt(
145 	hw_lock_t);
146 
147 extern unsigned int             hw_lock_held(
148 	hw_lock_t) __result_use_check;
149 
150 extern boolean_t                hw_atomic_test_and_set32(
151 	uint32_t *target,
152 	uint32_t test_mask,
153 	uint32_t set_mask,
154 	enum memory_order ord,
155 	boolean_t wait);
156 
157 extern boolean_t                atomic_test_and_set32(
158 	uint32_t *target,
159 	uint32_t test_mask,
160 	uint32_t set_mask,
161 	enum memory_order ord,
162 	boolean_t wait);
163 
164 extern void                     atomic_exchange_abort(
165 	void);
166 
167 extern boolean_t                atomic_exchange_complete32(
168 	uint32_t *target,
169 	uint32_t previous,
170 	uint32_t newval,
171 	enum memory_order ord);
172 
173 extern uint32_t                 atomic_exchange_begin32(
174 	uint32_t *target,
175 	uint32_t *previous,
176 	enum memory_order ord);
177 
178 #if defined(__arm__) || defined(__arm64__)
179 uint32_t                        load_exclusive32(
180 	uint32_t *target,
181 	enum memory_order ord);
182 boolean_t                       store_exclusive32(
183 	uint32_t *target,
184 	uint32_t value,
185 	enum memory_order ord);
186 #endif /* defined(__arm__)||defined(__arm64__) */
187 
188 extern void                     usimple_unlock_nopreempt(
189 	usimple_lock_t);
190 
191 #endif /* MACH_KERNEL_PRIVATE */
192 
193 struct usimple_lock_startup_spec {
194 	usimple_lock_t  lck;
195 	unsigned short  lck_init_arg;
196 };
197 
198 extern void                     usimple_lock_startup_init(
199 	struct usimple_lock_startup_spec *spec);
200 
201 #define SIMPLE_LOCK_DECLARE(var, arg) \
202 	decl_simple_lock_data(, var); \
203 	static __startup_data struct usimple_lock_startup_spec \
204 	__startup_usimple_lock_spec_ ## var = { &var, arg }; \
205 	STARTUP_ARG(LOCKS_EARLY, STARTUP_RANK_FOURTH, usimple_lock_startup_init, \
206 	    &__startup_usimple_lock_spec_ ## var)
207 
208 extern void *                   hw_wait_while_equals(
209 	void    **address,
210 	void    *current);
211 
212 extern void                     usimple_lock_init(
213 	usimple_lock_t,
214 	unsigned short);
215 
216 extern void                     usimple_lock(
217 	usimple_lock_t
218 	LCK_GRP_ARG(lck_grp_t*));
219 
220 extern unsigned int             usimple_lock_try(
221 	usimple_lock_t
222 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
223 
224 extern void             usimple_lock_try_lock_loop(
225 	usimple_lock_t
226 	LCK_GRP_ARG(lck_grp_t*));
227 
228 #if defined(__x86_64__)
229 extern unsigned int     usimple_lock_try_lock_mp_signal_safe_loop_deadline(
230 	usimple_lock_t,
231 	uint64_t
232 	LCK_GRP_ARG(lck_grp_t*)) /* __result_use_check */;
233 
234 extern unsigned int     usimple_lock_try_lock_mp_signal_safe_loop_duration(
235 	usimple_lock_t,
236 	uint64_t
237 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
238 #endif
239 
240 extern void                     usimple_unlock(
241 	usimple_lock_t);
242 
243 #if !LOCK_STATS
244 #define usimple_lock(lck, grp) \
245 	usimple_lock(lck)
246 
247 #define usimple_lock_try(lck, grp) \
248 	usimple_lock_try(lck)
249 
250 #define usimple_lock_try_lock_loop(lck, grp) \
251 	usimple_lock_try_lock_loop(lck)
252 
253 #if defined(__x86_64__)
254 #define usimple_lock_try_lock_mp_signal_safe_loop_deadline(lck, ddl, grp) \
255 	usimple_lock_try_lock_mp_signal_safe_loop_deadline(lck, ddl)
256 #define usimple_lock_try_lock_mp_signal_safe_loop_duration(lck, dur, grp) \
257 	usimple_lock_try_lock_mp_signal_safe_loop_duration(lck, dur)
258 #endif
259 #endif /* !LOCK_STATS */
260 
261 
262 /*
263  * If we got to here and we still don't have simple_lock_init
264  * defined, then we must either be outside the osfmk component,
265  * running on a true SMP, or need debug.
266  */
267 #if !defined(simple_lock_init)
268 #define simple_lock_init(l, t)               usimple_lock_init(l,t)
269 #define simple_lock(l, grp)                  usimple_lock(l, grp)
270 #define simple_unlock(l)                     usimple_unlock(l)
271 #define simple_lock_try(l, grp)              usimple_lock_try(l, grp)
272 #define simple_lock_try_lock_loop(l, grp)    usimple_lock_try_lock_loop(l, grp)
273 #define simple_lock_try_lock_mp_signal_safe_loop_deadline(l, ddl, grp) \
274 	usimple_lock_try_lock_mp_signal_safe_loop_deadline(l, ddl, grp)
275 #define simple_lock_try_lock_mp_signal_safe_loop_duration(l, dur, grp) \
276 	usimple_lock_try_lock_mp_signal_safe_loop_duration(l, dur, grp)
277 #define simple_lock_addr(l)     (&(l))
278 #endif /* !defined(simple_lock_init) */
279 
280 #ifdef MACH_KERNEL_PRIVATE
281 
282 typedef uint32_t hw_lock_bit_t;
283 
284 extern void     hw_lock_bit(
285 	hw_lock_bit_t *,
286 	unsigned int
287 	LCK_GRP_ARG(lck_grp_t*));
288 
289 extern void     hw_lock_bit_nopreempt(
290 	hw_lock_bit_t *,
291 	unsigned int
292 	LCK_GRP_ARG(lck_grp_t*));
293 
294 
295 extern unsigned int hw_lock_bit_try(
296 	hw_lock_bit_t *,
297 	unsigned int
298 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
299 
300 extern unsigned int hw_lock_bit_to(
301 	hw_lock_bit_t *,
302 	unsigned int,
303 	uint64_t,
304 	hw_lock_timeout_handler_t
305 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
306 
307 extern hw_lock_status_t hw_lock_bit_to_allow_invalid(
308 	hw_lock_bit_t *,
309 	unsigned int,
310 	uint64_t,
311 	hw_lock_timeout_handler_t
312 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
313 
314 extern void     hw_unlock_bit(
315 	hw_lock_bit_t *,
316 	unsigned int);
317 
318 extern void     hw_unlock_bit_nopreempt(
319 	hw_lock_bit_t *,
320 	unsigned int);
321 
322 #define hw_lock_bit_held(l, b) \
323 	(((*(l)) & (1 << (b))) != 0)
324 
325 #if !LOCK_STATS
326 #define hw_lock_bit(lck, bit, grp) \
327 	hw_lock_bit(lck, bit)
328 
329 #define hw_lock_bit_nopreempt(lck, bit, grp) \
330 	hw_lock_bit_nopreempt(lck, bit)
331 
332 
333 #define hw_lock_bit_try(lck, bit, grp) \
334 	hw_lock_bit_try(lck, bit)
335 
336 #define hw_lock_bit_to(lck, bit, timeout, handler, grp) \
337 	hw_lock_bit_to(lck, bit, timeout, handler)
338 
339 #define hw_lock_bit_to_allow_invalid(lck, bit, timeout, handler, grp) \
340 	hw_lock_bit_to_allow_invalid(lck, bit, timeout, handler)
341 #endif /* !LOCK_STATS */
342 #endif  /* MACH_KERNEL_PRIVATE */
343 
344 __END_DECLS
345 
346 #pragma GCC visibility pop
347 
348 #endif /* XNU_KERNEL_PRIVATE */
349 #endif /*!_KERN_SIMPLE_LOCK_H_*/
350 
351 #endif  /* KERNEL_PRIVATE */
352