1/*
2 * Copyright (c) 2022 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_LOCK_MTX_H_
30#define _KERN_LOCK_MTX_H_
31
32#include <kern/lock_types.h>
33#include <kern/lock_group.h>
34#include <kern/lock_attr.h>
35
36#ifdef XNU_KERNEL_PRIVATE
37#include <kern/startup.h>
38#endif /* XNU_KERNEL_PRIVATE */
39
40__BEGIN_DECLS
41
42#if MACH_KERNEL_PRIVATE
43#if !LCK_MTX_USE_ARCH
44
45typedef union lck_mtx_state {
46 struct {
47 uint32_t owner : 28;
48 uint32_t ilocked : 1;
49 uint32_t spin_mode : 1;
50 uint32_t needs_wakeup : 1;
51 uint32_t profile : 1;
52#define LCK_MTX_CTID_MASK 0x0fffffffu
53#define LCK_MTX_BITS_MASK 0xf0000000u
54#define LCK_MTX_ILOCK 0x10000000u
55#define LCK_MTX_SPIN_MODE 0x20000000u
56#define LCK_MTX_NEEDS_WAKEUP 0x40000000u
57#if CONFIG_DTRACE
58#define LCK_MTX_PROFILE 0x80000000u
59#else
60#define LCK_MTX_PROFILE 0x00000000u
61#endif
62 uint16_t ilk_tail;
63 uint16_t as_tail;
64 };
65 uint32_t data;
66 uint64_t val;
67} lck_mtx_state_t;
68
69typedef struct _lck_mtx_ {
70 uint32_t lck_mtx_tsid : 24; /* turnstile ID */
71 uint8_t lck_mtx_type : 8; /* Type */
72 uint32_t lck_mtx_grp;
73 lck_mtx_state_t lck_mtx;
74} lck_mtx_t;
75
76/* lock marked as destroyed, sets ILOCK | WAITERS */
77#define LCK_MTX_TAG_DESTROYED 0xf0fe2007
78
79/*
80 * for historical reasons the lck_mtx_t definition for the KDK
81 * are in <machine/locks.h> headers.
82 */
83#endif /* !LCK_MTX_USE_ARCH */
84#endif
85
86#define decl_lck_mtx_data(class, name) class lck_mtx_t name
87
88extern lck_mtx_t *lck_mtx_alloc_init(
89 lck_grp_t *grp,
90 lck_attr_t *attr);
91
92extern void lck_mtx_init(
93 lck_mtx_t *lck,
94 lck_grp_t *grp,
95 lck_attr_t *attr);
96extern void lck_mtx_lock(
97 lck_mtx_t *lck);
98
99extern void lck_mtx_unlock(
100 lck_mtx_t *lck);
101
102extern void lck_mtx_destroy(
103 lck_mtx_t *lck,
104 lck_grp_t *grp);
105
106extern void lck_mtx_free(
107 lck_mtx_t *lck,
108 lck_grp_t *grp);
109
110extern wait_result_t lck_mtx_sleep(
111 lck_mtx_t *lck,
112 lck_sleep_action_t lck_sleep_action,
113 event_t event,
114 wait_interrupt_t interruptible);
115
116extern wait_result_t lck_mtx_sleep_deadline(
117 lck_mtx_t *lck,
118 lck_sleep_action_t lck_sleep_action,
119 event_t event,
120 wait_interrupt_t interruptible,
121 uint64_t deadline);
122
123#define LCK_MTX_ASSERT_OWNED LCK_ASSERT_OWNED
124#define LCK_MTX_ASSERT_NOTOWNED LCK_ASSERT_NOTOWNED
125
126extern void lck_mtx_assert(
127 lck_mtx_t *lck,
128 unsigned int type);
129
130#if MACH_ASSERT
131#define LCK_MTX_ASSERT(lck, type) lck_mtx_assert((lck),(type))
132#else /* MACH_ASSERT */
133#define LCK_MTX_ASSERT(lck, type)
134#endif /* MACH_ASSERT */
135
136#if DEBUG
137#define LCK_MTX_ASSERT_DEBUG(lck, type) lck_mtx_assert((lck),(type))
138#else /* DEBUG */
139#define LCK_MTX_ASSERT_DEBUG(lck, type)
140#endif /* DEBUG */
141
142#if KERNEL_PRIVATE
143
144extern boolean_t lck_mtx_try_lock(
145 lck_mtx_t *lck);
146
147extern void mutex_pause(uint32_t);
148
149extern boolean_t lck_mtx_yield(
150 lck_mtx_t *lck);
151
152extern boolean_t lck_mtx_try_lock_spin(
153 lck_mtx_t *lck);
154
155extern void lck_mtx_lock_spin(
156 lck_mtx_t *lck);
157
158extern boolean_t kdp_lck_mtx_lock_spin_is_acquired(
159 lck_mtx_t *lck);
160
161extern void lck_mtx_convert_spin(
162 lck_mtx_t *lck);
163
164extern void lck_mtx_lock_spin_always(
165 lck_mtx_t *lck);
166
167extern boolean_t lck_mtx_try_lock_spin_always(
168 lck_mtx_t *lck);
169
170#define lck_mtx_unlock_always(l) lck_mtx_unlock(l)
171
172#endif /* KERNEL_PRIVATE */
173#if XNU_KERNEL_PRIVATE
174
175struct lck_mtx_startup_spec {
176 lck_mtx_t *lck;
177 lck_grp_t *lck_grp;
178 lck_attr_t *lck_attr;
179};
180
181extern void lck_mtx_startup_init(
182 struct lck_mtx_startup_spec *spec);
183
184#define LCK_MTX_DECLARE_ATTR(var, grp, attr) \
185 lck_mtx_t var; \
186 static __startup_data struct lck_mtx_startup_spec \
187 __startup_lck_mtx_spec_ ## var = { &var, grp, attr }; \
188 STARTUP_ARG(LOCKS, STARTUP_RANK_FOURTH, lck_mtx_startup_init, \
189 &__startup_lck_mtx_spec_ ## var)
190
191#define LCK_MTX_DECLARE(var, grp) \
192 LCK_MTX_DECLARE_ATTR(var, grp, LCK_ATTR_NULL)
193
194#endif /* XNU_KERNEL_PRIVATE */
195
196__END_DECLS
197
198#endif /* _KERN_LOCK_RW_H_ */
199