]> git.saurik.com Git - apple/libpthread.git/blame - kern/synch_internal.h
libpthread-105.40.1.tar.gz
[apple/libpthread.git] / kern / synch_internal.h
CommitLineData
f1a1da6c
A
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
28#define _PTHREAD_MTX_OPT_PSHARED 0x010
29#define _PTHREAD_MTX_OPT_NOTIFY 0x1000 /* notify to drop mutex handling in cvwait */
30#define _PTHREAD_MTX_OPT_MUTEX 0x2000 /* this is a mutex type */
31
32
33#define PTHRW_COUNT_SHIFT 8
34#define PTHRW_INC (1 << PTHRW_COUNT_SHIFT)
35#define PTHRW_BIT_MASK ((1 << PTHRW_COUNT_SHIFT) - 1)
36#define PTHRW_COUNT_MASK ((uint32_t)~PTHRW_BIT_MASK)
37#define PTHRW_MAX_READERS PTHRW_COUNT_MASK
38
39// L word
40#define PTH_RWL_KBIT 0x01 // cannot acquire in user mode
41#define PTH_RWL_EBIT 0x02 // exclusive lock in progress
42#define PTH_RWL_WBIT 0x04 // write waiters pending in kernel
43#define PTH_RWL_PBIT 0x04 // prepost (cv) pending in kernel
44
45#define PTH_RWL_MTX_WAIT 0x20 // in cvar in mutex wait
46#define PTH_RWL_RBIT 0x40 // reader pending in kernel (not used)
47#define PTH_RWL_MBIT 0x40 // overlapping grants from kernel
48#define PTH_RWL_IBIT 0x80 // lock reset, held until first successful unlock
49
50#define PTHRW_RWL_INIT PTH_RWL_IBIT // reset on the lock bits (U)
51#define PTHRW_RWLOCK_INIT (PTH_RWL_IBIT | PTH_RWL_RBIT) // reset on the lock bits (U)
52#define PTH_RWLOCK_RESET_RBIT ((uint32_t)~PTH_RWL_RBIT)
53
54// S word
55#define PTH_RWS_SBIT 0x01 // kernel transition seq not set yet
56#define PTH_RWS_IBIT 0x02 // Sequence is not set on return from kernel
57
58#define PTH_RWS_CV_CBIT PTH_RWS_SBIT // kernel has cleared all info w.r.s.t CV
59#define PTH_RWS_CV_PBIT PTH_RWS_IBIT // kernel has prepost/fake structs only,no waiters
60#define PTH_RWS_CV_BITSALL (PTH_RWS_CV_CBIT | PTH_RWS_CV_PBIT)
61#define PTH_RWS_CV_MBIT PTH_RWL_MBIT // to indicate prepost return from kernel
62#define PTH_RWS_CV_RESET_PBIT ((uint32_t)~PTH_RWS_CV_PBIT)
63
64#define PTH_RWS_WSVBIT 0x04 // save W bit
65
66#define PTHRW_RWS_SAVEMASK (PTH_RWS_WSVBIT) // save bits mask
67
68#define PTHRW_RWS_INIT PTH_RWS_SBIT // reset on the lock bits (U)
69#define PTHRW_SW_Reset_BIT_MASK (PTHRW_BIT_MASK & ~PTH_RWS_SBIT) // All bits except the S bit
70
71// rw_flags
72#define PTHRW_KERN_PROCESS_SHARED 0x10
73#define PTHRW_KERN_PROCESS_PRIVATE 0x20
74
75#define PTHREAD_MTX_TID_SWITCHING (uint64_t)-1
76
77// L word tests
78#define can_rwl_readinuser(x) (((x) & (PTH_RWL_WBIT | PTH_RWL_KBIT)) == 0)
79#define is_rwl_ebit_set(x) (((x) & PTH_RWL_EBIT) != 0)
80#define is_rwl_wbit_set(x) (((x) & PTH_RWL_WBIT) != 0)
81#define is_rwl_ebit_clear(x) (((x) & PTH_RWL_EBIT) == 0)
82#define is_rwl_readoverlap(x) (((x) & PTH_RWL_MBIT) != 0)
83
84// S word tests
85#define is_rws_setseq(x) (((x) & PTH_RWS_SBIT))
86#define is_rws_setunlockinit(x) (((x) & PTH_RWS_IBIT))
87
88static inline int
89is_seqlower(uint32_t x, uint32_t y)
90{
91 x &= PTHRW_COUNT_MASK;
92 y &= PTHRW_COUNT_MASK;
93 if (x < y) {
94 return ((y - x) < (PTHRW_MAX_READERS / 2));
95 } else {
96 return ((x - y) > (PTHRW_MAX_READERS / 2));
97 }
98}
99
100static inline int
101is_seqlower_eq(uint32_t x, uint32_t y)
102{
103 if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) {
104 return 1;
105 } else {
106 return is_seqlower(x, y);
107 }
108}
109
110static inline int
111is_seqhigher(uint32_t x, uint32_t y)
112{
113 x &= PTHRW_COUNT_MASK;
114 y &= PTHRW_COUNT_MASK;
115 if (x > y) {
116 return ((x - y) < (PTHRW_MAX_READERS / 2));
117 } else {
118 return ((y - x) > (PTHRW_MAX_READERS / 2));
119 }
120}
121
122static inline int
123is_seqhigher_eq(uint32_t x, uint32_t y)
124{
125 if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) {
126 return 1;
127 } else {
128 return is_seqhigher(x,y);
129 }
130}
131
132static inline int
133diff_genseq(uint32_t x, uint32_t y)
134{
135 x &= PTHRW_COUNT_MASK;
136 y &= PTHRW_COUNT_MASK;
137 if (x == y) {
138 return 0;
139 } else if (x > y) {
140 return x - y;
141 } else {
142 return ((PTHRW_MAX_READERS - y) + x + PTHRW_INC);
143 }
144}
145
146static inline int
147find_diff(uint32_t upto, uint32_t lowest)
148{
149 uint32_t diff;
150
151 if (upto == lowest)
152 return(0);
153#if 0
154 diff = diff_genseq(upto, lowest);
155#else
156 if (is_seqlower(upto, lowest) != 0)
157 diff = diff_genseq(lowest, upto);
158 else
159 diff = diff_genseq(upto, lowest);
160#endif
161 diff = (diff >> PTHRW_COUNT_SHIFT);
162 return(diff);
163}
164
165#endif /* __SYNCH_INTERNAL_H__ */