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