|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <config.h> |
|
|
|
|
|
|
|
|
#include "glthread/thread.h" |
|
|
|
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
|
|
|
#if USE_ISOC_THREADS |
|
|
|
|
|
struct thrd_with_exitvalue |
|
|
{ |
|
|
thrd_t volatile tid; |
|
|
void * volatile exitvalue; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static tss_t thrd_with_exitvalue_key; |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
do_init_thrd_with_exitvalue_key (void) |
|
|
{ |
|
|
if (tss_create (&thrd_with_exitvalue_key, NULL) != thrd_success) |
|
|
abort (); |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
init_thrd_with_exitvalue_key (void) |
|
|
{ |
|
|
static once_flag once = ONCE_FLAG_INIT; |
|
|
call_once (&once, do_init_thrd_with_exitvalue_key); |
|
|
} |
|
|
|
|
|
typedef union |
|
|
{ |
|
|
struct thrd_with_exitvalue t; |
|
|
struct |
|
|
{ |
|
|
thrd_t tid; |
|
|
void *(*mainfunc) (void *); |
|
|
void *arg; |
|
|
} a; |
|
|
} |
|
|
main_arg_t; |
|
|
|
|
|
static int |
|
|
thrd_main_func (void *pmarg) |
|
|
{ |
|
|
|
|
|
main_arg_t *main_arg = (main_arg_t *) pmarg; |
|
|
void *(*mainfunc) (void *) = main_arg->a.mainfunc; |
|
|
void *arg = main_arg->a.arg; |
|
|
|
|
|
if (tss_set (thrd_with_exitvalue_key, &main_arg->t) != thrd_success) |
|
|
abort (); |
|
|
|
|
|
|
|
|
{ |
|
|
void *exitvalue = mainfunc (arg); |
|
|
|
|
|
main_arg->t.exitvalue = exitvalue; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
int |
|
|
glthread_create (gl_thread_t *threadp, void *(*mainfunc) (void *), void *arg) |
|
|
{ |
|
|
init_thrd_with_exitvalue_key (); |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main_arg_t *main_arg = (main_arg_t *) malloc (sizeof (main_arg_t)); |
|
|
if (main_arg == NULL) |
|
|
return ENOMEM; |
|
|
main_arg->a.mainfunc = mainfunc; |
|
|
main_arg->a.arg = arg; |
|
|
switch (thrd_create ((thrd_t *) &main_arg->t.tid, thrd_main_func, main_arg)) |
|
|
{ |
|
|
case thrd_success: |
|
|
break; |
|
|
case thrd_nomem: |
|
|
free (main_arg); |
|
|
return ENOMEM; |
|
|
default: |
|
|
free (main_arg); |
|
|
return EAGAIN; |
|
|
} |
|
|
*threadp = &main_arg->t; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
gl_thread_t |
|
|
gl_thread_self (void) |
|
|
{ |
|
|
init_thrd_with_exitvalue_key (); |
|
|
{ |
|
|
gl_thread_t thread = |
|
|
(struct thrd_with_exitvalue *) tss_get (thrd_with_exitvalue_key); |
|
|
if (thread == NULL) |
|
|
{ |
|
|
|
|
|
|
|
|
for (;;) |
|
|
{ |
|
|
thread = |
|
|
(struct thrd_with_exitvalue *) |
|
|
malloc (sizeof (struct thrd_with_exitvalue)); |
|
|
if (thread != NULL) |
|
|
break; |
|
|
|
|
|
|
|
|
{ |
|
|
struct timespec ts = |
|
|
{ |
|
|
.tv_sec = 1, |
|
|
.tv_nsec = 0 |
|
|
}; |
|
|
thrd_sleep (&ts, NULL); |
|
|
} |
|
|
} |
|
|
thread->tid = thrd_current (); |
|
|
thread->exitvalue = NULL; |
|
|
if (tss_set (thrd_with_exitvalue_key, thread) != thrd_success) |
|
|
abort (); |
|
|
} |
|
|
return thread; |
|
|
} |
|
|
} |
|
|
|
|
|
int |
|
|
glthread_join (gl_thread_t thread, void **return_value_ptr) |
|
|
{ |
|
|
|
|
|
|
|
|
int dummy; |
|
|
|
|
|
if (thread == gl_thread_self ()) |
|
|
return EINVAL; |
|
|
if (thrd_join (thread->tid, &dummy) != thrd_success) |
|
|
return EINVAL; |
|
|
if (return_value_ptr != NULL) |
|
|
*return_value_ptr = thread->exitvalue; |
|
|
free (thread); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
_Noreturn void |
|
|
gl_thread_exit (void *return_value) |
|
|
{ |
|
|
gl_thread_t thread = gl_thread_self (); |
|
|
thread->exitvalue = return_value; |
|
|
thrd_exit (0); |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS |
|
|
|
|
|
#include <pthread.h> |
|
|
|
|
|
#if defined PTW32_VERSION || defined __MVS__ |
|
|
|
|
|
const gl_thread_t gl_null_thread ; |
|
|
|
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if USE_WINDOWS_THREADS |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
gl_thread_t |
|
|
gl_thread_create (void *(*func) (void *arg), void *arg) |
|
|
{ |
|
|
gl_thread_t thread; |
|
|
int ret; |
|
|
|
|
|
ret = glthread_create (&thread, func, arg); |
|
|
if (ret != 0) |
|
|
abort (); |
|
|
return thread; |
|
|
} |
|
|
|