xref: /xnu-8019.80.24/osfmk/kern/lock_group.h (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*
2  * Copyright (c) 2018 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 #define LCK_GRP_NULL    (lck_grp_t *)NULL
41 
42 typedef enum lck_type {
43 	LCK_TYPE_SPIN,
44 	LCK_TYPE_MTX,
45 	LCK_TYPE_RW,
46 	LCK_TYPE_TICKET
47 } lck_type_t;
48 
49 #if XNU_KERNEL_PRIVATE
50 /*
51  * Arguments wrapped in LCK_GRP_ARG() will be elided
52  * when LOCK_STATS is not set.
53  *
54  * Arguments wrapped with LCK_GRP_PROBEARG() will be
55  * NULL when LOCK_STATS is not set
56  */
57 #if LOCK_STATS
58 #define LCK_GRP_ARG(expr) ,expr
59 #define LCK_GRP_PROBEARG(grp) grp
60 #else
61 #define LCK_GRP_ARG(expr)
62 #define LCK_GRP_PROBEARG(grp) LCK_GRP_NULL
63 #endif /* LOCK_STATS */
64 
65 typedef struct _lck_grp_stat_ {
66 	uint64_t lgs_count;
67 	uint32_t lgs_enablings;
68 #if CONFIG_DTRACE
69 	/*
70 	 * Protected by dtrace_lock
71 	 */
72 	uint32_t lgs_probeid;
73 	uint64_t lgs_limit;
74 #endif /* CONFIG_DTRACE */
75 } lck_grp_stat_t;
76 
77 typedef struct _lck_grp_stats_ {
78 #if LOCK_STATS
79 	lck_grp_stat_t          lgss_spin_held;
80 	lck_grp_stat_t          lgss_spin_miss;
81 	lck_grp_stat_t          lgss_spin_spin;
82 	lck_grp_stat_t          lgss_ticket_held;
83 	lck_grp_stat_t          lgss_ticket_miss;
84 	lck_grp_stat_t          lgss_ticket_spin;
85 #endif /* LOCK_STATS */
86 
87 	lck_grp_stat_t          lgss_mtx_held;
88 	lck_grp_stat_t          lgss_mtx_direct_wait;
89 	lck_grp_stat_t          lgss_mtx_miss;
90 	lck_grp_stat_t          lgss_mtx_wait;
91 } lck_grp_stats_t;
92 
93 #define LCK_GRP_MAX_NAME        64
94 
95 typedef struct _lck_grp_ {
96 	queue_chain_t           lck_grp_link;
97 	os_refcnt_t             lck_grp_refcnt;
98 	uint32_t                lck_grp_spincnt;
99 	uint32_t                lck_grp_ticketcnt;
100 	uint32_t                lck_grp_mtxcnt;
101 	uint32_t                lck_grp_rwcnt;
102 	uint32_t                lck_grp_attr;
103 	char                    lck_grp_name[LCK_GRP_MAX_NAME];
104 	lck_grp_stats_t         lck_grp_stats;
105 } lck_grp_t;
106 
107 #else
108 typedef struct _lck_grp_ lck_grp_t;
109 #endif /* XNU_KERNEL_PRIVATE */
110 
111 #define LCK_GRP_ATTR_STAT       0x1
112 #define LCK_GRP_ATTR_TIME_STAT  0x2
113 
114 #ifdef XNU_KERNEL_PRIVATE
115 typedef struct _lck_grp_attr_ {
116 	uint32_t        grp_attr_val;
117 } lck_grp_attr_t;
118 
119 struct lck_grp_attr_startup_spec {
120 	lck_grp_attr_t *grp_attr;
121 	uint32_t        grp_attr_set_flags;
122 	uint32_t        grp_attr_clear_flags;
123 };
124 
125 struct lck_grp_startup_spec {
126 	lck_grp_t      *grp;
127 	const char     *grp_name;
128 	lck_grp_attr_t *grp_attr;
129 };
130 
131 extern void lck_grp_attr_startup_init(
132 	struct lck_grp_attr_startup_spec *spec);
133 
134 extern void lck_grp_startup_init(
135 	struct lck_grp_startup_spec *spec);
136 
137 /*
138  * Auto-initializing lock group declarations
139  * -----------------------------------------
140  *
141  * Use LCK_GRP_DECLARE to declare an automatically initialized group.
142  *
143  * Unless you need to configure your lock groups in very specific ways,
144  * there is no point creating explicit lock group attributes. If however
145  * you do need to tune the group, then LCK_GRP_DECLARE_ATTR can be used
146  * and takes an extra lock group attr argument previously declared with
147  * LCK_GRP_ATTR_DECLARE.
148  */
149 #define LCK_GRP_ATTR_DECLARE(var, set_flags, clear_flags) \
150 	SECURITY_READ_ONLY_LATE(lck_grp_attr_t) var; \
151 	static __startup_data struct lck_grp_attr_startup_spec \
152 	__startup_lck_grp_attr_spec_ ## var = { &var, set_flags, clear_flags }; \
153 	STARTUP_ARG(LOCKS_EARLY, STARTUP_RANK_SECOND, lck_grp_attr_startup_init, \
154 	    &__startup_lck_grp_attr_spec_ ## var)
155 
156 #define LCK_GRP_DECLARE_ATTR(var, name, attr) \
157 	__PLACE_IN_SECTION("__DATA,__lock_grp") lck_grp_t var; \
158 	static __startup_data struct lck_grp_startup_spec \
159 	__startup_lck_grp_spec_ ## var = { &var, name, attr }; \
160 	STARTUP_ARG(LOCKS_EARLY, STARTUP_RANK_THIRD, lck_grp_startup_init, \
161 	    &__startup_lck_grp_spec_ ## var)
162 
163 #define LCK_GRP_DECLARE(var, name) \
164 	LCK_GRP_DECLARE_ATTR(var, name, LCK_GRP_ATTR_NULL);
165 
166 #else
167 typedef struct __lck_grp_attr__ lck_grp_attr_t;
168 #endif /* XNU_KERNEL_PRIVATE */
169 
170 #define LCK_GRP_ATTR_NULL       (lck_grp_attr_t *)NULL
171 
172 extern  lck_grp_attr_t  *lck_grp_attr_alloc_init(
173 	void);
174 
175 extern  void            lck_grp_attr_setdefault(
176 	lck_grp_attr_t          *attr);
177 
178 extern  void            lck_grp_attr_setstat(
179 	lck_grp_attr_t          *attr);
180 
181 extern  void            lck_grp_attr_free(
182 	lck_grp_attr_t          *attr);
183 
184 extern  lck_grp_t       *lck_grp_alloc_init(
185 	const char*             grp_name,
186 	lck_grp_attr_t  *attr);
187 
188 extern void             lck_grp_free(
189 	lck_grp_t               *grp);
190 
191 #ifdef  MACH_KERNEL_PRIVATE
192 extern  void            lck_grp_init(
193 	lck_grp_t               *grp,
194 	const char*             grp_name,
195 	lck_grp_attr_t          *attr);
196 
197 extern  void            lck_grp_reference(
198 	lck_grp_t               *grp);
199 
200 extern  void            lck_grp_deallocate(
201 	lck_grp_t                *grp);
202 
203 extern  void            lck_grp_lckcnt_incr(
204 	lck_grp_t               *grp,
205 	lck_type_t              lck_type);
206 
207 extern  void            lck_grp_lckcnt_decr(
208 	lck_grp_t               *grp,
209 	lck_type_t              lck_type);
210 #endif /* MACH_KERNEL_PRIVATE */
211 
212 __END_DECLS
213 
214 #endif /* _KERN_LOCK_GROUP_H */
215