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