| @@ -1,326 +1,335 @@ | | | @@ -1,326 +1,335 @@ |
1 | /* $NetBSD: pthread_int.h,v 1.99 2020/01/27 20:50:05 ad Exp $ */ | | 1 | /* $NetBSD: pthread_int.h,v 1.100 2020/01/28 13:08:40 ad Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 | | 4 | * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 |
5 | * The NetBSD Foundation, Inc. | | 5 | * The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Nathan J. Williams and Andrew Doran. | | 9 | * by Nathan J. Williams and Andrew Doran. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the | | 17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. | | 18 | * documentation and/or other materials provided with the distribution. |
19 | * | | 19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #ifndef _LIB_PTHREAD_INT_H | | 33 | #ifndef _LIB_PTHREAD_INT_H |
34 | #define _LIB_PTHREAD_INT_H | | 34 | #define _LIB_PTHREAD_INT_H |
35 | | | 35 | |
36 | #include <sys/tls.h> | | 36 | #include <sys/tls.h> |
37 | | | 37 | |
38 | /* #define PTHREAD__DEBUG */ | | 38 | /* #define PTHREAD__DEBUG */ |
39 | #define ERRORCHECK | | 39 | #define ERRORCHECK |
40 | | | 40 | |
41 | #include "pthread_types.h" | | 41 | #include "pthread_types.h" |
42 | #include "pthread_queue.h" | | 42 | #include "pthread_queue.h" |
43 | #include "pthread_md.h" | | 43 | #include "pthread_md.h" |
44 | | | 44 | |
45 | /* Need to use libc-private names for atomic operations. */ | | 45 | /* Need to use libc-private names for atomic operations. */ |
46 | #include "../../common/lib/libc/atomic/atomic_op_namespace.h" | | 46 | #include "../../common/lib/libc/atomic/atomic_op_namespace.h" |
47 | | | 47 | |
48 | #include <sys/atomic.h> | | 48 | #include <sys/atomic.h> |
49 | #include <sys/rbtree.h> | | 49 | #include <sys/rbtree.h> |
| | | 50 | #include <sys/param.h> |
50 | | | 51 | |
51 | #include <limits.h> | | 52 | #include <limits.h> |
52 | #include <lwp.h> | | 53 | #include <lwp.h> |
53 | #include <signal.h> | | 54 | #include <signal.h> |
54 | #include <stdbool.h> | | 55 | #include <stdbool.h> |
55 | | | 56 | |
56 | #ifdef __GNUC__ | | 57 | #ifdef __GNUC__ |
57 | #define PTHREAD_HIDE __attribute__ ((visibility("hidden"))) | | 58 | #define PTHREAD_HIDE __attribute__ ((visibility("hidden"))) |
58 | #else | | 59 | #else |
59 | #define PTHREAD_HIDE /* nothing */ | | 60 | #define PTHREAD_HIDE /* nothing */ |
60 | #endif | | 61 | #endif |
61 | | | 62 | |
62 | #define PTHREAD__UNPARK_MAX 128 | | 63 | #define PTHREAD__UNPARK_MAX 128 |
63 | | | 64 | |
64 | /* | | 65 | /* |
65 | * The size of this structure needs to be no larger than struct | | 66 | * The size of this structure needs to be no larger than struct |
66 | * __pthread_cleanup_store, defined in pthread.h. | | 67 | * __pthread_cleanup_store, defined in pthread.h. |
67 | */ | | 68 | */ |
68 | struct pt_clean_t { | | 69 | struct pt_clean_t { |
69 | PTQ_ENTRY(pt_clean_t) ptc_next; | | 70 | PTQ_ENTRY(pt_clean_t) ptc_next; |
70 | void (*ptc_cleanup)(void *); | | 71 | void (*ptc_cleanup)(void *); |
71 | void *ptc_arg; | | 72 | void *ptc_arg; |
72 | }; | | 73 | }; |
73 | | | 74 | |
74 | /* Private data for pthread_attr_t */ | | 75 | /* Private data for pthread_attr_t */ |
75 | struct pthread_attr_private { | | 76 | struct pthread_attr_private { |
76 | char ptap_name[PTHREAD_MAX_NAMELEN_NP]; | | 77 | char ptap_name[PTHREAD_MAX_NAMELEN_NP]; |
77 | void *ptap_namearg; | | 78 | void *ptap_namearg; |
78 | void *ptap_stackaddr; | | 79 | void *ptap_stackaddr; |
79 | size_t ptap_stacksize; | | 80 | size_t ptap_stacksize; |
80 | size_t ptap_guardsize; | | 81 | size_t ptap_guardsize; |
81 | struct sched_param ptap_sp; | | 82 | struct sched_param ptap_sp; |
82 | int ptap_policy; | | 83 | int ptap_policy; |
83 | }; | | 84 | }; |
84 | | | 85 | |
85 | struct pthread_lock_ops { | | 86 | struct pthread_lock_ops { |
86 | void (*plo_init)(__cpu_simple_lock_t *); | | 87 | void (*plo_init)(__cpu_simple_lock_t *); |
87 | int (*plo_try)(__cpu_simple_lock_t *); | | 88 | int (*plo_try)(__cpu_simple_lock_t *); |
88 | void (*plo_unlock)(__cpu_simple_lock_t *); | | 89 | void (*plo_unlock)(__cpu_simple_lock_t *); |
89 | void (*plo_lock)(__cpu_simple_lock_t *); | | 90 | void (*plo_lock)(__cpu_simple_lock_t *); |
90 | }; | | 91 | }; |
91 | | | 92 | |
92 | struct __pthread_st { | | 93 | struct __pthread_st { |
93 | pthread_t pt_self; /* Must be first. */ | | 94 | pthread_t pt_self; /* Must be first. */ |
94 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | | 95 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) |
95 | struct tls_tcb *pt_tls; /* Thread Local Storage area */ | | 96 | struct tls_tcb *pt_tls; /* Thread Local Storage area */ |
96 | #endif | | 97 | #endif |
97 | unsigned int pt_magic; /* Magic number */ | | 98 | unsigned int pt_magic; /* Magic number */ |
98 | int pt_state; /* running, blocked, etc. */ | | 99 | int pt_state; /* running, blocked, etc. */ |
99 | pthread_mutex_t pt_lock; /* lock on state */ | | | |
100 | int pt_flags; /* see PT_FLAG_* below */ | | 100 | int pt_flags; /* see PT_FLAG_* below */ |
101 | int pt_cancel; /* Deferred cancellation */ | | 101 | int pt_cancel; /* Deferred cancellation */ |
102 | int pt_errno; /* Thread-specific errno. */ | | 102 | int pt_errno; /* Thread-specific errno. */ |
103 | stack_t pt_stack; /* Our stack */ | | 103 | stack_t pt_stack; /* Our stack */ |
104 | bool pt_stack_allocated; | | 104 | bool pt_stack_allocated; |
105 | size_t pt_guardsize; | | 105 | size_t pt_guardsize; |
106 | void *pt_exitval; /* Read by pthread_join() */ | | 106 | void *pt_exitval; /* Read by pthread_join() */ |
107 | char *pt_name; /* Thread's name, set by the app. */ | | 107 | char *pt_name; /* Thread's name, set by the app. */ |
108 | int pt_willpark; /* About to park */ | | 108 | int pt_willpark; /* About to park */ |
109 | lwpid_t pt_unpark; /* Unpark this when parking */ | | 109 | lwpid_t pt_unpark; /* Unpark this when parking */ |
110 | struct pthread_lock_ops pt_lockops;/* Cached to avoid PIC overhead */ | | 110 | struct pthread_lock_ops pt_lockops;/* Cached to avoid PIC overhead */ |
111 | void *(*pt_func)(void *);/* Function to call at start. */ | | 111 | void *(*pt_func)(void *);/* Function to call at start. */ |
112 | void *pt_arg; /* Argument to pass at start. */ | | 112 | void *pt_arg; /* Argument to pass at start. */ |
113 | | | 113 | |
114 | /* Threads to defer waking, usually until pthread_mutex_unlock(). */ | | 114 | /* Threads to defer waking, usually until pthread_mutex_unlock(). */ |
115 | lwpid_t pt_waiters[PTHREAD__UNPARK_MAX]; | | 115 | lwpid_t pt_waiters[PTHREAD__UNPARK_MAX]; |
116 | size_t pt_nwaiters; | | 116 | size_t pt_nwaiters; |
117 | | | 117 | |
118 | /* Stack of cancellation cleanup handlers and their arguments */ | | 118 | /* Stack of cancellation cleanup handlers and their arguments */ |
119 | PTQ_HEAD(, pt_clean_t) pt_cleanup_stack; | | 119 | PTQ_HEAD(, pt_clean_t) pt_cleanup_stack; |
120 | | | 120 | |
121 | /* LWP ID and entry on the list of all threads. */ | | 121 | /* LWP ID and entry on the list of all threads. */ |
122 | lwpid_t pt_lid; | | 122 | lwpid_t pt_lid; |
123 | rb_node_t pt_alltree; | | | |
124 | PTQ_ENTRY(__pthread_st) pt_allq; | | | |
125 | PTQ_ENTRY(__pthread_st) pt_deadq; | | 123 | PTQ_ENTRY(__pthread_st) pt_deadq; |
126 | | | 124 | |
127 | /* | | 125 | /* |
| | | 126 | * rbtree node and entry on the list of all threads. pt_alltree in |
| | | 127 | * its own cacheline, so pthread__find() is not needlessly impacted |
| | | 128 | * by threads going about their normal business. pt_allq is |
| | | 129 | * adjusted at the same time as pt_alltree. |
| | | 130 | */ |
| | | 131 | rb_node_t pt_alltree __aligned(COHERENCY_UNIT); |
| | | 132 | PTQ_ENTRY(__pthread_st) pt_allq; |
| | | 133 | |
| | | 134 | /* Lock on state also gets its own line. */ |
| | | 135 | pthread_mutex_t pt_lock __aligned(COHERENCY_UNIT); |
| | | 136 | |
| | | 137 | /* |
128 | * General synchronization data. We try to align, as threads | | 138 | * General synchronization data. We try to align, as threads |
129 | * on other CPUs will access this data frequently. | | 139 | * on other CPUs will access this data frequently. |
130 | */ | | 140 | */ |
131 | int pt_dummy1 __aligned(128); | | 141 | int pt_dummy1 __aligned(COHERENCY_UNIT); |
132 | struct lwpctl *pt_lwpctl; /* Kernel/user comms area */ | | 142 | struct lwpctl *pt_lwpctl; /* Kernel/user comms area */ |
133 | volatile int pt_rwlocked; /* Handed rwlock successfully */ | | 143 | volatile int pt_rwlocked; /* Handed rwlock successfully */ |
134 | volatile int pt_signalled; /* Received pthread_cond_signal() */ | | 144 | volatile int pt_signalled; /* Received pthread_cond_signal() */ |
135 | volatile int pt_mutexwait; /* Waiting to acquire mutex */ | | 145 | volatile int pt_mutexwait; /* Waiting to acquire mutex */ |
136 | void * volatile pt_mutexnext; /* Next thread in chain */ | | 146 | void * volatile pt_mutexnext; /* Next thread in chain */ |
137 | void * volatile pt_sleepobj; /* Object slept on */ | | 147 | void * volatile pt_sleepobj; /* Object slept on */ |
138 | PTQ_ENTRY(__pthread_st) pt_sleep; | | 148 | PTQ_ENTRY(__pthread_st) pt_sleep; |
139 | void (*pt_early)(void *); | | 149 | void (*pt_early)(void *); |
140 | int pt_dummy2 __aligned(128); | | | |
141 | | | 150 | |
142 | /* Thread-specific data. Large so it sits close to the end. */ | | 151 | /* Thread-specific data. Large so it sits close to the end. */ |
143 | int pt_havespecific; | | 152 | int pt_havespecific __aligned(COHERENCY_UNIT); |
144 | struct pt_specific { | | 153 | struct pt_specific { |
145 | void *pts_value; | | 154 | void *pts_value; |
146 | PTQ_ENTRY(pt_specific) pts_next; | | 155 | PTQ_ENTRY(pt_specific) pts_next; |
147 | } pt_specific[]; | | 156 | } pt_specific[]; |
148 | }; | | 157 | }; |
149 | | | 158 | |
150 | /* Thread states */ | | 159 | /* Thread states */ |
151 | #define PT_STATE_RUNNING 1 | | 160 | #define PT_STATE_RUNNING 1 |
152 | #define PT_STATE_ZOMBIE 5 | | 161 | #define PT_STATE_ZOMBIE 5 |
153 | #define PT_STATE_DEAD 6 | | 162 | #define PT_STATE_DEAD 6 |
154 | | | 163 | |
155 | /* Flag values */ | | 164 | /* Flag values */ |
156 | | | 165 | |
157 | #define PT_FLAG_DETACHED 0x0001 | | 166 | #define PT_FLAG_DETACHED 0x0001 |
158 | #define PT_FLAG_CS_DISABLED 0x0004 /* Cancellation disabled */ | | 167 | #define PT_FLAG_CS_DISABLED 0x0004 /* Cancellation disabled */ |
159 | #define PT_FLAG_CS_ASYNC 0x0008 /* Cancellation is async */ | | 168 | #define PT_FLAG_CS_ASYNC 0x0008 /* Cancellation is async */ |
160 | #define PT_FLAG_CS_PENDING 0x0010 | | 169 | #define PT_FLAG_CS_PENDING 0x0010 |
161 | #define PT_FLAG_SCOPE_SYSTEM 0x0040 | | 170 | #define PT_FLAG_SCOPE_SYSTEM 0x0040 |
162 | #define PT_FLAG_EXPLICIT_SCHED 0x0080 | | 171 | #define PT_FLAG_EXPLICIT_SCHED 0x0080 |
163 | #define PT_FLAG_SUSPENDED 0x0100 /* In the suspended queue */ | | 172 | #define PT_FLAG_SUSPENDED 0x0100 /* In the suspended queue */ |
164 | | | 173 | |
165 | #define PT_MAGIC 0x11110001 | | 174 | #define PT_MAGIC 0x11110001 |
166 | #define PT_DEAD 0xDEAD0001 | | 175 | #define PT_DEAD 0xDEAD0001 |
167 | | | 176 | |
168 | #define PT_ATTR_MAGIC 0x22220002 | | 177 | #define PT_ATTR_MAGIC 0x22220002 |
169 | #define PT_ATTR_DEAD 0xDEAD0002 | | 178 | #define PT_ATTR_DEAD 0xDEAD0002 |
170 | | | 179 | |
171 | extern size_t pthread__stacksize; | | 180 | extern size_t pthread__stacksize; |
172 | extern size_t pthread__guardsize; | | 181 | extern size_t pthread__guardsize; |
173 | extern size_t pthread__pagesize; | | 182 | extern size_t pthread__pagesize; |
174 | extern int pthread__nspins; | | 183 | extern int pthread__nspins; |
175 | extern int pthread__concurrency; | | 184 | extern int pthread__concurrency; |
176 | extern int pthread__osrev; | | 185 | extern int pthread__osrev; |
177 | extern int pthread__unpark_max; | | 186 | extern int pthread__unpark_max; |
178 | extern int pthread_keys_max; | | 187 | extern int pthread_keys_max; |
179 | | | 188 | |
180 | extern int __uselibcstub; | | 189 | extern int __uselibcstub; |
181 | | | 190 | |
182 | /* Flag to be used in a ucontext_t's uc_flags indicating that | | 191 | /* Flag to be used in a ucontext_t's uc_flags indicating that |
183 | * the saved register state is "user" state only, not full | | 192 | * the saved register state is "user" state only, not full |
184 | * trap state. | | 193 | * trap state. |
185 | */ | | 194 | */ |
186 | #define _UC_USER_BIT 30 | | 195 | #define _UC_USER_BIT 30 |
187 | #define _UC_USER (1LU << _UC_USER_BIT) | | 196 | #define _UC_USER (1LU << _UC_USER_BIT) |
188 | | | 197 | |
189 | /* Utility functions */ | | 198 | /* Utility functions */ |
190 | void pthread__unpark_all(pthread_queue_t *, pthread_t, pthread_mutex_t *) | | 199 | void pthread__unpark_all(pthread_queue_t *, pthread_t, pthread_mutex_t *) |
191 | PTHREAD_HIDE; | | 200 | PTHREAD_HIDE; |
192 | void pthread__unpark(pthread_queue_t *, pthread_t, pthread_mutex_t *) | | 201 | void pthread__unpark(pthread_queue_t *, pthread_t, pthread_mutex_t *) |
193 | PTHREAD_HIDE; | | 202 | PTHREAD_HIDE; |
194 | int pthread__park(pthread_t, pthread_mutex_t *, pthread_queue_t *, | | 203 | int pthread__park(pthread_t, pthread_mutex_t *, pthread_queue_t *, |
195 | const struct timespec *, int, const void *) | | 204 | const struct timespec *, int, const void *) |
196 | PTHREAD_HIDE; | | 205 | PTHREAD_HIDE; |
197 | pthread_mutex_t *pthread__hashlock(volatile const void *) PTHREAD_HIDE; | | 206 | pthread_mutex_t *pthread__hashlock(volatile const void *) PTHREAD_HIDE; |
198 | | | 207 | |
199 | /* Internal locking primitives */ | | 208 | /* Internal locking primitives */ |
200 | void pthread__lockprim_init(void) PTHREAD_HIDE; | | 209 | void pthread__lockprim_init(void) PTHREAD_HIDE; |
201 | void pthread_lockinit(pthread_spin_t *) PTHREAD_HIDE; | | 210 | void pthread_lockinit(pthread_spin_t *) PTHREAD_HIDE; |
202 | | | 211 | |
203 | static inline void pthread__spinlock(pthread_t, pthread_spin_t *) | | 212 | static inline void pthread__spinlock(pthread_t, pthread_spin_t *) |
204 | __attribute__((__always_inline__)); | | 213 | __attribute__((__always_inline__)); |
205 | static inline void | | 214 | static inline void |
206 | pthread__spinlock(pthread_t self, pthread_spin_t *lock) | | 215 | pthread__spinlock(pthread_t self, pthread_spin_t *lock) |
207 | { | | 216 | { |
208 | if (__predict_true((*self->pt_lockops.plo_try)(lock))) | | 217 | if (__predict_true((*self->pt_lockops.plo_try)(lock))) |
209 | return; | | 218 | return; |
210 | (*self->pt_lockops.plo_lock)(lock); | | 219 | (*self->pt_lockops.plo_lock)(lock); |
211 | } | | 220 | } |
212 | | | 221 | |
213 | static inline int pthread__spintrylock(pthread_t, pthread_spin_t *) | | 222 | static inline int pthread__spintrylock(pthread_t, pthread_spin_t *) |
214 | __attribute__((__always_inline__)); | | 223 | __attribute__((__always_inline__)); |
215 | static inline int | | 224 | static inline int |
216 | pthread__spintrylock(pthread_t self, pthread_spin_t *lock) | | 225 | pthread__spintrylock(pthread_t self, pthread_spin_t *lock) |
217 | { | | 226 | { |
218 | return (*self->pt_lockops.plo_try)(lock); | | 227 | return (*self->pt_lockops.plo_try)(lock); |
219 | } | | 228 | } |
220 | | | 229 | |
221 | static inline void pthread__spinunlock(pthread_t, pthread_spin_t *) | | 230 | static inline void pthread__spinunlock(pthread_t, pthread_spin_t *) |
222 | __attribute__((__always_inline__)); | | 231 | __attribute__((__always_inline__)); |
223 | static inline void | | 232 | static inline void |
224 | pthread__spinunlock(pthread_t self, pthread_spin_t *lock) | | 233 | pthread__spinunlock(pthread_t self, pthread_spin_t *lock) |
225 | { | | 234 | { |
226 | (*self->pt_lockops.plo_unlock)(lock); | | 235 | (*self->pt_lockops.plo_unlock)(lock); |
227 | } | | 236 | } |
228 | | | 237 | |
229 | extern const struct pthread_lock_ops *pthread__lock_ops; | | 238 | extern const struct pthread_lock_ops *pthread__lock_ops; |
230 | | | 239 | |
231 | int pthread__simple_locked_p(__cpu_simple_lock_t *) PTHREAD_HIDE; | | 240 | int pthread__simple_locked_p(__cpu_simple_lock_t *) PTHREAD_HIDE; |
232 | #define pthread__simple_lock_init(alp) (*pthread__lock_ops->plo_init)(alp) | | 241 | #define pthread__simple_lock_init(alp) (*pthread__lock_ops->plo_init)(alp) |
233 | #define pthread__simple_lock_try(alp) (*pthread__lock_ops->plo_try)(alp) | | 242 | #define pthread__simple_lock_try(alp) (*pthread__lock_ops->plo_try)(alp) |
234 | #define pthread__simple_unlock(alp) (*pthread__lock_ops->plo_unlock)(alp) | | 243 | #define pthread__simple_unlock(alp) (*pthread__lock_ops->plo_unlock)(alp) |
235 | | | 244 | |
236 | void pthread__testcancel(pthread_t) PTHREAD_HIDE; | | 245 | void pthread__testcancel(pthread_t) PTHREAD_HIDE; |
237 | int pthread__find(pthread_t) PTHREAD_HIDE; | | 246 | int pthread__find(pthread_t) PTHREAD_HIDE; |
238 | | | 247 | |
239 | #ifndef PTHREAD_MD_INIT | | 248 | #ifndef PTHREAD_MD_INIT |
240 | #define PTHREAD_MD_INIT | | 249 | #define PTHREAD_MD_INIT |
241 | #endif | | 250 | #endif |
242 | | | 251 | |
243 | #ifndef _INITCONTEXT_U_MD | | 252 | #ifndef _INITCONTEXT_U_MD |
244 | #define _INITCONTEXT_U_MD(ucp) | | 253 | #define _INITCONTEXT_U_MD(ucp) |
245 | #endif | | 254 | #endif |
246 | | | 255 | |
247 | #define _INITCONTEXT_U(ucp) do { \ | | 256 | #define _INITCONTEXT_U(ucp) do { \ |
248 | (ucp)->uc_flags = _UC_CPU | _UC_STACK; \ | | 257 | (ucp)->uc_flags = _UC_CPU | _UC_STACK; \ |
249 | _INITCONTEXT_U_MD(ucp) \ | | 258 | _INITCONTEXT_U_MD(ucp) \ |
250 | } while (/*CONSTCOND*/0) | | 259 | } while (/*CONSTCOND*/0) |
251 | | | 260 | |
252 | | | 261 | |
253 | #if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II) | | 262 | #if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II) |
254 | #error Either __HAVE_TLS_VARIANT_I or __HAVE_TLS_VARIANT_II must be defined | | 263 | #error Either __HAVE_TLS_VARIANT_I or __HAVE_TLS_VARIANT_II must be defined |
255 | #endif | | 264 | #endif |
256 | | | 265 | |
257 | #ifdef _PTHREAD_GETTCB_EXT | | 266 | #ifdef _PTHREAD_GETTCB_EXT |
258 | struct tls_tcb *_PTHREAD_GETTCB_EXT(void); | | 267 | struct tls_tcb *_PTHREAD_GETTCB_EXT(void); |
259 | #endif | | 268 | #endif |
260 | | | 269 | |
261 | static inline pthread_t __constfunc | | 270 | static inline pthread_t __constfunc |
262 | pthread__self(void) | | 271 | pthread__self(void) |
263 | { | | 272 | { |
264 | #if defined(_PTHREAD_GETTCB_EXT) | | 273 | #if defined(_PTHREAD_GETTCB_EXT) |
265 | struct tls_tcb * const tcb = _PTHREAD_GETTCB_EXT(); | | 274 | struct tls_tcb * const tcb = _PTHREAD_GETTCB_EXT(); |
266 | #elif defined(__HAVE___LWP_GETTCB_FAST) | | 275 | #elif defined(__HAVE___LWP_GETTCB_FAST) |
267 | struct tls_tcb * const tcb = __lwp_gettcb_fast(); | | 276 | struct tls_tcb * const tcb = __lwp_gettcb_fast(); |
268 | #else | | 277 | #else |
269 | struct tls_tcb * const tcb = __lwp_getprivate_fast(); | | 278 | struct tls_tcb * const tcb = __lwp_getprivate_fast(); |
270 | #endif | | 279 | #endif |
271 | return (pthread_t)tcb->tcb_pthread; | | 280 | return (pthread_t)tcb->tcb_pthread; |
272 | } | | 281 | } |
273 | | | 282 | |
274 | #define pthread__abort() \ | | 283 | #define pthread__abort() \ |
275 | pthread__assertfunc(__FILE__, __LINE__, __func__, "unreachable") | | 284 | pthread__assertfunc(__FILE__, __LINE__, __func__, "unreachable") |
276 | | | 285 | |
277 | #define pthread__assert(e) do { \ | | 286 | #define pthread__assert(e) do { \ |
278 | if (__predict_false(!(e))) \ | | 287 | if (__predict_false(!(e))) \ |
279 | pthread__assertfunc(__FILE__, __LINE__, __func__, #e); \ | | 288 | pthread__assertfunc(__FILE__, __LINE__, __func__, #e); \ |
280 | } while (/*CONSTCOND*/0) | | 289 | } while (/*CONSTCOND*/0) |
281 | | | 290 | |
282 | #define pthread__error(err, msg, e) do { \ | | 291 | #define pthread__error(err, msg, e) do { \ |
283 | if (__predict_false(!(e))) { \ | | 292 | if (__predict_false(!(e))) { \ |
284 | pthread__errorfunc(__FILE__, __LINE__, __func__, msg); \ | | 293 | pthread__errorfunc(__FILE__, __LINE__, __func__, msg); \ |
285 | return (err); \ | | 294 | return (err); \ |
286 | } \ | | 295 | } \ |
287 | } while (/*CONSTCOND*/0) | | 296 | } while (/*CONSTCOND*/0) |
288 | | | 297 | |
289 | void *pthread_tsd_init(size_t *) PTHREAD_HIDE; | | 298 | void *pthread_tsd_init(size_t *) PTHREAD_HIDE; |
290 | void pthread__destroy_tsd(pthread_t) PTHREAD_HIDE; | | 299 | void pthread__destroy_tsd(pthread_t) PTHREAD_HIDE; |
291 | void pthread__copy_tsd(pthread_t) PTHREAD_HIDE; | | 300 | void pthread__copy_tsd(pthread_t) PTHREAD_HIDE; |
292 | | | 301 | |
293 | __dead void pthread__assertfunc(const char *, int, const char *, const char *) | | 302 | __dead void pthread__assertfunc(const char *, int, const char *, const char *) |
294 | PTHREAD_HIDE; | | 303 | PTHREAD_HIDE; |
295 | void pthread__errorfunc(const char *, int, const char *, const char *) | | 304 | void pthread__errorfunc(const char *, int, const char *, const char *) |
296 | PTHREAD_HIDE; | | 305 | PTHREAD_HIDE; |
297 | char *pthread__getenv(const char *) PTHREAD_HIDE; | | 306 | char *pthread__getenv(const char *) PTHREAD_HIDE; |
298 | __dead void pthread__cancelled(void) PTHREAD_HIDE; | | 307 | __dead void pthread__cancelled(void) PTHREAD_HIDE; |
299 | void pthread__mutex_deferwake(pthread_t, pthread_mutex_t *) PTHREAD_HIDE; | | 308 | void pthread__mutex_deferwake(pthread_t, pthread_mutex_t *) PTHREAD_HIDE; |
300 | int pthread__checkpri(int) PTHREAD_HIDE; | | 309 | int pthread__checkpri(int) PTHREAD_HIDE; |
301 | int pthread__add_specific(pthread_t, pthread_key_t, const void *) PTHREAD_HIDE; | | 310 | int pthread__add_specific(pthread_t, pthread_key_t, const void *) PTHREAD_HIDE; |
302 | | | 311 | |
303 | #ifndef pthread__smt_pause | | 312 | #ifndef pthread__smt_pause |
304 | #define pthread__smt_pause() /* nothing */ | | 313 | #define pthread__smt_pause() /* nothing */ |
305 | #endif | | 314 | #endif |
306 | #ifndef pthread__smt_wake | | 315 | #ifndef pthread__smt_wake |
307 | #define pthread__smt_wake() /* nothing */ | | 316 | #define pthread__smt_wake() /* nothing */ |
308 | #endif | | 317 | #endif |
309 | | | 318 | |
310 | /* | | 319 | /* |
311 | * Bits in the owner field of the lock that indicate lock state. If the | | 320 | * Bits in the owner field of the lock that indicate lock state. If the |
312 | * WRITE_LOCKED bit is clear, then the owner field is actually a count of | | 321 | * WRITE_LOCKED bit is clear, then the owner field is actually a count of |
313 | * the number of readers. | | 322 | * the number of readers. |
314 | */ | | 323 | */ |
315 | #define RW_HAS_WAITERS 0x01 /* lock has waiters */ | | 324 | #define RW_HAS_WAITERS 0x01 /* lock has waiters */ |
316 | #define RW_WRITE_WANTED 0x02 /* >= 1 waiter is a writer */ | | 325 | #define RW_WRITE_WANTED 0x02 /* >= 1 waiter is a writer */ |
317 | #define RW_WRITE_LOCKED 0x04 /* lock is currently write locked */ | | 326 | #define RW_WRITE_LOCKED 0x04 /* lock is currently write locked */ |
318 | #define RW_UNUSED 0x08 /* currently unused */ | | 327 | #define RW_UNUSED 0x08 /* currently unused */ |
319 | | | 328 | |
320 | #define RW_FLAGMASK 0x0f | | 329 | #define RW_FLAGMASK 0x0f |
321 | | | 330 | |
322 | #define RW_READ_COUNT_SHIFT 4 | | 331 | #define RW_READ_COUNT_SHIFT 4 |
323 | #define RW_READ_INCR (1 << RW_READ_COUNT_SHIFT) | | 332 | #define RW_READ_INCR (1 << RW_READ_COUNT_SHIFT) |
324 | #define RW_THREAD ((uintptr_t)-RW_READ_INCR) | | 333 | #define RW_THREAD ((uintptr_t)-RW_READ_INCR) |
325 | | | 334 | |
326 | #endif /* _LIB_PTHREAD_INT_H */ | | 335 | #endif /* _LIB_PTHREAD_INT_H */ |