xref: /xnu-8020.101.4/osfmk/kern/simple_lock.h (revision e7776783b89a353188416a9a346c6cdb4928faad)
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 #if INTERRUPT_MASKED_DEBUG
192 uint64_t hw_lock_compute_timeout(
193 	uint64_t in_timeout,
194 	uint64_t default_timeout,
195 	bool in_ppl,
196 	bool interruptible);
197 #else
198 uint64_t        hw_lock_compute_timeout(
199 	uint64_t in_timeout,
200 	uint64_t default_timeout);
201 #endif /* INTERRUPT_MASKED_DEBUG */
202 
203 #endif /* MACH_KERNEL_PRIVATE */
204 
205 struct usimple_lock_startup_spec {
206 	usimple_lock_t  lck;
207 	unsigned short  lck_init_arg;
208 };
209 
210 extern void                     usimple_lock_startup_init(
211 	struct usimple_lock_startup_spec *spec);
212 
213 #define SIMPLE_LOCK_DECLARE(var, arg) \
214 	decl_simple_lock_data(, var); \
215 	static __startup_data struct usimple_lock_startup_spec \
216 	__startup_usimple_lock_spec_ ## var = { &var, arg }; \
217 	STARTUP_ARG(LOCKS_EARLY, STARTUP_RANK_FOURTH, usimple_lock_startup_init, \
218 	    &__startup_usimple_lock_spec_ ## var)
219 
220 extern uint32_t                 hw_wait_while_equals32(
221 	uint32_t *address,
222 	uint32_t  current);
223 
224 extern uint64_t                 hw_wait_while_equals64(
225 	uint64_t *address,
226 	uint64_t  current);
227 
228 #if __LP64__
229 #define hw_wait_while_equals_long(ptr, cur) ({ \
230 	static_assert(sizeof(*(ptr)) == sizeof(long)); \
231 	(typeof(cur))hw_wait_while_equals64(__DEVOLATILE(uint64_t *, ptr), (uint64_t)(cur)); \
232 })
233 #else
234 #define hw_wait_while_equals_long(ptr, cur) ({ \
235 	static_assert(sizeof(*(ptr)) == sizeof(long)); \
236 	(typeof(cur))hw_wait_while_equals32(__DEVOLATILE(uint32_t *, ptr), (uint32_t)(cur)); \
237 })
238 #endif
239 
240 
241 extern void                     usimple_lock_init(
242 	usimple_lock_t,
243 	unsigned short);
244 
245 extern void                     usimple_lock(
246 	usimple_lock_t
247 	LCK_GRP_ARG(lck_grp_t*));
248 
249 extern unsigned int             usimple_lock_try(
250 	usimple_lock_t
251 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
252 
253 extern void             usimple_lock_try_lock_loop(
254 	usimple_lock_t
255 	LCK_GRP_ARG(lck_grp_t*));
256 
257 #if defined(__x86_64__)
258 extern unsigned int     usimple_lock_try_lock_mp_signal_safe_loop_deadline(
259 	usimple_lock_t,
260 	uint64_t
261 	LCK_GRP_ARG(lck_grp_t*)) /* __result_use_check */;
262 
263 extern unsigned int     usimple_lock_try_lock_mp_signal_safe_loop_duration(
264 	usimple_lock_t,
265 	uint64_t
266 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
267 #endif
268 
269 extern void                     usimple_unlock(
270 	usimple_lock_t);
271 
272 #if !LOCK_STATS
273 #define usimple_lock(lck, grp) \
274 	usimple_lock(lck)
275 
276 #define usimple_lock_try(lck, grp) \
277 	usimple_lock_try(lck)
278 
279 #define usimple_lock_try_lock_loop(lck, grp) \
280 	usimple_lock_try_lock_loop(lck)
281 
282 #if defined(__x86_64__)
283 #define usimple_lock_try_lock_mp_signal_safe_loop_deadline(lck, ddl, grp) \
284 	usimple_lock_try_lock_mp_signal_safe_loop_deadline(lck, ddl)
285 #define usimple_lock_try_lock_mp_signal_safe_loop_duration(lck, dur, grp) \
286 	usimple_lock_try_lock_mp_signal_safe_loop_duration(lck, dur)
287 #endif
288 #endif /* !LOCK_STATS */
289 
290 
291 /*
292  * If we got to here and we still don't have simple_lock_init
293  * defined, then we must either be outside the osfmk component,
294  * running on a true SMP, or need debug.
295  */
296 #if !defined(simple_lock_init)
297 #define simple_lock_init(l, t)               usimple_lock_init(l,t)
298 #define simple_lock(l, grp)                  usimple_lock(l, grp)
299 #define simple_unlock(l)                     usimple_unlock(l)
300 #define simple_lock_try(l, grp)              usimple_lock_try(l, grp)
301 #define simple_lock_try_lock_loop(l, grp)    usimple_lock_try_lock_loop(l, grp)
302 #define simple_lock_try_lock_mp_signal_safe_loop_deadline(l, ddl, grp) \
303 	usimple_lock_try_lock_mp_signal_safe_loop_deadline(l, ddl, grp)
304 #define simple_lock_try_lock_mp_signal_safe_loop_duration(l, dur, grp) \
305 	usimple_lock_try_lock_mp_signal_safe_loop_duration(l, dur, grp)
306 #define simple_lock_addr(l)     (&(l))
307 #endif /* !defined(simple_lock_init) */
308 
309 #ifdef MACH_KERNEL_PRIVATE
310 
311 typedef uint32_t hw_lock_bit_t;
312 
313 extern void     hw_lock_bit(
314 	hw_lock_bit_t *,
315 	unsigned int
316 	LCK_GRP_ARG(lck_grp_t*));
317 
318 extern void     hw_lock_bit_nopreempt(
319 	hw_lock_bit_t *,
320 	unsigned int
321 	LCK_GRP_ARG(lck_grp_t*));
322 
323 
324 extern unsigned int hw_lock_bit_try(
325 	hw_lock_bit_t *,
326 	unsigned int
327 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
328 
329 extern unsigned int hw_lock_bit_to(
330 	hw_lock_bit_t *,
331 	unsigned int,
332 	uint64_t,
333 	hw_lock_timeout_handler_t
334 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
335 
336 extern hw_lock_status_t hw_lock_bit_to_allow_invalid(
337 	hw_lock_bit_t *,
338 	unsigned int,
339 	uint64_t,
340 	hw_lock_timeout_handler_t
341 	LCK_GRP_ARG(lck_grp_t*)) __result_use_check;
342 
343 extern void     hw_unlock_bit(
344 	hw_lock_bit_t *,
345 	unsigned int);
346 
347 extern void     hw_unlock_bit_nopreempt(
348 	hw_lock_bit_t *,
349 	unsigned int);
350 
351 #define hw_lock_bit_held(l, b) \
352 	(((*(l)) & (1 << (b))) != 0)
353 
354 #if !LOCK_STATS
355 #define hw_lock_bit(lck, bit, grp) \
356 	hw_lock_bit(lck, bit)
357 
358 #define hw_lock_bit_nopreempt(lck, bit, grp) \
359 	hw_lock_bit_nopreempt(lck, bit)
360 
361 
362 #define hw_lock_bit_try(lck, bit, grp) \
363 	hw_lock_bit_try(lck, bit)
364 
365 #define hw_lock_bit_to(lck, bit, timeout, handler, grp) \
366 	hw_lock_bit_to(lck, bit, timeout, handler)
367 
368 #define hw_lock_bit_to_allow_invalid(lck, bit, timeout, handler, grp) \
369 	hw_lock_bit_to_allow_invalid(lck, bit, timeout, handler)
370 #endif /* !LOCK_STATS */
371 #endif  /* MACH_KERNEL_PRIVATE */
372 
373 __END_DECLS
374 
375 #pragma GCC visibility pop
376 
377 #endif /* XNU_KERNEL_PRIVATE */
378 #endif /*!_KERN_SIMPLE_LOCK_H_*/
379 
380 #endif  /* KERNEL_PRIVATE */
381