1/*
2 * Copyright (c) 2004-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	_ARM_LOCKS_H_
30#define	_ARM_LOCKS_H_
31
32#include <sys/appleapiopts.h>
33#include <kern/kern_types.h>
34
35#ifdef	MACH_KERNEL_PRIVATE
36
37#include <ARM/hw_lock_types.h>
38
39extern	unsigned int	LcksOpts;
40
41#define enaLkDeb		0x00000001	/* Request debug in default attribute */
42#define enaLkStat		0x00000002	/* Request statistic in default attribute */
43
44#endif
45
46#ifdef	MACH_KERNEL_PRIVATE
47typedef struct {
48	unsigned long	interlock;
49	unsigned long	lck_spin_pad[9];	/* XXX - usimple_lock_data_t */
50} lck_spin_t;
51
52#define	LCK_SPIN_TAG_DESTROYED		0x00002007	/* lock marked as Destroyed */
53
54#else
55#ifdef	KERNEL_PRIVATE
56typedef struct {
57	unsigned long    opaque[10];
58} lck_spin_t;
59#else
60typedef	struct __lck_spin_t__	lck_spin_t;
61#endif
62#endif
63
64#ifdef	MACH_KERNEL_PRIVATE
65typedef struct _lck_mtx_ {
66	union {
67		struct {
68			volatile uintptr_t		lck_mtxd_owner;
69			unsigned long			lck_mtxd_ptr;
70			volatile uint32_t		lck_mtxd_waiters:16,
71				                        lck_mtxd_pri:8,
72			                                lck_mtxd_ilocked:1,
73			                                lck_mtxd_mlocked:1,
74			                                lck_mtxd_promoted:1,
75				                        lck_mtxd_spin:1,
76				                        lck_mtxd_pad4:4; 	/* padding */
77#ifdef __x86_64__
78			unsigned int			lck_mtxd_pad;
79#endif
80		} lck_mtxd;
81		struct {
82			unsigned long			lck_mtxi_tag;
83			struct _lck_mtx_ext_		*lck_mtxi_ptr;
84			unsigned long			lck_mtxi_pad;
85		} lck_mtxi;
86	} lck_mtx_sw;
87} lck_mtx_t;
88
89#define	lck_mtx_owner	lck_mtx_sw.lck_mtxd.lck_mtxd_owner
90#define	lck_mtx_waiters	lck_mtx_sw.lck_mtxd.lck_mtxd_waiters
91#define	lck_mtx_pri	lck_mtx_sw.lck_mtxd.lck_mtxd_pri
92#define	lck_mtx_ilocked	lck_mtx_sw.lck_mtxd.lck_mtxd_ilocked
93#define	lck_mtx_mlocked	lck_mtx_sw.lck_mtxd.lck_mtxd_mlocked
94#define	lck_mtx_promoted lck_mtx_sw.lck_mtxd.lck_mtxd_promoted
95#define	lck_mtx_spin	lck_mtx_sw.lck_mtxd.lck_mtxd_spin
96
97#define lck_mtx_tag	lck_mtx_sw.lck_mtxi.lck_mtxi_tag
98#define lck_mtx_ptr	lck_mtx_sw.lck_mtxi.lck_mtxi_ptr
99#define lck_mtx_state	lck_mtx_sw.lck_mtxi.lck_mtxi_pad
100
101#define	LCK_MTX_TAG_INDIRECT			0x00001007	/* lock marked as Indirect  */
102#define	LCK_MTX_TAG_DESTROYED			0x00002007	/* lock marked as Destroyed */
103#define LCK_MTX_PTR_EXTENDED			0x00003007	/* lock is extended version */
104
105/* Adaptive spin before blocking */
106extern unsigned int	MutexSpin;
107extern int		lck_mtx_lock_spinwait_x86(lck_mtx_t *mutex);
108extern void		lck_mtx_lock_wait_x86(lck_mtx_t *mutex);
109extern void		lck_mtx_lock_acquire_x86(lck_mtx_t *mutex);
110extern void		lck_mtx_unlock_wakeup_x86(lck_mtx_t *mutex, int owner_was_promoted);
111
112extern void		lck_mtx_lock_mark_destroyed(lck_mtx_t *mutex);
113extern int		lck_mtx_lock_mark_promoted(lck_mtx_t *mutex);
114extern int		lck_mtx_lock_decr_waiter(lck_mtx_t *mutex);
115extern int		lck_mtx_lock_grab_mutex(lck_mtx_t *mutex);
116extern integer_t	lck_mtx_lock_get_pri(lck_mtx_t *mutex);
117
118extern void		hw_lock_byte_init(uint8_t *lock_byte);
119extern void		hw_lock_byte_lock(uint8_t *lock_byte);
120extern void		hw_lock_byte_unlock(uint8_t *lock_byte);
121
122typedef struct {
123	unsigned int		type;
124#ifdef __x86_64__
125	unsigned int		pad4;
126#endif
127	vm_offset_t		pc;
128	vm_offset_t		thread;
129} lck_mtx_deb_t;
130
131#define MUTEX_TAG       0x4d4d
132
133typedef struct {
134	unsigned int		lck_mtx_stat_data;
135} lck_mtx_stat_t;
136
137typedef struct _lck_mtx_ext_ {
138	lck_mtx_t		lck_mtx;
139	struct _lck_grp_	*lck_mtx_grp;
140	unsigned int		lck_mtx_attr;
141#ifdef __x86_64__
142	unsigned int		lck_mtx_pad1;
143#endif
144	lck_mtx_deb_t		lck_mtx_deb;
145	uint64_t		lck_mtx_stat;
146#ifdef __x86_64__
147	unsigned int		lck_mtx_pad2[2];
148#endif
149} lck_mtx_ext_t;
150
151#define	LCK_MTX_ATTR_DEBUG	0x1
152#define	LCK_MTX_ATTR_DEBUGb	0
153#define	LCK_MTX_ATTR_STAT	0x2
154#define	LCK_MTX_ATTR_STATb	1
155
156#else
157#ifdef	KERNEL_PRIVATE
158typedef struct {
159	unsigned long		opaque[3];
160} lck_mtx_t;
161
162typedef struct {
163	unsigned long		opaque[10];
164} lck_mtx_ext_t;
165
166#else
167typedef struct __lck_mtx_t__		lck_mtx_t;
168typedef struct __lck_mtx_ext_t__	lck_mtx_ext_t;
169#endif
170#endif
171
172#ifdef	MACH_KERNEL_PRIVATE
173#pragma pack(1)		/* Make sure the structure stays as we defined it */
174typedef struct _lck_rw_t_internal_ {
175	volatile uint16_t	lck_rw_shared_count;	/* No. of accepted readers */
176	uint8_t			lck_rw_interlock; 	/* Interlock byte */
177	volatile uint8_t
178				lck_rw_priv_excl:1,	/* Writers prioritized if set */
179				lck_rw_want_upgrade:1,	/* Read-to-write upgrade waiting */
180				lck_rw_want_write:1,	/* Writer waiting or locked for write */
181				lck_r_waiting:1,	/* Reader is sleeping on lock */
182				lck_w_waiting:1,	/* Writer is sleeping on lock */
183				lck_rw_can_sleep:1,	/* Can attempts to lock go to sleep? */
184				lck_rw_padb6:2; 		/* padding */
185
186	uint32_t		lck_rw_tag; /* This can be obsoleted when stats
187					     * are in
188					     */
189	uint32_t		lck_rw_pad8;
190#ifdef __x86_64__
191	uint32_t		lck_rw_pad12;
192#endif
193} lck_rw_t;
194#pragma pack()
195
196#define	LCK_RW_ATTR_DEBUG	0x1
197#define	LCK_RW_ATTR_DEBUGb	0
198#define	LCK_RW_ATTR_STAT	0x2
199#define	LCK_RW_ATTR_STATb	1
200#define LCK_RW_ATTR_READ_PRI	0x3
201#define LCK_RW_ATTR_READ_PRIb	2
202#define	LCK_RW_ATTR_DIS_THREAD	0x40000000
203#define	LCK_RW_ATTR_DIS_THREADb	30
204#define	LCK_RW_ATTR_DIS_MYLOCK	0x10000000
205#define	LCK_RW_ATTR_DIS_MYLOCKb	28
206
207#define	LCK_RW_TAG_DESTROYED		0x00002007	/* lock marked as Destroyed */
208
209#else
210#ifdef	KERNEL_PRIVATE
211#pragma pack(1)
212typedef struct {
213	uint32_t		opaque[3];
214#ifdef	__x86_64__
215	uint32_t		opaque4;
216#endif
217} lck_rw_t;
218#pragma pack()
219#else
220typedef struct __lck_rw_t__	lck_rw_t;
221#endif
222#endif
223
224#endif	/* _ARM_LOCKS_H_ */
225