[77641d]: src / runtime / pthreads_win32.h Maximize Restore History

Download this file

pthreads_win32.h    431 lines (346 with data), 12.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
#ifndef WIN32_PTHREAD_INCLUDED
#define WIN32_PTHREAD_INCLUDED
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#ifndef _SIGSET_T
typedef int sigset_t;
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdint.h>
/* 0 - Misc */
#ifndef SIG_IGN
#define SIG_IGN ((void (*)(int, siginfo_t, void*))-1)
#endif
#ifndef SIG_DFL
#define SIG_DFL ((void (*)(int, siginfo_t, void*))-2)
#endif
#define SIGHUP 1
#define SIGINT 2 /* Interactive attention */
#define SIGQUIT 3
#define SIGILL 4 /* Illegal instruction */
#define SIGPIPE 5
#define SIGALRM 6
#define SIGURG 7
#define SIGFPE 8 /* Floating point error */
#define SIGTSTP 9
#define SIGCHLD 10
#define SIGSEGV 11 /* Segmentation violation */
#define SIGIO 12
#define SIGXCPU 13
#define SIGXFSZ 14
#define SIGTERM 15 /* Termination request */
#define SIGVTALRM 16
#define SIGPROF 17
#define SIGWINCH 18
#define SIGBREAK 21 /* Control-break */
#define SIGABRT 22 /* Abnormal termination (abort) */
#define SIGRTMIN 23
#ifndef NSIG
#define NSIG 32 /* maximum signal number + 1 */
#endif
/* To avoid overusing system TLS, pthread provides its own */
#define PTHREAD_KEYS_MAX 128
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
void pthreads_win32_init();
/* 1 - Thread */
typedef struct pthread_thread* pthread_t;
typedef struct pthread_attr_t {
unsigned int stack_size;
} pthread_attr_t;
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
typedef void (*pthread_cleanup_fn)(void* arg);
#define pthread_cleanup_push(fn, arg) { pthread_cleanup_fn __pthread_fn = fn; void *__pthread_arg = arg;
#define pthread_cleanup_pop(execute) if (execute) __pthread_fn(__pthread_arg); }
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
int pthread_equal(pthread_t thread1, pthread_t thread2);
int pthread_detach(pthread_t thread);
int pthread_join(pthread_t thread, void **retval);
int pthread_kill(pthread_t thread, int signum);
#ifndef PTHREAD_INTERNALS
pthread_t pthread_self(void) __attribute__((__const__));
#else
pthread_t pthread_self(void);
#endif
typedef DWORD pthread_key_t;
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
#define SIG_BLOCK 1
#define SIG_UNBLOCK 2
#define SIG_SETMASK 3
#ifdef PTHREAD_INTERNALS
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
#endif
/* 1a - Thread non-portable */
void pthread_np_suspend(pthread_t thread);
void pthread_np_suspend_with_signal(pthread_t thread, int signum);
/* Momentary suspend/getcontext/resume without locking or preventing
fiber reentrance. This call is for asymmetric synchronization,
ensuring that the thread sees global state before doing any
globally visible stores.
*/
void pthread_np_serialize(pthread_t thread);
void pthread_np_resume(pthread_t thread);
void pthread_np_request_interruption(pthread_t thread);
CONTEXT* pthread_np_publish_context(CONTEXT* maybe_save_old_one);
void pthread_np_unpublish_context();
void pthread_np_get_my_context_subset(CONTEXT* ctx);
/* 2 - Mutex */
typedef struct _pthread_mutex_info {
char padding[64];
CRITICAL_SECTION cs;
pthread_t owner;
const char* file;
int line;
} __attribute__((aligned(128))) *pthread_mutex_t;
typedef int pthread_mutexattr_t;
#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)-1)
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr);
int pthread_mutexattr_init(pthread_mutexattr_t*);
int pthread_mutexattr_destroy(pthread_mutexattr_t*);
int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
#define PTHREAD_MUTEX_ERRORCHECK 0
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_lock_annotate_np(pthread_mutex_t *mutex, const char* file, int line);
int pthread_mutex_trylock_annotate_np(pthread_mutex_t *mutex, const char* file, int line);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/* 3 - Condition variable */
typedef struct thread_wakeup {
HANDLE event;
struct thread_wakeup *next;
volatile intptr_t *uaddr;
intptr_t uval;
int info;
} thread_wakeup;
typedef HANDLE (*cv_event_get_fn)();
typedef void (*cv_event_return_fn)(HANDLE event);
typedef struct pthread_cond_t {
pthread_mutex_t wakeup_lock;
struct thread_wakeup *first_wakeup;
struct thread_wakeup *last_wakeup;
unsigned char alertable;
cv_event_get_fn get_fn;
cv_event_return_fn return_fn;
} pthread_cond_t;
typedef struct pthread_condattr_t {
unsigned char alertable;
cv_event_get_fn get_fn;
cv_event_return_fn return_fn;
} pthread_condattr_t;
#ifndef _TIMESPEC_DEFINED
typedef struct timespec {
time_t tv_sec;
long tv_nsec;
} timespec;
#endif
// not implemented: PTHREAD_COND_INITIALIZER
int pthread_condattr_init(pthread_condattr_t *attr);
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_setevent_np(pthread_condattr_t *attr,
cv_event_get_fn get_fn, cv_event_return_fn ret_fn);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, const struct timespec * abstime);
int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);
/* some MinGWs seem to include it, others not: */
#ifndef ETIMEDOUT
# define ETIMEDOUT 123 //Something
#endif
int sched_yield();
void pthread_lock_structures();
void pthread_unlock_structures();
typedef void *(*pthread_fn)(void*);
typedef enum {
pthread_state_running,
pthread_state_finished,
pthread_state_joined
} pthread_thread_state;
typedef struct pthread_thread {
pthread_fn start_routine;
void* arg;
HANDLE handle;
pthread_cond_t *waiting_cond;
void *futex_wakeup;
sigset_t blocked_signal_set;
volatile sigset_t pending_signal_set;
void * retval;
pthread_mutex_t lock;
pthread_cond_t cond;
int detached;
pthread_thread_state state;
/* Boolean flag: thread will produce fibers instead of threads with
pthread_create */
int fiber_factory;
/* NULL if current thread has no fibers and is not a fiber; LPVOID
returned by CreateFiber or ConvertThreadToFiber otherwise */
void* fiber;
/* True if pthreads_win32 created fiber, false if it was already
present and just captured. We should delete our fiber when not
needed, but external fibers should be left intact. */
int own_fiber;
/* True if thread was created as fiber */
int created_as_fiber;
/* For noticed foreign threads, wait_handle contains a result of
RegisterWaitForSingleObject. */
HANDLE wait_handle;
/* FCAT group of a fiber. */
pthread_t fiber_group;
/* Mutex preventing double-entering a fiber */
pthread_mutex_t fiber_lock;
/* When fiber switches to another fiber (dying or not) it makes
another's fiber_prev point to it. If it's dead, the fiber entered
should clean up. */
pthread_t fiber_prev;
/* For non-running fiber, this field provides context of its
last-known running state: not for jumps et al., but for
conservative stack GCing.
With pthread_np_publish_context and pthread_np_unpublish_context
application may manage its thread context cooperatively, not
requiring real SuspendThread and ResumeThread for threads that
don't do anything interesting (as defined by application).
Esp field of fiber_context is used as a validity flag (must not
be NULL). */
CONTEXT fiber_context;
/* Thread TEB base (mostly informative/debugging) */
void* teb;
/* For fiber-callouts (call-in-fiber) support. When switched into,
any fiber should execute fiber_callback and switch back to
fiber_prev. */
void (*fiber_callback)(void* context);
void *fiber_callback_context;
/* Pthread TLS, detached from windows system TLS */
void *specifics[PTHREAD_KEYS_MAX];
} pthread_thread;
#define PTHREAD_ONCE_INIT 0
typedef int pthread_once_t;
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
static inline int pthread_setspecific(pthread_key_t key, const void *value)
{
pthread_self()->specifics[key] = (void*)value;
return 0;
}
typedef struct {
int bogus;
} siginfo_t;
#define SA_SIGINFO (1u<<1)
#define SA_NODEFER (1u<<2)
#define SA_RESTART (1u<<3)
#define SA_ONSTACK (1u<<4)
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t*, void*);
sigset_t sa_mask;
int sa_flags;
};
int sigaction(int signum, const struct sigaction* act, struct sigaction* oldact);
int sigpending(sigset_t *set);
void pthread_np_add_pending_signal(pthread_t thread, int signum);
void pthread_np_remove_pending_signal(pthread_t thread, int signum);
sigset_t pthread_np_other_thread_sigpending(pthread_t thread);
int pthread_np_notice_thread();
int pthread_np_get_thread_context(pthread_t thread, CONTEXT* context);
int pthread_np_convert_self_to_fiber();
int pthread_np_switch_to_fiber(pthread_t fiber);
int pthread_np_run_in_fiber(pthread_t pth, void (*callback)(void*),
void* context);
int pthread_np_set_fiber_factory_mode(int on);
int pthread_np_fiber_save_tls(int slot, int enable);
HANDLE pthread_np_get_handle(pthread_t pth);
void* pthread_np_get_lowlevel_fiber(pthread_t pth);
int pthread_np_delete_lowlevel_fiber(void* ll_fiber);
int pthread_np_ack_pending_signals(void* ucontext_arg);
/* Fiber context hooks */
extern void (*pthread_save_context_hook)();
extern void (*pthread_restore_context_hook)();
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
typedef int sig_atomic_t;
/* Futexes */
int futex_wait(volatile intptr_t *lock_word, intptr_t oldval, long sec, unsigned long usec);
int futex_wake(volatile intptr_t *lock_word, int n);
/* Debugging */
void pthread_np_lose(int trace_depth, const char* fmt, ...);
struct _pthread_mutex_info DEAD_MUTEX;
static inline void pthread_np_assert_live_mutex(pthread_mutex_t* ptr,
const char *action)
{
if (*ptr == &DEAD_MUTEX) {
pthread_np_lose(5,"Trying to %s dead mutex %p\n",action,ptr);
}
}
typedef HANDLE sem_t;
#define SEM_VALUE_MAX (int) (~0U >>1)
int sem_init(sem_t *sem, int pshared_not_implemented, unsigned int value);
int sem_post(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_destroy(sem_t *sem);
#ifndef PTHREAD_INTERNALS
static inline int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
{
pthread_t self = pthread_self();
if (oldset)
*oldset = self->blocked_signal_set;
if (set) {
switch (how) {
case SIG_BLOCK:
self->blocked_signal_set |= *set;
break;
case SIG_UNBLOCK:
self->blocked_signal_set &= ~(*set);
break;
case SIG_SETMASK:
self->blocked_signal_set = *set;
break;
}
}
return 0;
}
/* Make speed-critical TLS access inline.
We don't check key range or validity here: (1) pthread spec is
explicit about undefined behavior for bogus keys, (2)
setspecific/getspecific should be as fast as possible. */
#define pthread_getspecific pthread_getspecific_np_inline
static inline void *pthread_getspecific_np_inline(pthread_key_t key)
{
return pthread_self()->specifics[key];
}
#ifdef PTHREAD_DEBUG_OUTPUT
#define pthread_mutex_lock(mutex) \
pthread_mutex_lock_annotate_np(mutex, __FILE__, __LINE__ )
#define pthread_mutex_trylock(mutex) \
pthread_mutex_trylock_annotate_np(mutex, __FILE__ ,__LINE__)
#else
/* I'm not after inlinining _everything_, but those two things below are
(1) fast, (2) critical (3) short */
static inline int pthread_mutex_lock_np_inline(pthread_mutex_t *mutex)
{
pthread_np_assert_live_mutex(mutex,"lock");
if ((*mutex) == PTHREAD_MUTEX_INITIALIZER) {
return pthread_mutex_lock(mutex);
} else {
EnterCriticalSection(&(*mutex)->cs);
return 0;
}
}
static inline int pthread_mutex_unlock_np_inline(pthread_mutex_t *mutex)
{
pthread_np_assert_live_mutex(mutex,"unlock");
LeaveCriticalSection(&(*mutex)->cs);
return 0;
}
#define pthread_mutex_lock pthread_mutex_lock_np_inline
#define pthread_mutex_unlock pthread_mutex_unlock_np_inline
#endif /* !PTHREAD_DEBUG_OUTPUT */
#endif /* !PTHREAD_INTERNALS */
#endif /* WIN32_PTHREAD_INCLUDED */