]>
Commit | Line | Data |
---|---|---|
e9ce8d39 A |
1 | /* |
2 | * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 | |
3 | * All Rights Reserved | |
4 | * | |
5 | * Permission to use, copy, modify, and distribute this software and | |
6 | * its documentation for any purpose and without fee is hereby granted, | |
7 | * provided that the above copyright notice appears in all copies and | |
8 | * that both the copyright notice and this permission notice appear in | |
9 | * supporting documentation. | |
10 | * | |
11 | * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE | |
12 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
13 | * FOR A PARTICULAR PURPOSE. | |
14 | * | |
15 | * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR | |
16 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |
17 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, | |
18 | * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | |
19 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
20 | * | |
21 | */ | |
22 | /* | |
23 | * MkLinux | |
24 | */ | |
25 | ||
26 | /* | |
27 | * POSIX Threads - IEEE 1003.1c | |
28 | */ | |
29 | ||
30 | #ifndef _POSIX_PTHREAD_INTERNALS_H | |
31 | #define _POSIX_PTHREAD_INTERNALS_H | |
32 | ||
33 | ||
34 | #include <assert.h> | |
35 | #include <mach/port.h> | |
36 | #include <mach/mach_error.h> | |
37 | #include <mach/message.h> | |
38 | #include <mach/machine/vm_types.h> | |
39 | #include <mach/std_types.h> | |
40 | #include <mach/policy.h> | |
41 | #include <mach/sync.h> | |
42 | #include <mach/sync_policy.h> | |
43 | #include <mach/mach_traps.h> | |
44 | #include <mach/thread_switch.h> | |
45 | #include <mach/mach_host.h> | |
46 | #include <mach/mach.h> /* For generic MACH support */ | |
47 | ||
48 | ||
49 | #ifndef __POSIX_LIB__ | |
50 | #define __POSIX_LIB__ | |
51 | #endif | |
52 | ||
53 | #include "posix_sched.h" /* For POSIX scheduling policy & parameter */ | |
54 | #include "pthread_machdep.h" /* Machine-dependent definitions. */ | |
55 | ||
56 | extern kern_return_t syscall_thread_switch(mach_port_name_t, int, mach_msg_timeout_t); | |
57 | ||
58 | /* | |
59 | * Compiled-in limits | |
60 | */ | |
61 | #undef _POSIX_THREAD_KEYS_MAX | |
62 | #define _POSIX_THREAD_KEYS_MAX 128 | |
63 | ||
64 | /* | |
65 | * Threads | |
66 | */ | |
67 | typedef struct _pthread | |
68 | { | |
69 | long sig; /* Unique signature for this structure */ | |
70 | struct _pthread_handler_rec *cleanup_stack; | |
71 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
72 | int detached; | |
73 | int inherit; | |
74 | int policy; | |
75 | struct sched_param param; | |
76 | struct _pthread_mutex *mutexes; | |
5b2abdfb A |
77 | struct _pthread *joiner; |
78 | int pad1; | |
79 | void *exit_value; | |
80 | semaphore_t death; /* pthread_join() uses this to wait for death's call */ | |
e9ce8d39 A |
81 | mach_port_t kernel_thread; /* kernel thread this thread is bound to */ |
82 | void *(*fun)(void*);/* Thread start routine */ | |
83 | void *arg; /* Argment for thread start routine */ | |
84 | int cancel_state; /* Whether thread can be cancelled */ | |
5b2abdfb | 85 | int err_no; /* thread-local errno */ |
e9ce8d39 A |
86 | void *tsd[_POSIX_THREAD_KEYS_MAX]; /* Thread specific data */ |
87 | void *stackaddr; /* Base of the stack (is aligned on vm_page_size boundary */ | |
88 | size_t stacksize; /* Size of the stack (is a multiple of vm_page_size and >= PTHREAD_STACK_MIN) */ | |
89 | mach_port_t reply_port; /* Cached MiG reply port */ | |
90 | void *cthread_self; /* cthread_self() if somebody calls cthread_set_self() */ | |
91 | boolean_t freeStackOnExit;/* Should we free the stack when we're done? */ | |
92 | } *pthread_t; | |
93 | ||
94 | ||
95 | /* | |
96 | * Thread attributes | |
97 | */ | |
98 | typedef struct | |
99 | { | |
100 | long sig; /* Unique signature for this structure */ | |
101 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
102 | int detached; | |
103 | int inherit; | |
104 | int policy; | |
105 | struct sched_param param; | |
106 | void *stackaddr; /* Base of the stack (is aligned on vm_page_size boundary */ | |
107 | size_t stacksize; /* Size of the stack (is a multiple of vm_page_size and >= PTHREAD_STACK_MIN) */ | |
108 | boolean_t freeStackOnExit;/* Should we free the stack when we exit? */ | |
109 | } pthread_attr_t; | |
110 | ||
111 | /* | |
112 | * Mutex attributes | |
113 | */ | |
114 | typedef struct | |
115 | { | |
116 | long sig; /* Unique signature for this structure */ | |
117 | int prioceiling; | |
5b2abdfb A |
118 | u_int32_t protocol:2, /* protocol attribute */ |
119 | type:2, /* mutex type */ | |
120 | rfu:28; | |
e9ce8d39 A |
121 | } pthread_mutexattr_t; |
122 | ||
123 | /* | |
124 | * Mutex variables | |
125 | */ | |
126 | typedef struct _pthread_mutex | |
127 | { | |
128 | long sig; /* Unique signature for this structure */ | |
129 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
5b2abdfb A |
130 | int waiters:30, /* Count of threads waiting for this mutex */ |
131 | def:1, | |
132 | cond_lock:1; /* Is there a condition locking me? */ | |
e9ce8d39 | 133 | pthread_t owner; /* Which thread has this mutex locked */ |
5b2abdfb A |
134 | mach_port_t sem; /* Semaphore used for waiting */ |
135 | u_int32_t protocol:2, /* protocol */ | |
136 | type:2, /* mutex type */ | |
137 | rfu:12, | |
138 | lock_count:16; | |
e9ce8d39 A |
139 | struct _pthread_mutex *next, *prev; /* List of other mutexes he owns */ |
140 | struct _pthread_cond *busy; /* List of condition variables using this mutex */ | |
5b2abdfb A |
141 | int prioceiling; |
142 | int priority; /* Priority to restore when mutex unlocked */ | |
e9ce8d39 A |
143 | } pthread_mutex_t; |
144 | ||
145 | /* | |
146 | * Condition variable attributes | |
147 | */ | |
148 | typedef struct | |
149 | { | |
150 | long sig; /* Unique signature for this structure */ | |
151 | int unsupported; | |
152 | } pthread_condattr_t; | |
153 | ||
154 | /* | |
155 | * Condition variables | |
156 | */ | |
157 | typedef struct _pthread_cond | |
158 | { | |
159 | long sig; /* Unique signature for this structure */ | |
160 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
161 | mach_port_t sem; /* Kernel semaphore */ | |
162 | struct _pthread_cond *next, *prev; /* List of condition variables using mutex */ | |
163 | struct _pthread_mutex *busy; /* mutex associated with variable */ | |
164 | int waiters:16, /* Number of threads waiting */ | |
165 | sigspending:16; /* Number of outstanding signals */ | |
166 | } pthread_cond_t; | |
167 | ||
168 | /* | |
169 | * Initialization control (once) variables | |
170 | */ | |
171 | typedef struct | |
172 | { | |
173 | long sig; /* Unique signature for this structure */ | |
174 | pthread_lock_t lock; /* Used for internal mutex on structure */ | |
175 | } pthread_once_t; | |
176 | ||
5b2abdfb A |
177 | typedef struct { |
178 | long sig; /* Unique signature for this structure */ | |
179 | int pshared; | |
180 | int rfu[2]; /* reserved for future use */ | |
181 | } pthread_rwlockattr_t; | |
182 | ||
183 | typedef struct { | |
184 | long sig; | |
185 | pthread_mutex_t lock; /* monitor lock */ | |
186 | int state; | |
187 | pthread_cond_t read_signal; | |
188 | pthread_cond_t write_signal; | |
189 | int blocked_writers; | |
190 | int pshared; | |
191 | int rfu[3]; | |
192 | } pthread_rwlock_t; | |
193 | ||
e9ce8d39 A |
194 | #include "pthread.h" |
195 | ||
196 | #define _PTHREAD_DEFAULT_INHERITSCHED PTHREAD_INHERIT_SCHED | |
197 | #define _PTHREAD_DEFAULT_PROTOCOL PTHREAD_PRIO_NONE | |
198 | #define _PTHREAD_DEFAULT_PRIOCEILING 0 | |
199 | #define _PTHREAD_DEFAULT_POLICY SCHED_OTHER | |
200 | #define _PTHREAD_DEFAULT_STACKSIZE 0x80000 /* 512K */ | |
201 | ||
202 | #define _PTHREAD_NO_SIG 0x00000000 | |
203 | #define _PTHREAD_MUTEX_ATTR_SIG 0x4D545841 /* 'MTXA' */ | |
204 | #define _PTHREAD_MUTEX_SIG 0x4D555458 /* 'MUTX' */ | |
205 | #define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 /* [almost] ~'MUTX' */ | |
5b2abdfb | 206 | #define _PTHREAD_COND_ATTR_SIG 0x434E4441 /* 'CNDA' */ |
e9ce8d39 A |
207 | #define _PTHREAD_COND_SIG 0x434F4E44 /* 'COND' */ |
208 | #define _PTHREAD_COND_SIG_init 0x3CB0B1BB /* [almost] ~'COND' */ | |
209 | #define _PTHREAD_ATTR_SIG 0x54484441 /* 'THDA' */ | |
210 | #define _PTHREAD_ONCE_SIG 0x4F4E4345 /* 'ONCE' */ | |
211 | #define _PTHREAD_ONCE_SIG_init 0x30B1BCBA /* [almost] ~'ONCE' */ | |
212 | #define _PTHREAD_SIG 0x54485244 /* 'THRD' */ | |
5b2abdfb A |
213 | #define _PTHREAD_RWLOCK_ATTR_SIG 0x52574C41 /* 'RWLA' */ |
214 | #define _PTHREAD_RWLOCK_SIG 0x52574C4B /* 'RWLK' */ | |
215 | #define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4 /* [almost] ~'RWLK' */ | |
e9ce8d39 | 216 | |
e9ce8d39 | 217 | #define _PTHREAD_CREATE_PARENT 4 |
5b2abdfb | 218 | #define _PTHREAD_EXITED 8 |
e9ce8d39 A |
219 | |
220 | #define _PTHREAD_CANCEL_STATE_MASK 0xFE | |
221 | #define _PTHREAD_CANCEL_TYPE_MASK 0xFD | |
222 | #define _PTHREAD_CANCEL_PENDING 0x10 /* pthread_cancel() has been called for this thread */ | |
223 | ||
224 | extern boolean_t swtch_pri(int); | |
225 | ||
226 | /* Number of times to spin when the lock is unavailable and we are on a | |
227 | multiprocessor. On a uniprocessor we yield the processor immediately. */ | |
3b2a1fe8 | 228 | #define MP_SPIN_TRIES 1000 |
e9ce8d39 A |
229 | extern int _spin_tries; |
230 | extern int __is_threaded; | |
231 | extern int _cpu_has_altivec; | |
232 | ||
233 | /* Internal mutex locks for data structures */ | |
3b2a1fe8 A |
234 | #define TRY_LOCK(v) (!__is_threaded || _spin_lock_try((pthread_lock_t *)&(v))) |
235 | #define LOCK(v) \ | |
236 | do { \ | |
237 | if (__is_threaded) { \ | |
238 | int tries = _spin_tries; \ | |
239 | \ | |
240 | while (!_spin_lock_try((pthread_lock_t *)&(v))) { \ | |
241 | if (tries-- > 0) \ | |
242 | continue; \ | |
243 | \ | |
244 | syscall_thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 1); \ | |
245 | tries = _spin_tries; \ | |
246 | } \ | |
247 | } \ | |
248 | } while (0) | |
249 | #define UNLOCK(v) \ | |
250 | do { \ | |
251 | if (__is_threaded) \ | |
252 | _spin_unlock((pthread_lock_t *)&(v)); \ | |
253 | } while (0) | |
254 | ||
e9ce8d39 A |
255 | #ifndef ESUCCESS |
256 | #define ESUCCESS 0 | |
257 | #endif | |
258 | ||
259 | #ifndef PTHREAD_MACH_CALL | |
260 | #define PTHREAD_MACH_CALL(expr, ret) (ret) = (expr) | |
261 | #endif | |
262 | ||
263 | /* Prototypes. */ | |
264 | ||
265 | /* Functions defined in machine-dependent files. */ | |
266 | extern vm_address_t _sp(void); | |
267 | extern vm_address_t _adjust_sp(vm_address_t sp); | |
268 | extern void _spin_lock(pthread_lock_t *lockp); | |
269 | extern int _spin_lock_try(pthread_lock_t *lockp); | |
270 | extern void _spin_unlock(pthread_lock_t *lockp); | |
5b2abdfb | 271 | extern void _pthread_setup(pthread_t th, void (*f)(pthread_t), void *sp, int suspended, int needresume); |
e9ce8d39 A |
272 | |
273 | extern void _pthread_tsd_cleanup(pthread_t self); | |
274 | ||
275 | __private_extern__ semaphore_t new_sem_from_pool(void); | |
276 | __private_extern__ void restore_sem_to_pool(semaphore_t); | |
277 | #endif /* _POSIX_PTHREAD_INTERNALS_H */ |