1/* 2 * Copyright (c) 2004-2012 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 _I386_LOCKS_H_ 30#define _I386_LOCKS_H_ 31 32#include <sys/appleapiopts.h> 33#include <kern/kern_types.h> 34 35#ifdef MACH_KERNEL_PRIVATE 36 37#include <i386/hw_lock_types.h> 38 39extern unsigned int LcksOpts; 40 41#define enaLkDeb 0x00000001 /* Request debug in default attribute */ 42#define enaLkStat 0x00000002 /* Request statistic in default attribute */ 43#define disLkRWPrio 0x00000004 /* Disable RW lock priority promotion */ 44 45#endif /* MACH_KERNEL_PRIVATE */ 46 47#if defined(MACH_KERNEL_PRIVATE) 48typedef struct { 49 volatile uintptr_t interlock; 50#if MACH_LDEBUG 51 unsigned long lck_spin_pad[9]; /* XXX - usimple_lock_data_t */ 52#endif 53} lck_spin_t; 54 55#define LCK_SPIN_TAG_DESTROYED 0x00002007 /* lock marked as Destroyed */ 56 57#else /* MACH_KERNEL_PRIVATE */ 58#ifdef KERNEL_PRIVATE 59typedef struct { 60 unsigned long opaque[10]; 61} lck_spin_t; 62#else /* KERNEL_PRIVATE */ 63typedef struct __lck_spin_t__ lck_spin_t; 64#endif 65#endif 66 67#ifdef MACH_KERNEL_PRIVATE 68/* The definition of this structure, including the layout of the 69 * state bitfield, is tailored to the asm implementation in i386_lock.s 70 */ 71typedef struct _lck_mtx_ { 72 union { 73 struct { 74 volatile uintptr_t lck_mtxd_owner; 75 union { 76 struct { 77 volatile uint32_t 78 lck_mtxd_waiters:16, 79 lck_mtxd_pri:8, 80 lck_mtxd_ilocked:1, 81 lck_mtxd_mlocked:1, 82 lck_mtxd_promoted:1, 83 lck_mtxd_spin:1, 84 lck_mtxd_is_ext:1, 85 lck_mtxd_pad3:3; 86 }; 87 uint32_t lck_mtxd_state; 88 }; 89 /* Pad field used as a canary, initialized to ~0 */ 90 uint32_t lck_mtxd_pad32; 91 } lck_mtxd; 92 struct { 93 struct _lck_mtx_ext_ *lck_mtxi_ptr; 94 uint32_t lck_mtxi_tag; 95 uint32_t lck_mtxi_pad32; 96 } lck_mtxi; 97 } lck_mtx_sw; 98} lck_mtx_t; 99 100#define lck_mtx_owner lck_mtx_sw.lck_mtxd.lck_mtxd_owner 101#define lck_mtx_waiters lck_mtx_sw.lck_mtxd.lck_mtxd_waiters 102#define lck_mtx_pri lck_mtx_sw.lck_mtxd.lck_mtxd_pri 103#define lck_mtx_promoted lck_mtx_sw.lck_mtxd.lck_mtxd_promoted 104#define lck_mtx_is_ext lck_mtx_sw.lck_mtxd.lck_mtxd_is_ext 105 106#define lck_mtx_tag lck_mtx_sw.lck_mtxi.lck_mtxi_tag 107#define lck_mtx_ptr lck_mtx_sw.lck_mtxi.lck_mtxi_ptr 108#define lck_mtx_state lck_mtx_sw.lck_mtxd.lck_mtxd_state 109/* This pattern must subsume the interlocked, mlocked and spin bits */ 110#define LCK_MTX_TAG_INDIRECT 0x07ff1007 /* lock marked as Indirect */ 111#define LCK_MTX_TAG_DESTROYED 0x07fe2007 /* lock marked as Destroyed */ 112 113/* Adaptive spin before blocking */ 114extern unsigned int MutexSpin; 115extern int lck_mtx_lock_spinwait_x86(lck_mtx_t *mutex); 116extern void lck_mtx_lock_wait_x86(lck_mtx_t *mutex); 117extern void lck_mtx_lock_acquire_x86(lck_mtx_t *mutex); 118extern void lck_mtx_unlock_wakeup_x86(lck_mtx_t *mutex, int prior_lock_state); 119 120extern void lck_mtx_lock_mark_destroyed(lck_mtx_t *mutex); 121extern int lck_mtx_lock_grab_mutex(lck_mtx_t *mutex); 122 123extern void hw_lock_byte_init(volatile uint8_t *lock_byte); 124extern void hw_lock_byte_lock(volatile uint8_t *lock_byte); 125extern void hw_lock_byte_unlock(volatile uint8_t *lock_byte); 126 127typedef struct { 128 unsigned int type; 129 unsigned int pad4; 130 vm_offset_t pc; 131 vm_offset_t thread; 132} lck_mtx_deb_t; 133 134#define MUTEX_TAG 0x4d4d 135 136typedef struct { 137 unsigned int lck_mtx_stat_data; 138} lck_mtx_stat_t; 139 140typedef struct _lck_mtx_ext_ { 141 lck_mtx_t lck_mtx; 142 struct _lck_grp_ *lck_mtx_grp; 143 unsigned int lck_mtx_attr; 144 unsigned int lck_mtx_pad1; 145 lck_mtx_deb_t lck_mtx_deb; 146 uint64_t lck_mtx_stat; 147 unsigned int lck_mtx_pad2[2]; 148} lck_mtx_ext_t; 149 150#define LCK_MTX_ATTR_DEBUG 0x1 151#define LCK_MTX_ATTR_DEBUGb 0 152#define LCK_MTX_ATTR_STAT 0x2 153#define LCK_MTX_ATTR_STATb 1 154 155#else /* MACH_KERNEL_PRIVATE */ 156#ifdef XNU_KERNEL_PRIVATE 157typedef struct { 158 unsigned long opaque[2]; 159} lck_mtx_t; 160 161typedef struct { 162 unsigned long opaque[10]; 163} lck_mtx_ext_t; 164#else 165#ifdef KERNEL_PRIVATE 166typedef struct { 167 unsigned long opaque[2]; 168} lck_mtx_t; 169 170typedef struct { 171 unsigned long opaque[10]; 172} lck_mtx_ext_t; 173 174#else 175typedef struct __lck_mtx_t__ lck_mtx_t; 176typedef struct __lck_mtx_ext_t__ lck_mtx_ext_t; 177#endif 178#endif 179#endif 180 181#ifdef MACH_KERNEL_PRIVATE 182#pragma pack(1) /* Make sure the structure stays as we defined it */ 183typedef struct _lck_rw_t_internal_ { 184 volatile uint16_t lck_rw_shared_count; /* No. of accepted readers */ 185 volatile uint8_t lck_rw_interlock; /* Interlock byte */ 186 volatile uint8_t 187 lck_rw_priv_excl:1, /* Writers prioritized if set */ 188 lck_rw_want_upgrade:1, /* Read-to-write upgrade waiting */ 189 lck_rw_want_write:1, /* Writer waiting or locked for write */ 190 lck_r_waiting:1, /* Reader is sleeping on lock */ 191 lck_w_waiting:1, /* Writer is sleeping on lock */ 192 lck_rw_can_sleep:1, /* Can attempts to lock go to sleep? */ 193 lck_rw_padb6:2; /* padding */ 194 195 uint32_t lck_rw_tag; /* This can be obsoleted when stats 196 * are in 197 */ 198 uint32_t lck_rw_pad8; 199 uint32_t lck_rw_pad12; 200} lck_rw_t; 201#pragma pack() 202 203#define LCK_RW_ATTR_DEBUG 0x1 204#define LCK_RW_ATTR_DEBUGb 0 205#define LCK_RW_ATTR_STAT 0x2 206#define LCK_RW_ATTR_STATb 1 207#define LCK_RW_ATTR_READ_PRI 0x3 208#define LCK_RW_ATTR_READ_PRIb 2 209#define LCK_RW_ATTR_DIS_THREAD 0x40000000 210#define LCK_RW_ATTR_DIS_THREADb 30 211#define LCK_RW_ATTR_DIS_MYLOCK 0x10000000 212#define LCK_RW_ATTR_DIS_MYLOCKb 28 213 214#define LCK_RW_TAG_DESTROYED 0x00002007 /* lock marked as Destroyed */ 215 216#else 217#ifdef KERNEL_PRIVATE 218#pragma pack(1) 219typedef struct { 220 uint32_t opaque[3]; 221 uint32_t opaque4; 222} lck_rw_t; 223#pragma pack() 224#else 225typedef struct __lck_rw_t__ lck_rw_t; 226#endif 227#endif 228 229#ifdef MACH_KERNEL_PRIVATE 230 231extern void kernel_preempt_check (void); 232 233#endif /* MACH_KERNEL_PRIVATE */ 234 235#endif /* _I386_LOCKS_H_ */ 236