]>
Commit | Line | Data |
---|---|---|
7c6c5b0a JF |
1 | /* |
2 | * Copyright (c) 2000-2003, 2007 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 | * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 | |
25 | * All Rights Reserved | |
26 | * | |
27 | * Permission to use, copy, modify, and distribute this software and | |
28 | * its documentation for any purpose and without fee is hereby granted, | |
29 | * provided that the above copyright notice appears in all copies and | |
30 | * that both the copyright notice and this permission notice appear in | |
31 | * supporting documentation. | |
32 | * | |
33 | * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE | |
34 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
35 | * FOR A PARTICULAR PURPOSE. | |
36 | * | |
37 | * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR | |
38 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |
39 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, | |
40 | * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
41 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
42 | * | |
43 | */ | |
44 | /* | |
45 | * MkLinux | |
46 | */ | |
47 | ||
48 | /* | |
49 | * POSIX Threads - IEEE 1003.1c | |
50 | */ | |
51 | ||
52 | #ifndef _POSIX_PTHREAD_INTERNALS_H | |
53 | #define _POSIX_PTHREAD_INTERNALS_H | |
54 | ||
55 | // suppress pthread_attr_t typedef in sys/signal.h | |
56 | #define _PTHREAD_ATTR_T | |
57 | struct _pthread_attr_t; /* forward reference */ | |
58 | typedef struct _pthread_attr_t pthread_attr_t; | |
59 | ||
60 | #include <assert.h> | |
61 | #include <stddef.h> | |
62 | #include <stdint.h> | |
63 | #include <stdlib.h> | |
64 | #include <limits.h> | |
65 | #include <errno.h> | |
66 | #include <mach/mach.h> | |
67 | #include <mach/mach_error.h> | |
68 | #include <libkern/OSAtomic.h> | |
69 | ||
70 | ||
71 | #ifndef __POSIX_LIB__ | |
72 | #define __POSIX_LIB__ | |
73 | #endif | |
74 | ||
75 | #include "posix_sched.h" /* For POSIX scheduling policy & parameter */ | |
76 | #include <sys/queue.h> /* For POSIX scheduling policy & parameter */ | |
77 | #include "pthread_machdep.h" /* Machine-dependent definitions. */ | |
78 | #include "pthread_spinlock.h" /* spinlock definitions. */ | |
79 | ||
80 | TAILQ_HEAD(__pthread_list, _pthread); | |
3615a2f7 JF |
81 | |
82 | extern int __pthread_lock_debug; | |
83 | extern int __pthread_lock_old; | |
84 | ||
7c6c5b0a JF |
85 | extern struct __pthread_list __pthread_head; /* head of list of open files */ |
86 | extern pthread_lock_t _pthread_list_lock; | |
87 | extern size_t pthreadsize; | |
88 | /* | |
89 | * Compiled-in limits | |
90 | */ | |
91 | #define _EXTERNAL_POSIX_THREAD_KEYS_MAX 512 | |
92 | #define _INTERNAL_POSIX_THREAD_KEYS_MAX 256 | |
93 | #define _INTERNAL_POSIX_THREAD_KEYS_END 768 | |
94 | ||
95 | /* | |
96 | * Threads | |
97 | */ | |
98 | #define MAXTHREADNAMESIZE 64 | |
99 | #define _PTHREAD_T | |
100 | typedef struct _pthread | |
101 | { | |
102 | long sig; /* Unique signature for this structure */ | |
103 | struct __darwin_pthread_handler_rec *__cleanup_stack; | |
104 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
105 | uint32_t detached:8, | |
106 | inherit:8, | |
107 | policy:8, | |
108 | freeStackOnExit:1, | |
109 | newstyle:1, | |
110 | kernalloc:1, | |
111 | schedset:1, | |
112 | wqthread:1, | |
113 | wqkillset:1, | |
114 | pad:2; | |
115 | size_t guardsize; /* size in bytes to guard stack overflow */ | |
116 | #if !defined(__LP64__) | |
117 | int pad0; /* for backwards compatibility */ | |
118 | #endif | |
119 | struct sched_param param; | |
3615a2f7 JF |
120 | uint32_t cancel_error; |
121 | #if defined(__LP64__) | |
122 | uint32_t cancel_pad; /* pad value for alignment */ | |
123 | #endif | |
7c6c5b0a JF |
124 | struct _pthread *joiner; |
125 | #if !defined(__LP64__) | |
126 | int pad1; /* for backwards compatibility */ | |
127 | #endif | |
128 | void *exit_value; | |
129 | semaphore_t death; /* pthread_join() uses this to wait for death's call */ | |
130 | mach_port_t kernel_thread; /* kernel thread this thread is bound to */ | |
131 | void *(*fun)(void*);/* Thread start routine */ | |
132 | void *arg; /* Argment for thread start routine */ | |
133 | int cancel_state; /* Whether thread can be cancelled */ | |
134 | int err_no; /* thread-local errno */ | |
135 | void *tsd[_EXTERNAL_POSIX_THREAD_KEYS_MAX + _INTERNAL_POSIX_THREAD_KEYS_MAX]; /* Thread specific data */ | |
136 | void *stackaddr; /* Base of the stack (is aligned on vm_page_size boundary */ | |
137 | size_t stacksize; /* Size of the stack (is a multiple of vm_page_size and >= PTHREAD_STACK_MIN) */ | |
138 | mach_port_t reply_port; /* Cached MiG reply port */ | |
139 | #if defined(__LP64__) | |
140 | int pad2; /* for natural alignment */ | |
141 | #endif | |
142 | void *cthread_self; /* cthread_self() if somebody calls cthread_set_self() */ | |
143 | /* protected by list lock */ | |
144 | uint32_t childrun:1, | |
145 | parentcheck:1, | |
146 | childexit:1, | |
147 | pad3:29; | |
148 | #if defined(__LP64__) | |
149 | int pad4; /* for natural alignment */ | |
150 | #endif | |
151 | TAILQ_ENTRY(_pthread) plist; | |
152 | void * freeaddr; | |
153 | size_t freesize; | |
154 | mach_port_t joiner_notify; | |
155 | char pthread_name[MAXTHREADNAMESIZE]; /* including nulll the name */ | |
156 | int max_tsd_key; | |
157 | void * cur_workq; | |
158 | void * cur_workitem; | |
159 | uint64_t thread_id; | |
160 | } *pthread_t; | |
161 | ||
7c6c5b0a JF |
162 | /* |
163 | * Thread attributes | |
164 | */ | |
165 | struct _pthread_attr_t | |
166 | { | |
167 | long sig; /* Unique signature for this structure */ | |
168 | pthread_lock_t lock; | |
169 | uint32_t detached:8, | |
170 | inherit:8, | |
171 | policy:8, | |
172 | freeStackOnExit:1, | |
173 | fastpath:1, | |
174 | schedset:1, | |
175 | reserved1:5; | |
176 | size_t guardsize; /* size in bytes to guard stack overflow */ | |
177 | int reserved2; /* Should we free the stack when we exit? */ | |
178 | struct sched_param param; | |
179 | void *stackaddr; /* Base of the stack (is aligned on vm_page_size boundary */ | |
180 | size_t stacksize; /* Size of the stack (is a multiple of vm_page_size and >= PTHREAD_STACK_MIN) */ | |
181 | boolean_t reserved3; | |
182 | }; | |
183 | ||
184 | /* | |
185 | * Mutex attributes | |
186 | */ | |
187 | #define _PTHREAD_MUTEX_POLICY_NONE 0 | |
188 | #define _PTHREAD_MUTEX_POLICY_FAIRSHARE 1 | |
189 | #define _PTHREAD_MUTEX_POLICY_FIRSTFIT 2 | |
190 | #define _PTHREAD_MUTEX_POLICY_REALTIME 3 | |
191 | #define _PTHREAD_MUTEX_POLICY_ADAPTIVE 4 | |
192 | #define _PTHREAD_MUTEX_POLICY_PRIPROTECT 5 | |
193 | #define _PTHREAD_MUTEX_POLICY_PRIINHERIT 6 | |
194 | ||
195 | #define _PTHREAD_MUTEXATTR_T | |
196 | typedef struct | |
197 | { | |
198 | long sig; /* Unique signature for this structure */ | |
199 | int prioceiling; | |
200 | uint32_t protocol:2, /* protocol attribute */ | |
201 | type:2, /* mutex type */ | |
202 | pshared:2, | |
203 | policy:3, | |
204 | rfu:23; | |
205 | } pthread_mutexattr_t; | |
206 | ||
207 | /* | |
208 | * Mutex variables | |
209 | */ | |
210 | struct _pthread_mutex_options { | |
211 | uint32_t protocol:2, /* protocol */ | |
212 | type:2, /* mutex type */ | |
213 | pshared:2, /* mutex type */ | |
214 | policy:3, | |
215 | hold:2, | |
216 | misalign:1, /* 8 byte aligned? */ | |
3615a2f7 JF |
217 | notify:1, /* CV notify field for kernel */ |
218 | mutex:1, /* used in clrprepo that it is a mutex */ | |
219 | rfu:2, | |
7c6c5b0a JF |
220 | lock_count:16; |
221 | }; | |
222 | ||
223 | ||
224 | #define _PTHREAD_MTX_OPT_PSHARED 0x010 | |
3615a2f7 JF |
225 | #define _PTHREAD_MTX_OPT_HOLD 0x200 /* current owner of the mutex */ |
226 | #define _PTHREAD_MTX_OPT_NOMTX 0x400 /* no mutex refs held */ | |
227 | ||
228 | #define _PTHREAD_MTX_OPT_NOTIFY 0x1000 /* notify to drop mutex handling in cvwait */ | |
229 | #define _PTHREAD_MTX_OPT_MUTEX 0x2000 /* this is a mutex type */ | |
7c6c5b0a JF |
230 | |
231 | ||
232 | #define _PTHREAD_MUTEX_T | |
233 | typedef struct _pthread_mutex | |
234 | { | |
235 | long sig; /* Unique signature for this structure */ | |
236 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
237 | union { | |
238 | uint32_t value; | |
239 | struct _pthread_mutex_options options; | |
240 | } mtxopts; | |
241 | int16_t prioceiling; | |
242 | int16_t priority; /* Priority to restore when mutex unlocked */ | |
243 | uint32_t waiters; /* Count of threads waiting for this mutex */ | |
244 | pthread_t owner; /* Which thread has this mutex locked */ | |
245 | struct _pthread_mutex *next, *prev; /* List of other mutexes he owns */ | |
246 | struct _pthread_cond *busy; /* List of condition variables using this mutex */ | |
247 | semaphore_t sem; /* Semaphore used for waiting */ | |
248 | semaphore_t order; | |
249 | } pthread_mutex_t; | |
250 | ||
251 | ||
252 | typedef struct _npthread_mutex | |
253 | { | |
254 | /* keep same as pthread_mutex_t from here to .. */ | |
255 | long sig; /* Unique signature for this structure */ | |
256 | pthread_lock_t lock; /* Used for static init sequencing */ | |
257 | union { | |
258 | uint32_t value; | |
259 | struct _pthread_mutex_options options; | |
260 | } mtxopts; | |
261 | int16_t prioceiling; | |
262 | int16_t priority; /* Priority to restore when mutex unlocked */ | |
263 | uint32_t m_seq[3]; | |
264 | #if defined(__LP64__) | |
265 | uint64_t m_tid; /* Which thread has this mutex locked */ | |
266 | uint32_t * m_lseqaddr; | |
267 | uint32_t * m_useqaddr; | |
268 | uint32_t reserved[2]; | |
269 | #else | |
270 | uint32_t * m_lseqaddr; | |
271 | uint64_t m_tid; /* Which thread has this mutex locked */ | |
272 | uint32_t * m_useqaddr; | |
273 | #endif | |
274 | } npthread_mutex_t; | |
275 | ||
276 | ||
277 | ||
278 | ||
279 | /* | |
280 | * Condition variable attributes | |
281 | */ | |
282 | #define _PTHREAD_CONDATTR_T | |
283 | typedef struct | |
284 | { | |
285 | long sig; /* Unique signature for this structure */ | |
286 | uint32_t pshared:2, /* pshared */ | |
287 | unsupported:30; | |
288 | } pthread_condattr_t; | |
289 | ||
290 | /* | |
291 | * Condition variables | |
292 | */ | |
293 | #define _PTHREAD_COND_T | |
294 | typedef struct _pthread_cond | |
295 | { | |
296 | long sig; /* Unique signature for this structure */ | |
297 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
298 | uint32_t waiters:15, /* Number of threads waiting */ | |
299 | sigspending:15, /* Number of outstanding signals */ | |
300 | pshared:2; | |
301 | struct _pthread_cond *next, *prev; /* List of condition variables using mutex */ | |
302 | struct _pthread_mutex *busy; /* mutex associated with variable */ | |
303 | semaphore_t sem; /* Kernel semaphore */ | |
304 | } pthread_cond_t; | |
305 | ||
306 | ||
307 | typedef struct _npthread_cond | |
308 | { | |
309 | long sig; /* Unique signature for this structure */ | |
310 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
311 | uint32_t rfu:29, /* not in use*/ | |
312 | misalign: 1, /* structure is not aligned to 8 byte boundary */ | |
313 | pshared:2; | |
314 | struct _npthread_mutex *busy; /* mutex associated with variable */ | |
315 | uint32_t c_seq[3]; | |
316 | #if defined(__LP64__) | |
317 | uint32_t reserved[3]; | |
318 | #endif /* __LP64__ */ | |
319 | } npthread_cond_t; | |
320 | ||
321 | /* | |
322 | * Initialization control (once) variables | |
323 | */ | |
324 | #define _PTHREAD_ONCE_T | |
325 | typedef struct | |
326 | { | |
327 | long sig; /* Unique signature for this structure */ | |
328 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
329 | } pthread_once_t; | |
330 | ||
331 | #define _PTHREAD_RWLOCKATTR_T | |
332 | typedef struct { | |
333 | long sig; /* Unique signature for this structure */ | |
334 | int pshared; | |
335 | int rfu[2]; /* reserved for future use */ | |
336 | } pthread_rwlockattr_t; | |
337 | ||
338 | #define _PTHREAD_RWLOCK_T | |
339 | typedef struct { | |
340 | long sig; | |
341 | pthread_mutex_t lock; /* monitor lock */ | |
342 | int state; | |
343 | pthread_cond_t read_signal; | |
344 | pthread_cond_t write_signal; | |
345 | int blocked_writers; | |
346 | int reserved; | |
347 | pthread_t owner; | |
348 | int rfu[1]; | |
349 | int pshared; | |
350 | } pthread_rwlock_t; | |
351 | ||
3615a2f7 JF |
352 | #define PTHRW_RFU_64BIT 124 /* 31 * sizeof(uint32_t) */ |
353 | #define PTHRW_RFU_32BIT 72 /* 18 * sizeof(uint32_t) */ | |
354 | ||
7c6c5b0a JF |
355 | #define _PTHREAD_RWLOCK_T |
356 | typedef struct { | |
357 | long sig; | |
358 | pthread_lock_t lock; | |
359 | #if defined(__LP64__) | |
360 | int reserv; | |
361 | volatile uint32_t rw_seq[4]; | |
362 | pthread_t rw_owner; | |
363 | #else /* __LP64__ */ | |
364 | volatile uint32_t rw_seq[4]; | |
365 | pthread_t rw_owner; | |
366 | int reserv; | |
367 | #endif /* __LP64__ */ | |
3615a2f7 JF |
368 | volatile uint32_t * rw_lcntaddr; |
369 | volatile uint32_t * rw_seqaddr; | |
370 | volatile uint32_t * rw_ucntaddr; | |
7c6c5b0a JF |
371 | uint32_t rw_flags; |
372 | int misalign; | |
373 | #if defined(__LP64__) | |
3615a2f7 | 374 | char rfu[PTHRW_RFU_64BIT]; |
7c6c5b0a | 375 | #else /* __LP64__ */ |
3615a2f7 | 376 | char rfu[PTHRW_RFU_32BIT]; |
7c6c5b0a JF |
377 | #endif /* __LP64__ */ |
378 | int pshared; | |
379 | } npthread_rwlock_t; | |
380 | ||
381 | /* flags for rw_flags */ | |
382 | #define PTHRW_KERN_PROCESS_SHARED 0x10 | |
383 | #define PTHRW_KERN_PROCESS_PRIVATE 0x20 | |
384 | #define PTHRW_KERN_PROCESS_FLAGS_MASK 0x30 | |
3615a2f7 JF |
385 | #define _PTHREAD_RWLOCK_UPGRADE_TRY 0x10000 |
386 | ||
387 | /* New model bits on Lword */ | |
388 | #define PTH_RWL_KBIT 0x01 /* users cannot acquire in user mode */ | |
389 | #define PTH_RWL_EBIT 0x02 /* exclusive lock in progress */ | |
390 | #define PTH_RWL_WBIT 0x04 /* write waiters pending in kernel */ | |
391 | #define PTH_RWL_PBIT 0x04 /* prepost (cv) pending in kernel */ | |
392 | #define PTH_RWL_YBIT 0x08 /* yielding write waiters pending in kernel */ | |
393 | #define PTH_RWL_RETRYBIT 0x08 /* mutex retry wait */ | |
394 | #define PTH_RWL_LBIT 0x10 /* long read in progress */ | |
395 | #define PTH_RWL_MTXNONE 0x10 /* indicates the cvwait does not have mutex held */ | |
396 | #define PTH_RWL_UBIT 0x20 /* upgrade request pending */ | |
397 | #define PTH_RWL_MTX_WAIT 0x20 /* in cvar in mutex wait */ | |
398 | #define PTH_RWL_RBIT 0x40 /* reader pending in kernel(not used) */ | |
399 | #define PTH_RWL_MBIT 0x40 /* overlapping grants from kernel */ | |
400 | #define PTH_RWL_TRYLKBIT 0x40 /* sets try lock attempt */ | |
401 | #define PTH_RWL_IBIT 0x80 /* lock reset, held untill first succeesful unlock */ | |
402 | ||
403 | /* UBIT values for mutex, cvar */ | |
404 | #define PTH_RWU_SBIT 0x01 | |
405 | #define PTH_RWU_BBIT 0x02 | |
406 | ||
407 | #define PTHRW_RWL_INIT PTH_RWL_IBIT /* reset on the lock bits (U)*/ | |
408 | #define PTHRW_RWLOCK_INIT (PTH_RWL_IBIT | PTH_RWL_RBIT) /* reset on the lock bits (U)*/ | |
409 | #define PTH_RWLOCK_RESET_RBIT 0xffffffbf | |
7c6c5b0a | 410 | |
3615a2f7 JF |
411 | #define PTHRW_INC 0x100 |
412 | #define PTHRW_BIT_MASK 0x000000ff | |
7c6c5b0a | 413 | |
3615a2f7 | 414 | #define PTHRW_UN_BIT_MASK 0x000000bf /* remove overlap bit */ |
7c6c5b0a | 415 | |
7c6c5b0a | 416 | |
3615a2f7 JF |
417 | /* New model bits on Sword */ |
418 | #define PTH_RWS_SBIT 0x01 /* kernel transition seq not set yet*/ | |
419 | #define PTH_RWS_IBIT 0x02 /* Sequence is not set on return from kernel */ | |
420 | ||
421 | #define PTH_RWS_CV_CBIT PTH_RWS_SBIT /* kernel has cleared all info w.r.s.t CV */ | |
422 | #define PTH_RWS_CV_PBIT PTH_RWS_IBIT /* kernel has prepost/fake structs only,no waiters */ | |
423 | #define PTH_RWS_CV_BITSALL (PTH_RWS_CV_CBIT | PTH_RWS_CV_PBIT) | |
424 | #define PTH_RWS_CV_MBIT PTH_RWL_MBIT /* to indicate prepost return from kernel */ | |
425 | #define PTH_RWS_CV_RESET_PBIT 0xfffffffd | |
426 | ||
427 | #define PTH_RWS_WSVBIT 0x04 /* save W bit */ | |
428 | #define PTH_RWS_USVBIT 0x08 /* save U bit */ | |
429 | #define PTH_RWS_YSVBIT 0x10 /* save Y bit */ | |
430 | #define PTHRW_RWS_INIT PTH_RWS_SBIT /* reset on the lock bits (U)*/ | |
431 | #define PTHRW_RWS_SAVEMASK (PTH_RWS_WSVBIT|PTH_RWS_USVBIT|PTH_RWS_YSVBIT) /*save bits mask*/ | |
432 | #define PTHRW_SW_Reset_BIT_MASK 0x000000fe /* remove S bit and get rest of the bits */ | |
7c6c5b0a JF |
433 | |
434 | #define PTHRW_COUNT_SHIFT 8 | |
435 | #define PTHRW_COUNT_MASK 0xffffff00 | |
436 | #define PTHRW_MAX_READERS 0xffffff00 | |
437 | ||
438 | ||
439 | #define PTHREAD_MTX_TID_SWITCHING (uint64_t)-1 | |
440 | ||
3615a2f7 JF |
441 | /* new L word defns */ |
442 | #define can_rwl_readinuser(x) ((((x) & (PTH_RWL_UBIT | PTH_RWL_WBIT | PTH_RWL_KBIT)) == 0)||(((x) & PTH_RWL_LBIT) != 0)) | |
443 | #define can_rwl_longreadinuser(x) (((x) & (PTH_RWL_UBIT | PTH_RWL_WBIT | PTH_RWL_KBIT | PTH_RWL_YBIT)) == 0) | |
444 | #define is_rwl_ebit_set(x) (((x) & PTH_RWL_EBIT) != 0) | |
445 | #define is_rwl_eubit_set(x) (((x) & (PTH_RWL_EBIT | PTH_RWL_UBIT)) != 0) | |
446 | #define is_rwl_wbit_set(x) (((x) & PTH_RWL_WBIT) != 0) | |
447 | #define is_rwl_lbit_set(x) (((x) & PTH_RWL_LBIT) != 0) | |
448 | #define is_rwl_ebit_clear(x) (((x) & PTH_RWL_EBIT) == 0) | |
449 | #define is_rwl_lbit_clear(x) (((x) & PTH_RWL_LBIT) == 0) | |
450 | #define is_rwl_readoverlap(x) (((x) & PTH_RWL_MBIT) != 0) | |
451 | ||
452 | /* S word checks */ | |
453 | #define is_rws_setseq(x) (((x) & PTH_RWS_SBIT)) | |
454 | #define is_rws_setunlockinit(x) (((x) & PTH_RWS_IBIT)) | |
7c6c5b0a JF |
455 | |
456 | /* is x lower than Y */ | |
3615a2f7 JF |
457 | static inline int is_seqlower(uint32_t x, uint32_t y) { |
458 | if (x < y) { | |
459 | if ((y-x) < (PTHRW_MAX_READERS/2)) | |
460 | return(1); | |
461 | } else { | |
462 | if ((x-y) > (PTHRW_MAX_READERS/2)) | |
463 | return(1); | |
464 | } | |
465 | return(0); | |
466 | } | |
467 | ||
7c6c5b0a | 468 | /* is x lower than or eq Y */ |
3615a2f7 JF |
469 | static inline int is_seqlower_eq(uint32_t x, uint32_t y) { |
470 | if (x==y) | |
471 | return(1); | |
472 | else | |
473 | return(is_seqlower(x,y)); | |
474 | } | |
7c6c5b0a JF |
475 | |
476 | /* is x greater than Y */ | |
3615a2f7 JF |
477 | static inline int is_seqhigher(uint32_t x, uint32_t y) { |
478 | if (x > y) { | |
479 | if ((x-y) < (PTHRW_MAX_READERS/2)) | |
480 | return(1); | |
481 | } else { | |
482 | if ((y-x) > (PTHRW_MAX_READERS/2)) | |
483 | return(1); | |
484 | } | |
485 | return(0); | |
486 | } | |
7c6c5b0a JF |
487 | |
488 | static inline int diff_genseq(uint32_t x, uint32_t y) { | |
3615a2f7 JF |
489 | if (x == y) { |
490 | return(0); | |
491 | } else if (x > y) { | |
7c6c5b0a JF |
492 | return(x-y); |
493 | } else { | |
3615a2f7 | 494 | return((PTHRW_MAX_READERS - y) + x + PTHRW_INC); |
7c6c5b0a JF |
495 | } |
496 | } | |
497 | ||
498 | /* keep the size to 64bytes for both 64 and 32 */ | |
499 | #define _PTHREAD_WORKQUEUE_ATTR_T | |
500 | typedef struct { | |
501 | uint32_t sig; | |
502 | int queueprio; | |
503 | int overcommit; | |
504 | unsigned int resv2[13]; | |
505 | } pthread_workqueue_attr_t; | |
506 | ||
507 | #define _PTHREAD_WORKITEM_T | |
508 | typedef struct _pthread_workitem { | |
509 | TAILQ_ENTRY(_pthread_workitem) item_entry; /* pthread_workitem list in prio */ | |
510 | void (*func)(void *); | |
511 | void * func_arg; | |
512 | struct _pthread_workqueue * workq; | |
513 | unsigned int flags; | |
3615a2f7 | 514 | unsigned int fromcache; /* padding for 64bit */ |
7c6c5b0a JF |
515 | } * pthread_workitem_t; |
516 | ||
517 | #define PTH_WQITEM_INKERNEL_QUEUE 1 | |
518 | #define PTH_WQITEM_RUNNING 2 | |
519 | #define PTH_WQITEM_COMPLETED 4 | |
520 | #define PTH_WQITEM_REMOVED 8 | |
521 | #define PTH_WQITEM_BARRIER 0x10 | |
522 | #define PTH_WQITEM_DESTROY 0x20 | |
523 | #define PTH_WQITEM_NOTINLIST 0x40 | |
524 | #define PTH_WQITEM_APPLIED 0x80 | |
525 | #define PTH_WQITEM_KERN_COUNT 0x100 | |
526 | ||
3615a2f7 JF |
527 | /* try to fit these within multiple of pages (8 pages for now) */ |
528 | #define WORKITEM_POOL_SIZE 680 | |
529 | /* ensure some multiple of the chunk is the pool size */ | |
530 | #define WORKITEM_CHUNK_SIZE 40 | |
531 | ||
532 | #define WORKITEM_STARTPOOL_SIZE WORKITEM_CHUNK_SIZE | |
533 | ||
7c6c5b0a JF |
534 | TAILQ_HEAD(__pthread_workitem_pool, _pthread_workitem); |
535 | extern struct __pthread_workitem_pool __pthread_workitem_pool_head; /* head list of workitem pool */ | |
536 | ||
7c6c5b0a JF |
537 | #define _PTHREAD_WORKQUEUE_HEAD_T |
538 | typedef struct _pthread_workqueue_head { | |
539 | TAILQ_HEAD(, _pthread_workqueue) wqhead; | |
540 | struct _pthread_workqueue * next_workq; | |
541 | } * pthread_workqueue_head_t; | |
542 | ||
543 | ||
3615a2f7 | 544 | /* sized to be 128 bytes both in 32 and 64bit archs */ |
7c6c5b0a JF |
545 | #define _PTHREAD_WORKQUEUE_T |
546 | typedef struct _pthread_workqueue { | |
547 | unsigned int sig; /* Unique signature for this structure */ | |
548 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
549 | TAILQ_ENTRY(_pthread_workqueue) wq_list; /* workqueue list in prio */ | |
550 | TAILQ_HEAD(, _pthread_workitem) item_listhead; /* pthread_workitem list in prio */ | |
551 | TAILQ_HEAD(, _pthread_workitem) item_kernhead; /* pthread_workitem list in prio */ | |
552 | unsigned int flags; | |
553 | size_t stacksize; | |
554 | int istimeshare; | |
555 | int importance; | |
556 | int affinity; | |
557 | int queueprio; | |
558 | int barrier_count; | |
559 | int kq_count; | |
560 | void (*term_callback)(struct _pthread_workqueue *,void *); | |
561 | void * term_callarg; | |
562 | pthread_workqueue_head_t headp; | |
563 | int overcommit; | |
3615a2f7 | 564 | #if !defined(__LP64__) |
7c6c5b0a JF |
565 | unsigned int rev2[12]; |
566 | #endif | |
567 | } * pthread_workqueue_t; | |
568 | ||
569 | #define PTHREAD_WORKQ_IN_CREATION 1 | |
570 | #define PTHREAD_WORKQ_IN_TERMINATE 2 | |
571 | #define PTHREAD_WORKQ_BARRIER_ON 4 | |
572 | #define PTHREAD_WORKQ_TERM_ON 8 | |
573 | #define PTHREAD_WORKQ_DESTROYED 0x10 | |
574 | #define PTHREAD_WORKQ_REQUEUED 0x20 | |
575 | #define PTHREAD_WORKQ_SUSPEND 0x40 | |
576 | ||
3615a2f7 | 577 | #define WORKQUEUE_POOL_SIZE 16 |
7c6c5b0a JF |
578 | TAILQ_HEAD(__pthread_workqueue_pool, _pthread_workqueue); |
579 | extern struct __pthread_workqueue_pool __pthread_workqueue_pool_head; /* head list of workqueue pool */ | |
580 | ||
3615a2f7 | 581 | #include "pthread_spis.h" |
7c6c5b0a JF |
582 | |
583 | #if defined(__i386__) || defined(__ppc64__) || defined(__x86_64__) || (defined(__arm__) && (defined(_ARM_ARCH_7) || !defined(_ARM_ARCH_6) || !defined(__thumb__))) | |
584 | /* | |
585 | * Inside libSystem, we can use r13 or %gs directly to get access to the | |
586 | * thread-specific data area. The current thread is in the first slot. | |
587 | */ | |
588 | inline static pthread_t __attribute__((__pure__)) | |
589 | _pthread_self_direct(void) | |
590 | { | |
3615a2f7 JF |
591 | pthread_t ret; |
592 | ||
7c6c5b0a | 593 | #if defined(__i386__) || defined(__x86_64__) |
3615a2f7 | 594 | ret = (pthread_t) _pthread_getspecific_direct(0); |
7c6c5b0a JF |
595 | #elif defined(__ppc64__) |
596 | register const pthread_t __pthread_self asm ("r13"); | |
597 | ret = __pthread_self; | |
598 | #elif defined(__arm__) && defined(_ARM_ARCH_6) | |
3615a2f7 | 599 | ret = (pthread_t) _pthread_getspecific_direct(0); |
7c6c5b0a | 600 | #elif defined(__arm__) && !defined(_ARM_ARCH_6) |
3615a2f7 | 601 | ret = (pthread_t) _pthread_getspecific_direct(0); |
7c6c5b0a JF |
602 | #endif |
603 | return ret; | |
604 | } | |
605 | #define pthread_self() _pthread_self_direct() | |
606 | #endif | |
607 | ||
608 | #define _PTHREAD_DEFAULT_INHERITSCHED PTHREAD_INHERIT_SCHED | |
609 | #define _PTHREAD_DEFAULT_PROTOCOL PTHREAD_PRIO_NONE | |
610 | #define _PTHREAD_DEFAULT_PRIOCEILING 0 | |
611 | #define _PTHREAD_DEFAULT_POLICY SCHED_OTHER | |
612 | #define _PTHREAD_DEFAULT_STACKSIZE 0x80000 /* 512K */ | |
613 | #define _PTHREAD_DEFAULT_PSHARED PTHREAD_PROCESS_PRIVATE | |
614 | ||
615 | #define _PTHREAD_NO_SIG 0x00000000 | |
616 | #define _PTHREAD_MUTEX_ATTR_SIG 0x4D545841 /* 'MTXA' */ | |
617 | #define _PTHREAD_MUTEX_SIG 0x4D555458 /* 'MUTX' */ | |
618 | #define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 /* [almost] ~'MUTX' */ | |
3615a2f7 JF |
619 | #define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1 |
620 | #define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2 | |
621 | #define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3 | |
622 | #define _PTHREAD_MUTEX_SIG_init_MASK 0xfffffff0 | |
623 | #define _PTHREAD_MUTEX_SIG_CMP 0x32AAABA0 | |
7c6c5b0a JF |
624 | #define _PTHREAD_COND_ATTR_SIG 0x434E4441 /* 'CNDA' */ |
625 | #define _PTHREAD_COND_SIG 0x434F4E44 /* 'COND' */ | |
626 | #define _PTHREAD_COND_SIG_init 0x3CB0B1BB /* [almost] ~'COND' */ | |
627 | #define _PTHREAD_ATTR_SIG 0x54484441 /* 'THDA' */ | |
628 | #define _PTHREAD_ONCE_SIG 0x4F4E4345 /* 'ONCE' */ | |
629 | #define _PTHREAD_ONCE_SIG_init 0x30B1BCBA /* [almost] ~'ONCE' */ | |
630 | #define _PTHREAD_SIG 0x54485244 /* 'THRD' */ | |
631 | #define _PTHREAD_RWLOCK_ATTR_SIG 0x52574C41 /* 'RWLA' */ | |
632 | #define _PTHREAD_RWLOCK_SIG 0x52574C4B /* 'RWLK' */ | |
633 | #define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4 /* [almost] ~'RWLK' */ | |
634 | ||
635 | ||
636 | #define _PTHREAD_KERN_COND_SIG 0x12345678 /* */ | |
637 | #define _PTHREAD_KERN_MUTEX_SIG 0x34567812 /* */ | |
638 | #define _PTHREAD_KERN_RWLOCK_SIG 0x56781234 /* */ | |
639 | ||
640 | #define _PTHREAD_CREATE_PARENT 4 | |
641 | #define _PTHREAD_EXITED 8 | |
642 | // 4597450: begin | |
643 | #define _PTHREAD_WASCANCEL 0x10 | |
644 | // 4597450: end | |
645 | ||
646 | #if defined(DEBUG) | |
647 | #define _PTHREAD_MUTEX_OWNER_SELF pthread_self() | |
648 | #else | |
649 | #define _PTHREAD_MUTEX_OWNER_SELF (pthread_t)0x12141968 | |
650 | #endif | |
651 | #define _PTHREAD_MUTEX_OWNER_SWITCHING (pthread_t)(~0) | |
652 | ||
653 | #define _PTHREAD_CANCEL_STATE_MASK 0x01 | |
654 | #define _PTHREAD_CANCEL_TYPE_MASK 0x02 | |
655 | #define _PTHREAD_CANCEL_PENDING 0x10 /* pthread_cancel() has been called for this thread */ | |
656 | ||
657 | extern boolean_t swtch_pri(int); | |
658 | ||
659 | #ifndef PTHREAD_MACH_CALL | |
660 | #define PTHREAD_MACH_CALL(expr, ret) (ret) = (expr) | |
661 | #endif | |
662 | ||
663 | /* Prototypes. */ | |
664 | ||
665 | /* Functions defined in machine-dependent files. */ | |
666 | extern vm_address_t _sp(void); | |
667 | extern vm_address_t _adjust_sp(vm_address_t sp); | |
668 | extern void _pthread_setup(pthread_t th, void (*f)(pthread_t), void *sp, int suspended, int needresume); | |
669 | ||
670 | extern void _pthread_tsd_cleanup(pthread_t self); | |
671 | ||
3615a2f7 JF |
672 | __private_extern__ void __mtx_holdlock(npthread_mutex_t *mutex, uint32_t diff, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp, uint64_t *tidp); |
673 | __private_extern__ int __mtx_droplock(npthread_mutex_t *mutex, uint32_t diff, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp); | |
674 | __private_extern__ int __mtx_updatebits(npthread_mutex_t *mutex, uint32_t updateval, int firstfiti, int fromcond, uint64_t selfid); | |
7c6c5b0a JF |
675 | |
676 | /* syscall interfaces */ | |
677 | extern uint32_t __psynch_mutexwait(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags); | |
678 | extern uint32_t __psynch_mutexdrop(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags); | |
3615a2f7 JF |
679 | |
680 | extern uint32_t __psynch_cvbroad(pthread_cond_t * cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid); | |
681 | extern uint32_t __psynch_cvsignal(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid, uint32_t flags); | |
682 | extern uint32_t __psynch_cvwait(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, pthread_mutex_t * mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec); | |
683 | extern uint32_t __psynch_cvclrprepost(void * cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags); | |
7c6c5b0a JF |
684 | extern uint32_t __psynch_rw_longrdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); |
685 | extern uint32_t __psynch_rw_yieldwrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); | |
686 | extern int __psynch_rw_downgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); | |
687 | extern uint32_t __psynch_rw_upgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); | |
688 | extern uint32_t __psynch_rw_rdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); | |
689 | extern uint32_t __psynch_rw_wrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); | |
690 | extern uint32_t __psynch_rw_unlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); | |
691 | extern uint32_t __psynch_rw_unlock2(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags); | |
7c6c5b0a JF |
692 | |
693 | __private_extern__ semaphore_t new_sem_from_pool(void); | |
694 | __private_extern__ void restore_sem_to_pool(semaphore_t); | |
695 | __private_extern__ void _pthread_atfork_queue_init(void); | |
696 | int _pthread_lookup_thread(pthread_t thread, mach_port_t * port, int only_joinable); | |
697 | int _pthread_join_cleanup(pthread_t thread, void ** value_ptr, int conforming); | |
3615a2f7 | 698 | __private_extern__ int proc_setthreadname(void * buffer, int buffersize); |
7c6c5b0a JF |
699 | |
700 | #endif /* _POSIX_PTHREAD_INTERNALS_H */ |