]> git.saurik.com Git - apple/libpthread.git/blob - kern/synch_internal.h
libpthread-416.60.2.tar.gz
[apple/libpthread.git] / kern / 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__ */