1/* 2 * Copyright (c) 2003-2007 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_LOCKS_H_ 30#define _KERN_LOCKS_H_ 31 32#include <sys/cdefs.h> 33#include <sys/appleapiopts.h> 34#include <mach/boolean.h> 35#include <mach/mach_types.h> 36#include <kern/kern_types.h> 37#include <machine/locks.h> 38 39#ifdef MACH_KERNEL_PRIVATE 40#include <kern/queue.h> 41 42extern void lck_mod_init( 43 void) __attribute__((section("__TEXT, initcode"))); 44 45typedef unsigned int lck_type_t; 46 47#define LCK_TYPE_SPIN 1 48#define LCK_TYPE_MTX 2 49#define LCK_TYPE_RW 3 50 51#endif 52 53typedef unsigned int lck_sleep_action_t; 54 55#define LCK_SLEEP_DEFAULT 0x00 /* Release the lock while waiting for the event, then reclaim */ 56 /* RW locks are returned in the same mode */ 57#define LCK_SLEEP_UNLOCK 0x01 /* Release the lock and return unheld */ 58#define LCK_SLEEP_SHARED 0x02 /* Reclaim the lock in shared mode (RW only) */ 59#define LCK_SLEEP_EXCLUSIVE 0x04 /* Reclaim the lock in exclusive mode (RW only) */ 60#define LCK_SLEEP_SPIN 0x08 /* Reclaim the lock in spin mode (mutex only) */ 61 62#define LCK_SLEEP_MASK 0x0f /* Valid actions */ 63 64#ifdef MACH_KERNEL_PRIVATE 65 66typedef struct { 67 uint64_t lck_grp_spin_util_cnt; 68 uint64_t lck_grp_spin_held_cnt; 69 uint64_t lck_grp_spin_miss_cnt; 70 uint64_t lck_grp_spin_held_max; 71 uint64_t lck_grp_spin_held_cum; 72} lck_grp_spin_stat_t; 73 74typedef struct { 75 uint64_t lck_grp_mtx_util_cnt; 76 /* On x86, this is used as the "direct wait" count */ 77 uint64_t lck_grp_mtx_held_cnt; 78 uint64_t lck_grp_mtx_miss_cnt; 79 uint64_t lck_grp_mtx_wait_cnt; 80 /* Rest currently unused */ 81 uint64_t lck_grp_mtx_held_max; 82 uint64_t lck_grp_mtx_held_cum; 83 uint64_t lck_grp_mtx_wait_max; 84 uint64_t lck_grp_mtx_wait_cum; 85} lck_grp_mtx_stat_t; 86 87typedef struct { 88 uint64_t lck_grp_rw_util_cnt; 89 uint64_t lck_grp_rw_held_cnt; 90 uint64_t lck_grp_rw_miss_cnt; 91 uint64_t lck_grp_rw_wait_cnt; 92 uint64_t lck_grp_rw_held_max; 93 uint64_t lck_grp_rw_held_cum; 94 uint64_t lck_grp_rw_wait_max; 95 uint64_t lck_grp_rw_wait_cum; 96} lck_grp_rw_stat_t; 97 98typedef struct _lck_grp_stat_ { 99 lck_grp_spin_stat_t lck_grp_spin_stat; 100 lck_grp_mtx_stat_t lck_grp_mtx_stat; 101 lck_grp_rw_stat_t lck_grp_rw_stat; 102} lck_grp_stat_t; 103 104#define LCK_GRP_MAX_NAME 64 105 106typedef struct _lck_grp_ { 107 queue_chain_t lck_grp_link; 108 uint32_t lck_grp_refcnt; 109 uint32_t lck_grp_spincnt; 110 uint32_t lck_grp_mtxcnt; 111 uint32_t lck_grp_rwcnt; 112 uint32_t lck_grp_attr; 113 char lck_grp_name[LCK_GRP_MAX_NAME]; 114 lck_grp_stat_t lck_grp_stat; 115} lck_grp_t; 116 117#define LCK_GRP_NULL (lck_grp_t *)0 118 119#else 120typedef struct __lck_grp__ lck_grp_t; 121#endif 122 123#ifdef MACH_KERNEL_PRIVATE 124typedef struct _lck_grp_attr_ { 125 uint32_t grp_attr_val; 126} lck_grp_attr_t; 127 128extern lck_grp_attr_t LockDefaultGroupAttr; 129 130#define LCK_GRP_ATTR_STAT 0x1 131 132#else 133typedef struct __lck_grp_attr__ lck_grp_attr_t; 134#endif 135 136#define LCK_GRP_ATTR_NULL (lck_grp_attr_t *)0 137 138__BEGIN_DECLS 139 140extern lck_grp_attr_t *lck_grp_attr_alloc_init( 141 void); 142 143extern void lck_grp_attr_setdefault( 144 lck_grp_attr_t *attr); 145 146extern void lck_grp_attr_setstat( 147 lck_grp_attr_t *attr); 148 149extern void lck_grp_attr_free( 150 lck_grp_attr_t *attr); 151 152extern lck_grp_t *lck_grp_alloc_init( 153 const char* grp_name, 154 lck_grp_attr_t *attr); 155 156__END_DECLS 157 158#ifdef MACH_KERNEL_PRIVATE 159extern void lck_grp_init( 160 lck_grp_t *grp, 161 const char* grp_name, 162 lck_grp_attr_t *attr); 163 164extern void lck_grp_reference( 165 lck_grp_t *grp); 166 167extern void lck_grp_deallocate( 168 lck_grp_t *grp); 169 170extern void lck_grp_lckcnt_incr( 171 lck_grp_t *grp, 172 lck_type_t lck_type); 173 174extern void lck_grp_lckcnt_decr( 175 lck_grp_t *grp, 176 lck_type_t lck_type); 177#endif 178 179__BEGIN_DECLS 180 181extern void lck_grp_free( 182 lck_grp_t *grp); 183 184__END_DECLS 185 186#ifdef MACH_KERNEL_PRIVATE 187typedef struct _lck_attr_ { 188 unsigned int lck_attr_val; 189} lck_attr_t; 190 191extern lck_attr_t LockDefaultLckAttr; 192 193#define LCK_ATTR_NONE 0 194 195#define LCK_ATTR_DEBUG 0x00000001 196#define LCK_ATTR_RW_SHARED_PRIORITY 0x00010000 197 198#else 199typedef struct __lck_attr__ lck_attr_t; 200#endif 201 202#define LCK_ATTR_NULL (lck_attr_t *)0 203 204__BEGIN_DECLS 205 206extern lck_attr_t *lck_attr_alloc_init( 207 void); 208 209extern void lck_attr_setdefault( 210 lck_attr_t *attr); 211 212extern void lck_attr_setdebug( 213 lck_attr_t *attr); 214 215extern void lck_attr_cleardebug( 216 lck_attr_t *attr); 217 218#ifdef XNU_KERNEL_PRIVATE 219extern void lck_attr_rw_shared_priority( 220 lck_attr_t *attr); 221#endif 222 223extern void lck_attr_free( 224 lck_attr_t *attr); 225 226#define decl_lck_spin_data(class,name) class lck_spin_t name; 227 228extern lck_spin_t *lck_spin_alloc_init( 229 lck_grp_t *grp, 230 lck_attr_t *attr); 231 232extern void lck_spin_init( 233 lck_spin_t *lck, 234 lck_grp_t *grp, 235 lck_attr_t *attr); 236 237extern void lck_spin_lock( 238 lck_spin_t *lck); 239 240extern void lck_spin_unlock( 241 lck_spin_t *lck); 242 243extern void lck_spin_destroy( 244 lck_spin_t *lck, 245 lck_grp_t *grp); 246 247extern void lck_spin_free( 248 lck_spin_t *lck, 249 lck_grp_t *grp); 250 251extern wait_result_t lck_spin_sleep( 252 lck_spin_t *lck, 253 lck_sleep_action_t lck_sleep_action, 254 event_t event, 255 wait_interrupt_t interruptible); 256 257extern wait_result_t lck_spin_sleep_deadline( 258 lck_spin_t *lck, 259 lck_sleep_action_t lck_sleep_action, 260 event_t event, 261 wait_interrupt_t interruptible, 262 uint64_t deadline); 263 264#ifdef KERNEL_PRIVATE 265 266extern boolean_t lck_spin_try_lock( 267 lck_spin_t *lck); 268 269struct _lck_mtx_ext_; 270extern void lck_mtx_init_ext(lck_mtx_t *lck, struct _lck_mtx_ext_ *lck_ext, 271 lck_grp_t *grp, lck_attr_t *attr); 272 273#endif 274 275 276#define decl_lck_mtx_data(class,name) class lck_mtx_t name; 277 278extern lck_mtx_t *lck_mtx_alloc_init( 279 lck_grp_t *grp, 280 lck_attr_t *attr); 281 282extern void lck_mtx_init( 283 lck_mtx_t *lck, 284 lck_grp_t *grp, 285 lck_attr_t *attr); 286extern void lck_mtx_lock( 287 lck_mtx_t *lck); 288 289#if defined(__i386__) 290extern void lck_mtx_unlock(lck_mtx_t *lck) __DARWIN10_ALIAS(lck_mtx_unlock); 291#else 292extern void lck_mtx_unlock( 293 lck_mtx_t *lck); 294#endif /* __i386__ */ 295 296extern void lck_mtx_destroy( 297 lck_mtx_t *lck, 298 lck_grp_t *grp); 299 300extern void lck_mtx_free( 301 lck_mtx_t *lck, 302 lck_grp_t *grp); 303 304extern wait_result_t lck_mtx_sleep( 305 lck_mtx_t *lck, 306 lck_sleep_action_t lck_sleep_action, 307 event_t event, 308 wait_interrupt_t interruptible); 309 310extern wait_result_t lck_mtx_sleep_deadline( 311 lck_mtx_t *lck, 312 lck_sleep_action_t lck_sleep_action, 313 event_t event, 314 wait_interrupt_t interruptible, 315 uint64_t deadline); 316 317#ifdef KERNEL_PRIVATE 318 319extern boolean_t lck_mtx_try_lock( 320 lck_mtx_t *lck); 321 322extern void mutex_pause(uint32_t); 323 324extern void lck_mtx_yield ( 325 lck_mtx_t *lck); 326 327#if defined(__i386__) || defined(__x86_64__) 328extern boolean_t lck_mtx_try_lock_spin( 329 lck_mtx_t *lck); 330 331extern void lck_mtx_lock_spin_always( 332 lck_mtx_t *lck); 333 334extern void lck_mtx_lock_spin( 335 lck_mtx_t *lck); 336 337extern void lck_mtx_convert_spin( 338 lck_mtx_t *lck); 339 340#define lck_mtx_unlock_always(l) lck_mtx_unlock(l) 341 342#else 343#define lck_mtx_try_lock_spin(l) lck_mtx_try_lock(l) 344#define lck_mtx_lock_spin(l) lck_mtx_lock(l) 345#define lck_mtx_lock_spin_always(l) lck_spin_lock(l) 346#define lck_mtx_unlock_always(l) lck_spin_unlock(l) 347#define lck_mtx_convert_spin(l) do {} while (0) 348#endif 349 350#endif /* KERNEL_PRIVATE */ 351 352extern void lck_mtx_assert( 353 lck_mtx_t *lck, 354 unsigned int type); 355 356__END_DECLS 357 358#define LCK_MTX_ASSERT_OWNED 0x01 359#define LCK_MTX_ASSERT_NOTOWNED 0x02 360 361#ifdef MACH_KERNEL_PRIVATE 362extern void lck_mtx_lock_wait( 363 lck_mtx_t *lck, 364 thread_t holder); 365 366extern int lck_mtx_lock_acquire( 367 lck_mtx_t *lck); 368 369extern void lck_mtx_unlock_wakeup( 370 lck_mtx_t *lck, 371 thread_t holder); 372extern void lck_mtx_unlockspin_wakeup( 373 lck_mtx_t *lck); 374 375extern boolean_t lck_mtx_ilk_unlock( 376 lck_mtx_t *lck); 377 378#endif 379 380#define decl_lck_rw_data(class,name) class lck_rw_t name; 381 382typedef unsigned int lck_rw_type_t; 383 384#define LCK_RW_TYPE_SHARED 0x01 385#define LCK_RW_TYPE_EXCLUSIVE 0x02 386 387#ifdef XNU_KERNEL_PRIVATE 388#define LCK_RW_ASSERT_SHARED 0x01 389#define LCK_RW_ASSERT_EXCLUSIVE 0x02 390#define LCK_RW_ASSERT_HELD (LCK_RW_ASSERT_SHARED | LCK_RW_ASSERT_EXCLUSIVE) 391#endif 392 393__BEGIN_DECLS 394 395extern lck_rw_t *lck_rw_alloc_init( 396 lck_grp_t *grp, 397 lck_attr_t *attr); 398 399extern void lck_rw_init( 400 lck_rw_t *lck, 401 lck_grp_t *grp, 402 lck_attr_t *attr); 403 404extern void lck_rw_lock( 405 lck_rw_t *lck, 406 lck_rw_type_t lck_rw_type); 407 408extern void lck_rw_unlock( 409 lck_rw_t *lck, 410 lck_rw_type_t lck_rw_type); 411 412extern void lck_rw_lock_shared( 413 lck_rw_t *lck); 414 415extern void lck_rw_unlock_shared( 416 lck_rw_t *lck); 417 418extern void lck_rw_lock_exclusive( 419 lck_rw_t *lck); 420 421extern void lck_rw_unlock_exclusive( 422 lck_rw_t *lck); 423 424#ifdef XNU_KERNEL_PRIVATE 425/* 426 * CAUTION 427 * read-write locks do not have a concept of ownership, so lck_rw_assert() 428 * merely asserts that someone is holding the lock, not necessarily the caller. 429 */ 430extern void lck_rw_assert( 431 lck_rw_t *lck, 432 unsigned int type); 433#endif 434 435#ifdef KERNEL_PRIVATE 436 437extern lck_rw_type_t lck_rw_done( 438 lck_rw_t *lck); 439#endif 440 441extern void lck_rw_destroy( 442 lck_rw_t *lck, 443 lck_grp_t *grp); 444 445extern void lck_rw_free( 446 lck_rw_t *lck, 447 lck_grp_t *grp); 448 449extern wait_result_t lck_rw_sleep( 450 lck_rw_t *lck, 451 lck_sleep_action_t lck_sleep_action, 452 event_t event, 453 wait_interrupt_t interruptible); 454 455extern wait_result_t lck_rw_sleep_deadline( 456 lck_rw_t *lck, 457 lck_sleep_action_t lck_sleep_action, 458 event_t event, 459 wait_interrupt_t interruptible, 460 uint64_t deadline); 461 462extern boolean_t lck_rw_lock_shared_to_exclusive( 463 lck_rw_t *lck); 464 465extern void lck_rw_lock_exclusive_to_shared( 466 lck_rw_t *lck); 467 468extern boolean_t lck_rw_try_lock( 469 lck_rw_t *lck, 470 lck_rw_type_t lck_rw_type); 471 472#ifdef KERNEL_PRIVATE 473 474extern boolean_t lck_rw_try_lock_shared( 475 lck_rw_t *lck); 476 477extern boolean_t lck_rw_try_lock_exclusive( 478 lck_rw_t *lck); 479#endif 480 481__END_DECLS 482 483#endif /* _KERN_LOCKS_H_ */ 484