synch_internal.h
1 /* 2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_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. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 #ifndef __SYNCH_INTERNAL_H__ 25 #define __SYNCH_INTERNAL_H__ 26 27 // kwe_state 28 enum { 29 KWE_THREAD_INWAIT = 1, 30 KWE_THREAD_PREPOST, 31 KWE_THREAD_BROADCAST, 32 }; 33 34 #define _PTHREAD_MTX_OPT_PSHARED 0x010 35 #define _PTHREAD_MTX_OPT_NOTIFY 0x1000 /* notify to drop mutex handling in cvwait */ 36 #define _PTHREAD_MTX_OPT_MUTEX 0x2000 /* this is a mutex type */ 37 38 39 #define PTHRW_COUNT_SHIFT 8 40 #define PTHRW_INC (1 << PTHRW_COUNT_SHIFT) 41 #define PTHRW_BIT_MASK ((1 << PTHRW_COUNT_SHIFT) - 1) 42 #define PTHRW_COUNT_MASK ((uint32_t)~PTHRW_BIT_MASK) 43 #define PTHRW_MAX_READERS PTHRW_COUNT_MASK 44 45 // L word 46 #define PTH_RWL_KBIT 0x01 // cannot acquire in user mode 47 #define PTH_RWL_EBIT 0x02 // exclusive lock in progress 48 #define PTH_RWL_WBIT 0x04 // write waiters pending in kernel 49 #define PTH_RWL_PBIT 0x04 // prepost (cv) pending in kernel 50 51 #define PTH_RWL_MTX_WAIT 0x20 // in cvar in mutex wait 52 #define PTH_RWL_UBIT 0x40 // lock is unlocked (no readers or writers) 53 #define PTH_RWL_MBIT 0x40 // overlapping grants from kernel (only in updateval) 54 #define PTH_RWL_IBIT 0x80 // lock reset, held until first successful unlock 55 56 #define PTHRW_RWL_INIT PTH_RWL_IBIT // reset on the lock bits (U) 57 #define PTHRW_RWLOCK_INIT (PTH_RWL_IBIT | PTH_RWL_UBIT) // reset on the lock bits (U) 58 59 // S word 60 #define PTH_RWS_SBIT 0x01 // kernel transition seq not set yet 61 #define PTH_RWS_IBIT 0x02 // Sequence is not set on return from kernel 62 63 #define PTH_RWS_CV_CBIT PTH_RWS_SBIT // kernel has cleared all info w.r.s.t CV 64 #define PTH_RWS_CV_PBIT PTH_RWS_IBIT // kernel has prepost/fake structs only,no waiters 65 #define PTH_RWS_CV_BITSALL (PTH_RWS_CV_CBIT | PTH_RWS_CV_PBIT) 66 #define PTH_RWS_CV_MBIT PTH_RWL_MBIT // to indicate prepost return from kernel 67 #define PTH_RWS_CV_RESET_PBIT ((uint32_t)~PTH_RWS_CV_PBIT) 68 69 #define PTH_RWS_WSVBIT 0x04 // save W bit 70 71 #define PTHRW_RWS_SAVEMASK (PTH_RWS_WSVBIT) // save bits mask 72 73 #define PTHRW_RWS_INIT PTH_RWS_SBIT // reset on the lock bits (U) 74 75 // rw_flags 76 #define PTHRW_KERN_PROCESS_SHARED 0x10 77 #define PTHRW_KERN_PROCESS_PRIVATE 0x20 78 79 #define PTHREAD_MTX_TID_SWITCHING (uint64_t)-1 80 81 // L word tests 82 #define is_rwl_ebit_set(x) (((x) & PTH_RWL_EBIT) != 0) 83 #define is_rwl_wbit_set(x) (((x) & PTH_RWL_WBIT) != 0) 84 #define is_rwl_ebit_clear(x) (((x) & PTH_RWL_EBIT) == 0) 85 #define is_rwl_readoverlap(x) (((x) & PTH_RWL_MBIT) != 0) 86 87 // S word tests 88 #define is_rws_sbit_set(x) (((x) & PTH_RWS_SBIT) != 0) 89 #define is_rws_unlockinit_set(x) (((x) & PTH_RWS_IBIT) != 0) 90 #define is_rws_savemask_set(x) (((x) & PTHRW_RWS_SAVEMASK) != 0) 91 #define is_rws_pbit_set(x) (((x) & PTH_RWS_CV_PBIT) != 0) 92 93 // kwe_flags 94 #define KWE_FLAG_LOCKPREPOST 0x1 // cvwait caused a lock prepost 95 96 static inline int 97 is_seqlower(uint32_t x, uint32_t y) 98 { 99 x &= PTHRW_COUNT_MASK; 100 y &= PTHRW_COUNT_MASK; 101 if (x < y) { 102 return ((y - x) < (PTHRW_MAX_READERS / 2)); 103 } else { 104 return ((x - y) > (PTHRW_MAX_READERS / 2)); 105 } 106 } 107 108 static inline int 109 is_seqlower_eq(uint32_t x, uint32_t y) 110 { 111 if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) { 112 return 1; 113 } else { 114 return is_seqlower(x, y); 115 } 116 } 117 118 static inline int 119 is_seqhigher(uint32_t x, uint32_t y) 120 { 121 x &= PTHRW_COUNT_MASK; 122 y &= PTHRW_COUNT_MASK; 123 if (x > y) { 124 return ((x - y) < (PTHRW_MAX_READERS / 2)); 125 } else { 126 return ((y - x) > (PTHRW_MAX_READERS / 2)); 127 } 128 } 129 130 static inline int 131 is_seqhigher_eq(uint32_t x, uint32_t y) 132 { 133 if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) { 134 return 1; 135 } else { 136 return is_seqhigher(x,y); 137 } 138 } 139 140 static inline int 141 diff_genseq(uint32_t x, uint32_t y) 142 { 143 x &= PTHRW_COUNT_MASK; 144 y &= PTHRW_COUNT_MASK; 145 if (x == y) { 146 return 0; 147 } else if (x > y) { 148 return x - y; 149 } else { 150 return ((PTHRW_MAX_READERS - y) + x + PTHRW_INC); 151 } 152 } 153 154 static inline int 155 find_diff(uint32_t upto, uint32_t lowest) 156 { 157 uint32_t diff; 158 159 if (upto == lowest) 160 return(0); 161 #if 0 162 diff = diff_genseq(upto, lowest); 163 #else 164 if (is_seqlower(upto, lowest) != 0) 165 diff = diff_genseq(lowest, upto); 166 else 167 diff = diff_genseq(upto, lowest); 168 #endif 169 diff = (diff >> PTHRW_COUNT_SHIFT); 170 return(diff); 171 } 172 173 #endif /* __SYNCH_INTERNAL_H__ */