1/*
2 * Copyright (c) 2003-2007 Apple 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#ifndef _KERN_LOCKS_H_
30#define _KERN_LOCKS_H_
31
32#include	<sys/cdefs.h>
33#include	<sys/appleapiopts.h>
34#include	<mach/boolean.h>
35#include	<mach/mach_types.h>
36#include	<kern/kern_types.h>
37#include	<machine/locks.h>
38
39#ifdef	MACH_KERNEL_PRIVATE
40#include	<kern/queue.h>
41
42extern void				lck_mod_init(
43								void) __attribute__((section("__TEXT, initcode")));
44
45typedef	unsigned int	lck_type_t;
46
47#define	LCK_TYPE_SPIN	1
48#define	LCK_TYPE_MTX	2
49#define	LCK_TYPE_RW	3
50
51#endif
52
53typedef	unsigned int		lck_sleep_action_t;
54
55#define	LCK_SLEEP_DEFAULT	0x00	/* Release the lock while waiting for the event, then reclaim */
56									/* RW locks are returned in the same mode */
57#define	LCK_SLEEP_UNLOCK	0x01	/* Release the lock and return unheld */
58#define	LCK_SLEEP_SHARED	0x02	/* Reclaim the lock in shared mode (RW only) */
59#define	LCK_SLEEP_EXCLUSIVE	0x04	/* Reclaim the lock in exclusive mode (RW only) */
60#define	LCK_SLEEP_SPIN		0x08	/* Reclaim the lock in spin mode (mutex only) */
61
62#define	LCK_SLEEP_MASK		0x0f	/* Valid actions */
63
64#ifdef	MACH_KERNEL_PRIVATE
65
66typedef struct {
67	uint64_t			lck_grp_spin_util_cnt;
68	uint64_t			lck_grp_spin_held_cnt;
69	uint64_t			lck_grp_spin_miss_cnt;
70	uint64_t			lck_grp_spin_held_max;
71	uint64_t			lck_grp_spin_held_cum;
72} lck_grp_spin_stat_t;
73
74typedef struct {
75	uint64_t			lck_grp_mtx_util_cnt;
76	/* On x86, this is used as the "direct wait" count */
77	uint64_t			lck_grp_mtx_held_cnt;
78	uint64_t			lck_grp_mtx_miss_cnt;
79	uint64_t			lck_grp_mtx_wait_cnt;
80	/* Rest currently unused */
81	uint64_t			lck_grp_mtx_held_max;
82	uint64_t			lck_grp_mtx_held_cum;
83	uint64_t			lck_grp_mtx_wait_max;
84	uint64_t			lck_grp_mtx_wait_cum;
85} lck_grp_mtx_stat_t;
86
87typedef struct {
88	uint64_t			lck_grp_rw_util_cnt;
89	uint64_t			lck_grp_rw_held_cnt;
90	uint64_t			lck_grp_rw_miss_cnt;
91	uint64_t			lck_grp_rw_wait_cnt;
92	uint64_t			lck_grp_rw_held_max;
93	uint64_t			lck_grp_rw_held_cum;
94	uint64_t			lck_grp_rw_wait_max;
95	uint64_t			lck_grp_rw_wait_cum;
96} lck_grp_rw_stat_t;
97
98typedef	struct _lck_grp_stat_ {
99	lck_grp_spin_stat_t	lck_grp_spin_stat;
100	lck_grp_mtx_stat_t	lck_grp_mtx_stat;
101	lck_grp_rw_stat_t	lck_grp_rw_stat;
102} lck_grp_stat_t;
103
104#define	LCK_GRP_MAX_NAME	64
105
106typedef	struct _lck_grp_ {
107	queue_chain_t		lck_grp_link;
108	uint32_t		lck_grp_refcnt;
109	uint32_t		lck_grp_spincnt;
110	uint32_t		lck_grp_mtxcnt;
111	uint32_t		lck_grp_rwcnt;
112	uint32_t		lck_grp_attr;
113	char			lck_grp_name[LCK_GRP_MAX_NAME];
114	lck_grp_stat_t		lck_grp_stat;
115} lck_grp_t;
116
117#define LCK_GRP_NULL	(lck_grp_t *)0
118
119#else
120typedef struct __lck_grp__ lck_grp_t;
121#endif
122
123#ifdef	MACH_KERNEL_PRIVATE
124typedef	struct _lck_grp_attr_ {
125	uint32_t	grp_attr_val;
126} lck_grp_attr_t;
127
128extern lck_grp_attr_t  LockDefaultGroupAttr;
129
130#define LCK_GRP_ATTR_STAT	0x1
131
132#else
133typedef struct __lck_grp_attr__ lck_grp_attr_t;
134#endif
135
136#define LCK_GRP_ATTR_NULL	(lck_grp_attr_t *)0
137
138__BEGIN_DECLS
139
140extern	lck_grp_attr_t	*lck_grp_attr_alloc_init(
141									void);
142
143extern	void			lck_grp_attr_setdefault(
144									lck_grp_attr_t	*attr);
145
146extern	void			lck_grp_attr_setstat(
147									lck_grp_attr_t  *attr);
148
149extern	void			lck_grp_attr_free(
150									lck_grp_attr_t	*attr);
151
152extern	lck_grp_t		*lck_grp_alloc_init(
153									const char*		grp_name,
154									lck_grp_attr_t	*attr);
155
156__END_DECLS
157
158#ifdef	MACH_KERNEL_PRIVATE
159extern	void			lck_grp_init(
160									lck_grp_t		*grp,
161									const char*		grp_name,
162									lck_grp_attr_t	*attr);
163
164extern	void			lck_grp_reference(
165									lck_grp_t		*grp);
166
167extern	void			lck_grp_deallocate(
168									lck_grp_t		 *grp);
169
170extern	void			lck_grp_lckcnt_incr(
171									lck_grp_t		*grp,
172									lck_type_t		lck_type);
173
174extern	void			lck_grp_lckcnt_decr(
175									lck_grp_t		*grp,
176									lck_type_t		lck_type);
177#endif
178
179__BEGIN_DECLS
180
181extern void				lck_grp_free(
182									lck_grp_t		*grp);
183
184__END_DECLS
185
186#ifdef	MACH_KERNEL_PRIVATE
187typedef	struct _lck_attr_ {
188	unsigned int	lck_attr_val;
189} lck_attr_t;
190
191extern lck_attr_t      LockDefaultLckAttr;
192
193#define LCK_ATTR_NONE		0
194
195#define	LCK_ATTR_DEBUG				0x00000001
196#define	LCK_ATTR_RW_SHARED_PRIORITY	0x00010000
197
198#else
199typedef struct __lck_attr__ lck_attr_t;
200#endif
201
202#define LCK_ATTR_NULL (lck_attr_t *)0
203
204__BEGIN_DECLS
205
206extern	lck_attr_t		*lck_attr_alloc_init(
207									void);
208
209extern	void			lck_attr_setdefault(
210									lck_attr_t		*attr);
211
212extern	void			lck_attr_setdebug(
213									lck_attr_t		*attr);
214
215extern	void			lck_attr_cleardebug(
216									lck_attr_t		*attr);
217
218#ifdef	XNU_KERNEL_PRIVATE
219extern	void			lck_attr_rw_shared_priority(
220									lck_attr_t		*attr);
221#endif
222
223extern	void			lck_attr_free(
224									lck_attr_t		*attr);
225
226#define decl_lck_spin_data(class,name)     class lck_spin_t name;
227
228extern lck_spin_t		*lck_spin_alloc_init(
229									lck_grp_t		*grp,
230									lck_attr_t		*attr);
231
232extern void				lck_spin_init(
233									lck_spin_t		*lck,
234									lck_grp_t		*grp,
235									lck_attr_t		*attr);
236
237extern void				lck_spin_lock(
238									lck_spin_t		*lck);
239
240extern void				lck_spin_unlock(
241									lck_spin_t		*lck);
242
243extern void				lck_spin_destroy(
244									lck_spin_t		*lck,
245									lck_grp_t		*grp);
246
247extern void				lck_spin_free(
248									lck_spin_t		*lck,
249									lck_grp_t		*grp);
250
251extern wait_result_t	lck_spin_sleep(
252									lck_spin_t			*lck,
253									lck_sleep_action_t	lck_sleep_action,
254									event_t				event,
255									wait_interrupt_t	interruptible);
256
257extern wait_result_t	lck_spin_sleep_deadline(
258									lck_spin_t			*lck,
259									lck_sleep_action_t	lck_sleep_action,
260									event_t				event,
261									wait_interrupt_t	interruptible,
262									uint64_t			deadline);
263
264#ifdef	KERNEL_PRIVATE
265
266extern boolean_t		lck_spin_try_lock(
267									lck_spin_t		*lck);
268
269struct _lck_mtx_ext_;
270extern void lck_mtx_init_ext(lck_mtx_t *lck, struct _lck_mtx_ext_ *lck_ext,
271    lck_grp_t *grp, lck_attr_t *attr);
272
273#endif
274
275
276#define decl_lck_mtx_data(class,name)     class lck_mtx_t name;
277
278extern lck_mtx_t		*lck_mtx_alloc_init(
279									lck_grp_t		*grp,
280									lck_attr_t		*attr);
281
282extern void				lck_mtx_init(
283									lck_mtx_t		*lck,
284									lck_grp_t		*grp,
285									lck_attr_t		*attr);
286extern void				lck_mtx_lock(
287									lck_mtx_t		*lck);
288
289#if	defined(__i386__)
290extern void	lck_mtx_unlock(lck_mtx_t		*lck) __DARWIN10_ALIAS(lck_mtx_unlock);
291#else
292extern void				lck_mtx_unlock(
293									lck_mtx_t		*lck);
294#endif	/* __i386__ */
295
296extern void				lck_mtx_destroy(
297									lck_mtx_t		*lck,
298									lck_grp_t		*grp);
299
300extern void				lck_mtx_free(
301									lck_mtx_t		*lck,
302									lck_grp_t		*grp);
303
304extern wait_result_t	lck_mtx_sleep(
305									lck_mtx_t			*lck,
306									lck_sleep_action_t	lck_sleep_action,
307									event_t				event,
308									wait_interrupt_t	interruptible);
309
310extern wait_result_t	lck_mtx_sleep_deadline(
311									lck_mtx_t			*lck,
312									lck_sleep_action_t	lck_sleep_action,
313									event_t				event,
314									wait_interrupt_t	interruptible,
315									uint64_t			deadline);
316
317#ifdef	KERNEL_PRIVATE
318
319extern boolean_t		lck_mtx_try_lock(
320									lck_mtx_t		*lck);
321
322extern void				mutex_pause(uint32_t);
323
324extern void 			lck_mtx_yield (
325									lck_mtx_t		*lck);
326
327#if defined(__i386__) || defined(__x86_64__)
328extern boolean_t		lck_mtx_try_lock_spin(
329									lck_mtx_t		*lck);
330
331extern void			lck_mtx_lock_spin_always(
332									lck_mtx_t		*lck);
333
334extern void			lck_mtx_lock_spin(
335									lck_mtx_t		*lck);
336
337extern void			lck_mtx_convert_spin(
338									lck_mtx_t		*lck);
339
340#define lck_mtx_unlock_always(l)	lck_mtx_unlock(l)
341
342#else
343#define lck_mtx_try_lock_spin(l)	lck_mtx_try_lock(l)
344#define	lck_mtx_lock_spin(l)		lck_mtx_lock(l)
345#define lck_mtx_lock_spin_always(l)	lck_spin_lock(l)
346#define lck_mtx_unlock_always(l)	lck_spin_unlock(l)
347#define	lck_mtx_convert_spin(l)		do {} while (0)
348#endif
349
350#endif	/* KERNEL_PRIVATE */
351
352extern void				lck_mtx_assert(
353									lck_mtx_t		*lck,
354									unsigned int	type);
355
356__END_DECLS
357
358#define	LCK_MTX_ASSERT_OWNED	0x01
359#define	LCK_MTX_ASSERT_NOTOWNED	0x02
360
361#ifdef	MACH_KERNEL_PRIVATE
362extern void				lck_mtx_lock_wait(
363									lck_mtx_t		*lck,
364									thread_t		holder);
365
366extern int				lck_mtx_lock_acquire(
367									lck_mtx_t		*lck);
368
369extern void				lck_mtx_unlock_wakeup(
370									lck_mtx_t		*lck,
371									thread_t		holder);
372extern void				lck_mtx_unlockspin_wakeup(
373							                lck_mtx_t		*lck);
374
375extern boolean_t		lck_mtx_ilk_unlock(
376									lck_mtx_t		*lck);
377
378#endif
379
380#define decl_lck_rw_data(class,name)     class lck_rw_t name;
381
382typedef unsigned int	 lck_rw_type_t;
383
384#define	LCK_RW_TYPE_SHARED			0x01
385#define	LCK_RW_TYPE_EXCLUSIVE		0x02
386
387#ifdef XNU_KERNEL_PRIVATE
388#define LCK_RW_ASSERT_SHARED	0x01
389#define LCK_RW_ASSERT_EXCLUSIVE	0x02
390#define LCK_RW_ASSERT_HELD	(LCK_RW_ASSERT_SHARED | LCK_RW_ASSERT_EXCLUSIVE)
391#endif
392
393__BEGIN_DECLS
394
395extern lck_rw_t			*lck_rw_alloc_init(
396									lck_grp_t		*grp,
397									lck_attr_t		*attr);
398
399extern void				lck_rw_init(
400									lck_rw_t		*lck,
401									lck_grp_t		*grp,
402									lck_attr_t		*attr);
403
404extern void				lck_rw_lock(
405									lck_rw_t		*lck,
406									lck_rw_type_t	lck_rw_type);
407
408extern void				lck_rw_unlock(
409									lck_rw_t		*lck,
410									lck_rw_type_t	lck_rw_type);
411
412extern void				lck_rw_lock_shared(
413									lck_rw_t		*lck);
414
415extern void				lck_rw_unlock_shared(
416									lck_rw_t		*lck);
417
418extern void				lck_rw_lock_exclusive(
419									lck_rw_t		*lck);
420
421extern void				lck_rw_unlock_exclusive(
422									lck_rw_t		*lck);
423
424#ifdef	XNU_KERNEL_PRIVATE
425/*
426 * CAUTION
427 * read-write locks do not have a concept of ownership, so lck_rw_assert()
428 * merely asserts that someone is holding the lock, not necessarily the caller.
429 */
430extern void				lck_rw_assert(
431									lck_rw_t		*lck,
432									unsigned int		type);
433#endif
434
435#ifdef	KERNEL_PRIVATE
436
437extern lck_rw_type_t	lck_rw_done(
438									lck_rw_t		*lck);
439#endif
440
441extern void				lck_rw_destroy(
442									lck_rw_t		*lck,
443									lck_grp_t		*grp);
444
445extern void				lck_rw_free(
446									lck_rw_t		*lck,
447									lck_grp_t		*grp);
448
449extern wait_result_t	lck_rw_sleep(
450									lck_rw_t			*lck,
451									lck_sleep_action_t	lck_sleep_action,
452									event_t				event,
453									wait_interrupt_t	interruptible);
454
455extern wait_result_t	lck_rw_sleep_deadline(
456									lck_rw_t			*lck,
457									lck_sleep_action_t	lck_sleep_action,
458									event_t				event,
459									wait_interrupt_t	interruptible,
460									uint64_t			deadline);
461
462extern boolean_t		lck_rw_lock_shared_to_exclusive(
463									lck_rw_t		*lck);
464
465extern void				lck_rw_lock_exclusive_to_shared(
466									lck_rw_t		*lck);
467
468extern boolean_t		lck_rw_try_lock(
469									lck_rw_t		*lck,
470									lck_rw_type_t	lck_rw_type);
471
472#ifdef	KERNEL_PRIVATE
473
474extern boolean_t		lck_rw_try_lock_shared(
475									lck_rw_t		*lck);
476
477extern boolean_t		lck_rw_try_lock_exclusive(
478									lck_rw_t		*lck);
479#endif
480
481__END_DECLS
482
483#endif /* _KERN_LOCKS_H_ */
484