1 #ifndef WIN32_PTHREAD_INCLUDED
2 #define WIN32_PTHREAD_INCLUDED
13 #define WIN32_LEAN_AND_MEAN
20 #define SIG_IGN ((void (*)(int, siginfo_t, void*))-1)
23 #define SIG_DFL ((void (*)(int, siginfo_t, void*))-2)
27 #define SIGINT 2 /* Interactive attention */
29 #define SIGILL 4 /* Illegal instruction */
33 #define SIGFPE 8 /* Floating point error */
36 #define SIGSEGV 11 /* Segmentation violation */
40 #define SIGTERM 15 /* Termination request */
44 #define SIGBREAK 21 /* Control-break */
45 #define SIGABRT 22 /* Abnormal termination (abort) */
50 #define NSIG 32 /* maximum signal number + 1 */
53 /* To avoid overusing system TLS, pthread provides its own */
54 #define PTHREAD_KEYS_MAX 128
56 #define PTHREAD_DESTRUCTOR_ITERATIONS 4
58 void pthreads_win32_init();
62 typedef struct pthread_thread
* pthread_t
;
64 typedef struct pthread_attr_t
{
65 unsigned int stack_size
;
68 int pthread_attr_init(pthread_attr_t
*attr
);
69 int pthread_attr_destroy(pthread_attr_t
*attr
);
70 int pthread_attr_setstack(pthread_attr_t
*attr
, void *stackaddr
, size_t stacksize
);
71 int pthread_attr_setstacksize(pthread_attr_t
*attr
, size_t stacksize
);
73 typedef void (*pthread_cleanup_fn
)(void* arg
);
75 #define pthread_cleanup_push(fn, arg) { pthread_cleanup_fn __pthread_fn = fn; void *__pthread_arg = arg;
76 #define pthread_cleanup_pop(execute) if (execute) __pthread_fn(__pthread_arg); }
78 int pthread_create(pthread_t
*thread
, const pthread_attr_t
*attr
, void *(*start_routine
) (void *), void *arg
);
79 int pthread_equal(pthread_t thread1
, pthread_t thread2
);
80 int pthread_detach(pthread_t thread
);
81 int pthread_join(pthread_t thread
, void **retval
);
82 int pthread_kill(pthread_t thread
, int signum
);
84 #ifndef PTHREAD_INTERNALS
85 pthread_t
pthread_self(void) __attribute__((__const__
));
87 pthread_t
pthread_self(void);
90 typedef DWORD pthread_key_t
;
91 int pthread_key_create(pthread_key_t
*key
, void (*destructor
)(void*));
96 #ifdef PTHREAD_INTERNALS
97 int _sbcl_pthread_sigmask(int how
, const sigset_t
*set
, sigset_t
*oldset
);
100 /* 1a - Thread non-portable */
102 void pthread_np_suspend(pthread_t thread
);
103 void pthread_np_suspend_with_signal(pthread_t thread
, int signum
);
105 /* Momentary suspend/getcontext/resume without locking or preventing
106 fiber reentrance. This call is for asymmetric synchronization,
107 ensuring that the thread sees global state before doing any
108 globally visible stores.
110 void pthread_np_serialize(pthread_t thread
);
112 void pthread_np_resume(pthread_t thread
);
113 void pthread_np_request_interruption(pthread_t thread
);
114 CONTEXT
* pthread_np_publish_context(CONTEXT
* maybe_save_old_one
);
115 void pthread_np_unpublish_context();
116 void pthread_np_get_my_context_subset(CONTEXT
* ctx
);
120 typedef struct _pthread_mutex_info
{
126 } __attribute__((aligned(128))) *pthread_mutex_t
;
128 typedef int pthread_mutexattr_t
;
129 #define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)-1)
130 int pthread_mutex_init(pthread_mutex_t
* mutex
, const pthread_mutexattr_t
* attr
);
131 int pthread_mutexattr_init(pthread_mutexattr_t
*);
132 int pthread_mutexattr_destroy(pthread_mutexattr_t
*);
133 int pthread_mutexattr_settype(pthread_mutexattr_t
*, int);
134 #define PTHREAD_MUTEX_ERRORCHECK 0
135 int pthread_mutex_destroy(pthread_mutex_t
*mutex
);
136 int pthread_mutex_lock(pthread_mutex_t
*mutex
);
137 int pthread_mutex_trylock(pthread_mutex_t
*mutex
);
138 int pthread_mutex_lock_annotate_np(pthread_mutex_t
*mutex
, const char* file
, int line
);
139 int pthread_mutex_trylock_annotate_np(pthread_mutex_t
*mutex
, const char* file
, int line
);
140 int pthread_mutex_unlock(pthread_mutex_t
*mutex
);
142 /* 3 - Condition variable */
144 typedef struct thread_wakeup
{
146 struct thread_wakeup
*next
;
147 volatile intptr_t *uaddr
;
152 typedef HANDLE (*cv_event_get_fn
)();
153 typedef void (*cv_event_return_fn
)(HANDLE event
);
155 typedef struct pthread_cond_t
{
156 pthread_mutex_t wakeup_lock
;
157 struct thread_wakeup
*first_wakeup
;
158 struct thread_wakeup
*last_wakeup
;
159 unsigned char alertable
;
160 cv_event_get_fn get_fn
;
161 cv_event_return_fn return_fn
;
164 typedef struct pthread_condattr_t
{
165 unsigned char alertable
;
166 cv_event_get_fn get_fn
;
167 cv_event_return_fn return_fn
;
168 } pthread_condattr_t
;
170 #ifndef _TIMESPEC_DEFINED
171 typedef struct timespec
{
177 // not implemented: PTHREAD_COND_INITIALIZER
178 int pthread_condattr_init(pthread_condattr_t
*attr
);
179 int pthread_condattr_destroy(pthread_condattr_t
*attr
);
180 int pthread_condattr_setevent_np(pthread_condattr_t
*attr
,
181 cv_event_get_fn get_fn
, cv_event_return_fn ret_fn
);
182 int pthread_cond_destroy(pthread_cond_t
*cond
);
183 int pthread_cond_init(pthread_cond_t
* cond
, const pthread_condattr_t
* attr
);
184 int pthread_cond_broadcast(pthread_cond_t
*cond
);
185 int pthread_cond_signal(pthread_cond_t
*cond
);
186 int pthread_cond_timedwait(pthread_cond_t
* cond
, pthread_mutex_t
* mutex
, const struct timespec
* abstime
);
187 int pthread_cond_wait(pthread_cond_t
* cond
, pthread_mutex_t
* mutex
);
189 /* some MinGWs seem to include it, others not: */
191 # define ETIMEDOUT 123 //Something
196 void pthread_lock_structures();
197 void pthread_unlock_structures();
199 typedef void *(*pthread_fn
)(void*);
202 pthread_state_running
,
203 pthread_state_finished
,
205 } pthread_thread_state
;
207 typedef struct pthread_thread
{
208 pthread_fn start_routine
;
211 pthread_cond_t
*waiting_cond
;
213 sigset_t blocked_signal_set
;
214 volatile sigset_t pending_signal_set
;
217 pthread_mutex_t lock
;
220 pthread_thread_state state
;
222 /* Boolean flag: thread will produce fibers instead of threads with
226 /* NULL if current thread has no fibers and is not a fiber; LPVOID
227 returned by CreateFiber or ConvertThreadToFiber otherwise */
230 /* True if pthreads_win32 created fiber, false if it was already
231 present and just captured. We should delete our fiber when not
232 needed, but external fibers should be left intact. */
235 /* True if thread was created as fiber */
236 int created_as_fiber
;
238 /* For noticed foreign threads, wait_handle contains a result of
239 RegisterWaitForSingleObject. */
242 /* FCAT group of a fiber. */
243 pthread_t fiber_group
;
245 /* Mutex preventing double-entering a fiber */
246 pthread_mutex_t fiber_lock
;
248 /* When fiber switches to another fiber (dying or not) it makes
249 another's fiber_prev point to it. If it's dead, the fiber entered
251 pthread_t fiber_prev
;
253 /* For non-running fiber, this field provides context of its
254 last-known running state: not for jumps et al., but for
255 conservative stack GCing.
257 With pthread_np_publish_context and pthread_np_unpublish_context
258 application may manage its thread context cooperatively, not
259 requiring real SuspendThread and ResumeThread for threads that
260 don't do anything interesting (as defined by application).
262 Esp field of fiber_context is used as a validity flag (must not
264 CONTEXT fiber_context
;
266 /* Thread TEB base (mostly informative/debugging) */
269 /* For fiber-callouts (call-in-fiber) support. When switched into,
270 any fiber should execute fiber_callback and switch back to
272 void (*fiber_callback
)(void* context
);
273 void *fiber_callback_context
;
275 /* Pthread TLS, detached from windows system TLS */
276 void *specifics
[PTHREAD_KEYS_MAX
];
279 #define PTHREAD_ONCE_INIT 0
281 typedef int pthread_once_t
;
282 int pthread_once(pthread_once_t
*once_control
, void (*init_routine
)(void));
284 static inline int pthread_setspecific(pthread_key_t key
, const void *value
)
286 pthread_self()->specifics
[key
] = (void*)value
;
294 #define SA_SIGINFO (1u<<1)
295 #define SA_NODEFER (1u<<2)
296 #define SA_RESTART (1u<<3)
297 #define SA_ONSTACK (1u<<4)
300 void (*sa_handler
)(int);
301 void (*sa_sigaction
)(int, siginfo_t
*, void*);
305 int sigaction(int signum
, const struct sigaction
* act
, struct sigaction
* oldact
);
307 int sigpending(sigset_t
*set
);
309 void pthread_np_add_pending_signal(pthread_t thread
, int signum
);
310 void pthread_np_remove_pending_signal(pthread_t thread
, int signum
);
311 sigset_t
pthread_np_other_thread_sigpending(pthread_t thread
);
313 int pthread_np_notice_thread();
314 int pthread_np_get_thread_context(pthread_t thread
, CONTEXT
* context
);
315 int pthread_np_convert_self_to_fiber();
316 int pthread_np_switch_to_fiber(pthread_t fiber
);
317 int pthread_np_run_in_fiber(pthread_t pth
, void (*callback
)(void*),
319 int pthread_np_set_fiber_factory_mode(int on
);
320 int pthread_np_fiber_save_tls(int slot
, int enable
);
321 HANDLE
pthread_np_get_handle(pthread_t pth
);
322 void* pthread_np_get_lowlevel_fiber(pthread_t pth
);
323 int pthread_np_delete_lowlevel_fiber(void* ll_fiber
);
324 int pthread_np_ack_pending_signals(void* ucontext_arg
);
326 /* Fiber context hooks */
327 extern void (*pthread_save_context_hook
)();
328 extern void (*pthread_restore_context_hook
)();
330 int sigemptyset(sigset_t
*set
);
331 int sigfillset(sigset_t
*set
);
332 int sigaddset(sigset_t
*set
, int signum
);
333 int sigdelset(sigset_t
*set
, int signum
);
334 int sigismember(const sigset_t
*set
, int signum
);
336 typedef int sig_atomic_t;
339 int futex_wait(volatile intptr_t *lock_word
, intptr_t oldval
, long sec
, unsigned long usec
);
340 int futex_wake(volatile intptr_t *lock_word
, int n
);
343 void pthread_np_lose(int trace_depth
, const char* fmt
, ...);
344 struct _pthread_mutex_info DEAD_MUTEX
;
346 static inline void pthread_np_assert_live_mutex(pthread_mutex_t
* ptr
,
349 if (*ptr
== &DEAD_MUTEX
) {
350 pthread_np_lose(5,"Trying to %s dead mutex %p\n",action
,ptr
);
354 typedef HANDLE sem_t
;
356 #define SEM_VALUE_MAX (int) (~0U >>1)
358 int sem_init(sem_t
*sem
, int pshared_not_implemented
, unsigned int value
);
359 int sem_post(sem_t
*sem
);
360 int sem_wait(sem_t
*sem
);
361 int sem_trywait(sem_t
*sem
);
362 int sem_destroy(sem_t
*sem
);
364 #ifndef PTHREAD_INTERNALS
365 static inline int _sbcl_pthread_sigmask(int how
, const sigset_t
*set
, sigset_t
*oldset
)
367 pthread_t self
= pthread_self();
369 *oldset
= self
->blocked_signal_set
;
373 self
->blocked_signal_set
|= *set
;
376 self
->blocked_signal_set
&= ~(*set
);
379 self
->blocked_signal_set
= *set
;
386 /* Make speed-critical TLS access inline.
388 We don't check key range or validity here: (1) pthread spec is
389 explicit about undefined behavior for bogus keys, (2)
390 setspecific/getspecific should be as fast as possible. */
391 #define pthread_getspecific pthread_getspecific_np_inline
393 static inline void *pthread_getspecific_np_inline(pthread_key_t key
)
395 return pthread_self()->specifics
[key
];
398 #ifdef PTHREAD_DEBUG_OUTPUT
399 #define pthread_mutex_lock(mutex) \
400 pthread_mutex_lock_annotate_np(mutex, __FILE__, __LINE__ )
401 #define pthread_mutex_trylock(mutex) \
402 pthread_mutex_trylock_annotate_np(mutex, __FILE__ ,__LINE__)
405 /* I'm not after inlinining _everything_, but those two things below are
406 (1) fast, (2) critical (3) short */
407 static inline int pthread_mutex_lock_np_inline(pthread_mutex_t
*mutex
)
409 pthread_np_assert_live_mutex(mutex
,"lock");
410 if ((*mutex
) == PTHREAD_MUTEX_INITIALIZER
) {
411 return pthread_mutex_lock(mutex
);
413 EnterCriticalSection(&(*mutex
)->cs
);
418 static inline int pthread_mutex_unlock_np_inline(pthread_mutex_t
*mutex
)
420 pthread_np_assert_live_mutex(mutex
,"unlock");
421 LeaveCriticalSection(&(*mutex
)->cs
);
425 #define pthread_mutex_lock pthread_mutex_lock_np_inline
426 #define pthread_mutex_unlock pthread_mutex_unlock_np_inline
428 #endif /* !PTHREAD_DEBUG_OUTPUT */
429 #endif /* !PTHREAD_INTERNALS */
430 #endif /* WIN32_PTHREAD_INCLUDED */