xref: /xnu-8020.140.41/osfmk/kern/lock_group.h (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1 /*
2  * Copyright (c) 2018-2021 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 #ifndef _KERN_LOCK_GROUP_H
29 #define _KERN_LOCK_GROUP_H
30 
31 #include <kern/queue.h>
32 #include <kern/lock_types.h>
33 #if XNU_KERNEL_PRIVATE
34 #include <kern/startup.h>
35 #include <os/refcnt.h>
36 #endif /* XNU_KERNEL_PRIVATE */
37 
38 __BEGIN_DECLS
39 
40 /*!
41  * @typedef lck_grp_t
42  *
43  * @abstract
44  * The opaque type of a lock group.
45  */
46 typedef struct _lck_grp_        lck_grp_t;
47 #define LCK_GRP_NULL            ((lck_grp_t *)NULL)
48 
49 /*!
50  * @typedef lck_grp_attr_t
51  *
52  * @abstract
53  * The opaque type for attributes to a group.
54  */
55 typedef struct _lck_grp_attr_   lck_grp_attr_t;
56 #define LCK_GRP_ATTR_NULL       ((lck_grp_attr_t *)NULL)
57 
58 extern lck_grp_attr_t  *lck_grp_attr_alloc_init(
59 	void);
60 
61 extern void             lck_grp_attr_setdefault(
62 	lck_grp_attr_t         *attr);
63 
64 extern void             lck_grp_attr_setstat(
65 	lck_grp_attr_t         *attr);
66 
67 extern void             lck_grp_attr_free(
68 	lck_grp_attr_t         *attr);
69 
70 extern lck_grp_t       *lck_grp_alloc_init(
71 	const char             *grp_name,
72 	lck_grp_attr_t         *attr);
73 
74 extern void             lck_grp_free(
75 	lck_grp_t              *grp);
76 
77 #if XNU_KERNEL_PRIVATE
78 #pragma GCC visibility push(hidden)
79 
80 /*
81  * Arguments wrapped in LCK_GRP_ARG() will be elided
82  * when LOCK_STATS is not set.
83  *
84  * Arguments wrapped with LCK_GRP_PROBEARG() will be
85  * NULL when LOCK_STATS is not set
86  */
87 #if LOCK_STATS
88 #define LCK_GRP_ARG(expr)       , expr
89 #define LCK_GRP_PROBEARG(grp)   grp
90 #else
91 #define LCK_GRP_ARG(expr)
92 #define LCK_GRP_PROBEARG(grp)   LCK_GRP_NULL
93 #endif /* LOCK_STATS */
94 
95 extern uint32_t LcksOpts;
96 
97 __options_decl(lck_grp_options_t, uint32_t, {
98 	LCK_GRP_ATTR_NONE       = 0x00000000,
99 
100 #if MACH_KERNEL_PRIVATE
101 	LCK_GRP_ATTR_STAT       = 0x00000001,
102 	LCK_GRP_ATTR_TIME_STAT  = 0x00000002,
103 	LCK_GRP_ATTR_ALLOCATED  = 0x00000004,
104 #endif
105 });
106 
107 typedef struct _lck_grp_stat_ {
108 	uint64_t lgs_count;
109 	uint32_t lgs_enablings;
110 #if CONFIG_DTRACE
111 	/*
112 	 * Protected by dtrace_lock
113 	 */
114 	uint32_t lgs_probeid;
115 	uint64_t lgs_limit;
116 #endif /* CONFIG_DTRACE */
117 } lck_grp_stat_t;
118 
119 typedef struct _lck_grp_stats_ {
120 #if LOCK_STATS
121 	lck_grp_stat_t          lgss_spin_held;
122 	lck_grp_stat_t          lgss_spin_miss;
123 	lck_grp_stat_t          lgss_spin_spin;
124 	lck_grp_stat_t          lgss_ticket_held;
125 	lck_grp_stat_t          lgss_ticket_miss;
126 	lck_grp_stat_t          lgss_ticket_spin;
127 #endif /* LOCK_STATS */
128 
129 	lck_grp_stat_t          lgss_mtx_held;
130 	lck_grp_stat_t          lgss_mtx_direct_wait;
131 	lck_grp_stat_t          lgss_mtx_miss;
132 	lck_grp_stat_t          lgss_mtx_wait;
133 } lck_grp_stats_t;
134 
135 #define LCK_GRP_MAX_NAME        64
136 
137 typedef struct _lck_grp_ {
138 	queue_chain_t           lck_grp_link;
139 	os_refcnt_t             lck_grp_refcnt;
140 	uint32_t                lck_grp_spincnt;
141 	uint32_t                lck_grp_ticketcnt;
142 	uint32_t                lck_grp_mtxcnt;
143 	uint32_t                lck_grp_rwcnt;
144 	lck_grp_options_t       lck_grp_attr;
145 	char                    lck_grp_name[LCK_GRP_MAX_NAME];
146 	lck_grp_stats_t         lck_grp_stats;
147 } lck_grp_t;
148 
149 typedef struct _lck_grp_attr_ {
150 	lck_grp_options_t       grp_attr_val;
151 } lck_grp_attr_t;
152 
153 struct lck_grp_spec {
154 	lck_grp_t              *grp;
155 	char                    grp_name[LCK_GRP_MAX_NAME];
156 	lck_grp_options_t       grp_flags;
157 };
158 
159 /*
160  * Auto-initializing lock group declarations
161  * -----------------------------------------
162  *
163  * Use LCK_GRP_DECLARE to declare an automatically initialized group.
164  */
165 #define LCK_GRP_DECLARE_ATTR(var, name, flags) \
166 	__PLACE_IN_SECTION("__DATA,__lock_grp") lck_grp_t var; \
167 	static __startup_data struct lck_grp_spec \
168 	__startup_lck_grp_spec_ ## var = { &var, name, flags }; \
169 	STARTUP_ARG(LOCKS_EARLY, STARTUP_RANK_THIRD, lck_grp_startup_init, \
170 	    &__startup_lck_grp_spec_ ## var)
171 
172 #define LCK_GRP_DECLARE(var, name) \
173 	LCK_GRP_DECLARE_ATTR(var, name, LCK_GRP_ATTR_NONE);
174 
175 extern bool             lck_grp_has_stats(
176 	lck_grp_t              *grp);
177 
178 extern void             lck_grp_startup_init(
179 	struct lck_grp_spec    *spec);
180 
181 extern void             lck_grp_init(
182 	lck_grp_t              *grp,
183 	const char*             grp_name,
184 	lck_grp_attr_t         *attr);
185 
186 extern lck_grp_t       *lck_grp_init_flags(
187 	lck_grp_t              *grp,
188 	const char*             grp_name,
189 	lck_grp_options_t       grp_flags);
190 
191 extern void             lck_grp_reference(
192 	lck_grp_t              *grp,
193 	uint32_t               *cnt);
194 
195 extern void             lck_grp_deallocate(
196 	lck_grp_t              *grp,
197 	uint32_t               *cnt);
198 
199 extern void             lck_grp_foreach(
200 	bool                  (^block)(lck_grp_t *));
201 
202 #pragma GCC visibility pop
203 #endif /* XNU_KERNEL_PRIVATE */
204 
205 __END_DECLS
206 
207 #endif /* _KERN_LOCK_GROUP_H */
208