Hopefully fix the windows build to grovel time structures correctly.
[sbcl.git] / src / runtime / pthreads_win32.h
1 #ifndef WIN32_PTHREAD_INCLUDED
2 #define WIN32_PTHREAD_INCLUDED
3
4 #include <time.h>
5 #include <errno.h>
6 #include <sys/types.h>
7
8 #ifndef _SIGSET_T
9 typedef int sigset_t;
10 #endif
11
12
13 #define WIN32_LEAN_AND_MEAN
14 #include <windows.h>
15 #include <stdint.h>
16
17 /* 0 - Misc */
18
19 #ifndef SIG_IGN
20 #define SIG_IGN ((void (*)(int, siginfo_t, void*))-1)
21 #endif
22 #ifndef SIG_DFL
23 #define SIG_DFL ((void (*)(int, siginfo_t, void*))-2)
24 #endif
25
26 #define SIGHUP    1
27 #define SIGINT    2 /* Interactive attention */
28 #define SIGQUIT   3
29 #define SIGILL    4 /* Illegal instruction */
30 #define SIGPIPE   5
31 #define SIGALRM   6
32 #define SIGURG    7
33 #define SIGFPE    8 /* Floating point error */
34 #define SIGTSTP   9
35 #define SIGCHLD   10
36 #define SIGSEGV   11 /* Segmentation violation */
37 #define SIGIO     12
38 #define SIGXCPU   13
39 #define SIGXFSZ   14
40 #define SIGTERM   15 /* Termination request */
41 #define SIGVTALRM 16
42 #define SIGPROF   17
43 #define SIGWINCH  18
44 #define SIGBREAK  21 /* Control-break */
45 #define SIGABRT   22 /* Abnormal termination (abort) */
46
47 #define SIGRTMIN  23
48
49 #ifndef NSIG
50 #define NSIG 32     /* maximum signal number + 1 */
51 #endif
52
53 /* To avoid overusing system TLS, pthread provides its own */
54 #define PTHREAD_KEYS_MAX 128
55
56 #define PTHREAD_DESTRUCTOR_ITERATIONS 4
57
58 void pthreads_win32_init();
59
60 /* 1 - Thread */
61
62 typedef struct pthread_thread* pthread_t;
63
64 typedef struct pthread_attr_t {
65   unsigned int stack_size;
66 } pthread_attr_t;
67
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);
72
73 typedef void (*pthread_cleanup_fn)(void* arg);
74
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); }
77
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);
83
84 #ifndef PTHREAD_INTERNALS
85 pthread_t pthread_self(void) __attribute__((__const__));
86 #else
87 pthread_t pthread_self(void);
88 #endif
89
90 typedef DWORD pthread_key_t;
91 int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
92
93 #define SIG_BLOCK 1
94 #define SIG_UNBLOCK 2
95 #define SIG_SETMASK 3
96 #ifdef PTHREAD_INTERNALS
97 int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
98 #endif
99
100 /* 1a - Thread non-portable */
101
102 void pthread_np_suspend(pthread_t thread);
103 void pthread_np_suspend_with_signal(pthread_t thread, int signum);
104
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.
109 */
110 void pthread_np_serialize(pthread_t thread);
111
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);
117
118 /* 2 - Mutex */
119
120 typedef struct _pthread_mutex_info {
121   char padding[64];
122   CRITICAL_SECTION cs;
123   pthread_t owner;
124   const char* file;
125   int line;
126 } __attribute__((aligned(128))) *pthread_mutex_t;
127
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);
141
142 /* 3 - Condition variable */
143
144 typedef struct thread_wakeup {
145   HANDLE event;
146   struct thread_wakeup *next;
147   volatile intptr_t *uaddr;
148   intptr_t uval;
149   int info;
150 } thread_wakeup;
151
152 typedef HANDLE (*cv_event_get_fn)();
153 typedef void (*cv_event_return_fn)(HANDLE event);
154
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;
162 } pthread_cond_t;
163
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;
169
170 #ifndef _TIMESPEC_DEFINED
171 typedef struct timespec {
172   time_t tv_sec;
173   long tv_nsec;
174 } timespec;
175 #endif
176
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);
188
189 /* some MinGWs seem to include it, others not: */
190 #ifndef ETIMEDOUT
191 # define ETIMEDOUT 123 //Something
192 #endif
193
194 int sched_yield();
195
196 void pthread_lock_structures();
197 void pthread_unlock_structures();
198
199 typedef void *(*pthread_fn)(void*);
200
201 typedef enum {
202   pthread_state_running,
203   pthread_state_finished,
204   pthread_state_joined
205 } pthread_thread_state;
206
207 typedef struct pthread_thread {
208   pthread_fn start_routine;
209   void* arg;
210   HANDLE handle;
211   pthread_cond_t *waiting_cond;
212   void *futex_wakeup;
213   sigset_t blocked_signal_set;
214   volatile sigset_t pending_signal_set;
215   void * retval;
216
217   pthread_mutex_t lock;
218   pthread_cond_t cond;
219   int detached;
220   pthread_thread_state state;
221
222   /* Boolean flag: thread will produce fibers instead of threads with
223      pthread_create */
224   int fiber_factory;
225
226   /* NULL if current thread has no fibers and is not a fiber; LPVOID
227      returned by CreateFiber or ConvertThreadToFiber otherwise */
228   void* fiber;
229
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. */
233   int own_fiber;
234
235   /* True if thread was created as fiber */
236   int created_as_fiber;
237
238   /* For noticed foreign threads, wait_handle contains a result of
239      RegisterWaitForSingleObject. */
240   HANDLE wait_handle;
241
242   /* FCAT group of a fiber. */
243   pthread_t fiber_group;
244
245   /* Mutex preventing double-entering a fiber */
246   pthread_mutex_t fiber_lock;
247
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
250      should clean up. */
251   pthread_t fiber_prev;
252
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.
256
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).
261
262      Esp field of fiber_context is used as a validity flag (must not
263      be NULL). */
264   CONTEXT fiber_context;
265
266   /* Thread TEB base (mostly informative/debugging) */
267   void* teb;
268
269   /* For fiber-callouts (call-in-fiber) support.  When switched into,
270      any fiber should execute fiber_callback and switch back to
271      fiber_prev. */
272   void (*fiber_callback)(void* context);
273   void *fiber_callback_context;
274
275   /* Pthread TLS, detached from windows system TLS */
276   void *specifics[PTHREAD_KEYS_MAX];
277 } pthread_thread;
278
279 #define PTHREAD_ONCE_INIT 0
280
281 typedef int pthread_once_t;
282 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
283
284 static inline int pthread_setspecific(pthread_key_t key, const void *value)
285 {
286   pthread_self()->specifics[key] = (void*)value;
287   return 0;
288 }
289
290 typedef struct {
291   int bogus;
292 } siginfo_t;
293
294 #define SA_SIGINFO (1u<<1)
295 #define SA_NODEFER (1u<<2)
296 #define SA_RESTART (1u<<3)
297 #define SA_ONSTACK (1u<<4)
298
299 struct sigaction {
300   void (*sa_handler)(int);
301   void (*sa_sigaction)(int, siginfo_t*, void*);
302   sigset_t sa_mask;
303   int sa_flags;
304 };
305 int sigaction(int signum, const struct sigaction* act, struct sigaction* oldact);
306
307 int sigpending(sigset_t *set);
308
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);
312
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*),
318                             void* context);
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);
325
326 /* Fiber context hooks */
327 extern void (*pthread_save_context_hook)();
328 extern void (*pthread_restore_context_hook)();
329
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);
335
336 typedef int sig_atomic_t;
337
338 /* Futexes */
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);
341
342 /* Debugging */
343 void pthread_np_lose(int trace_depth, const char* fmt, ...);
344 struct _pthread_mutex_info DEAD_MUTEX;
345
346 static inline void pthread_np_assert_live_mutex(pthread_mutex_t* ptr,
347                                                 const char *action)
348 {
349     if (*ptr == &DEAD_MUTEX) {
350         pthread_np_lose(5,"Trying to %s dead mutex %p\n",action,ptr);
351     }
352 }
353
354 typedef HANDLE sem_t;
355
356 #define SEM_VALUE_MAX (int) (~0U >>1)
357
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);
363
364 #ifndef PTHREAD_INTERNALS
365 static inline int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
366 {
367   pthread_t self = pthread_self();
368   if (oldset)
369     *oldset = self->blocked_signal_set;
370   if (set) {
371     switch (how) {
372       case SIG_BLOCK:
373         self->blocked_signal_set |= *set;
374         break;
375       case SIG_UNBLOCK:
376         self->blocked_signal_set &= ~(*set);
377         break;
378       case SIG_SETMASK:
379         self->blocked_signal_set = *set;
380         break;
381     }
382   }
383   return 0;
384 }
385
386 /* Make speed-critical TLS access inline.
387
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
392
393 static inline void *pthread_getspecific_np_inline(pthread_key_t key)
394 {
395   return pthread_self()->specifics[key];
396 }
397
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__)
403 #else
404
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)
408 {
409     pthread_np_assert_live_mutex(mutex,"lock");
410     if ((*mutex) == PTHREAD_MUTEX_INITIALIZER) {
411         return pthread_mutex_lock(mutex);
412     } else {
413         EnterCriticalSection(&(*mutex)->cs);
414         return 0;
415     }
416 }
417
418 static inline int pthread_mutex_unlock_np_inline(pthread_mutex_t *mutex)
419 {
420     pthread_np_assert_live_mutex(mutex,"unlock");
421     LeaveCriticalSection(&(*mutex)->cs);
422     return 0;
423 }
424
425 #define pthread_mutex_lock pthread_mutex_lock_np_inline
426 #define pthread_mutex_unlock pthread_mutex_unlock_np_inline
427
428 #endif  /* !PTHREAD_DEBUG_OUTPUT */
429 #endif  /* !PTHREAD_INTERNALS */
430 #endif  /* WIN32_PTHREAD_INCLUDED */