diff options
author | Bruno Haible <bruno@clisp.org> | 2019-06-20 04:16:20 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2019-06-20 04:17:11 +0200 |
commit | 0894f96f89e0e44bdf2921e6cd51fca429bf9802 (patch) | |
tree | 24ba548ed51d2b75af2299102410646764738c67 /lib/glthread/thread.c | |
parent | 7435d61f26ef6dece4f94ea00972145b587ef7ab (diff) | |
download | gnulib-0894f96f89e0e44bdf2921e6cd51fca429bf9802.tar.gz |
windows-thread: New module.
* lib/windows-thread.h: New file, based on lib/glthread/thread.h.
* lib/windows-thread.c: New file, based on lib/glthread/thread.c.
* lib/glthread/thread.h: Include windows-thread.h.
(gl_thread_t): Define using glwthread_thread_t.
(glthread_create): Define using glwthread_thread_create.
(glthread_join): Define using glwthread_thread_join.
(gl_thread_self): Define using glwthread_thread_self.
(gl_thread_exit): Define using glwthread_thread_exit.
(glthread_create_func, glthread_join_func, gl_thread_self_func,
gl_thread_exit_func): Remove declarations.
* lib/glthread/thread.c (self_key): Remove variable.
(do_init_self_key, init_self_key): Remove functions.
(struct gl_thread_struct): Remove type.
(get_current_thread_handle, gl_thread_self_func, wrapper_func,
glthread_create_func, glthread_join_func, gl_thread_exit_func): Remove
functions.
* modules/windows-thread: New file.
* modules/thread (Depends-on): Add windows-thread.
Diffstat (limited to 'lib/glthread/thread.c')
-rw-r--r-- | lib/glthread/thread.c | 182 |
1 files changed, 0 insertions, 182 deletions
diff --git a/lib/glthread/thread.c b/lib/glthread/thread.c index 9461949911..9da054242b 100644 --- a/lib/glthread/thread.c +++ b/lib/glthread/thread.c @@ -45,188 +45,6 @@ const gl_thread_t gl_null_thread /* = { .p = NULL } */; #if USE_WINDOWS_THREADS -#include <process.h> - -/* -------------------------- gl_thread_t datatype -------------------------- */ - -/* The Thread-Local Storage (TLS) key that allows to access each thread's - 'struct gl_thread_struct *' pointer. */ -static DWORD self_key = (DWORD)-1; - -/* Initializes self_key. This function must only be called once. */ -static void -do_init_self_key (void) -{ - self_key = TlsAlloc (); - /* If this fails, we're hosed. */ - if (self_key == (DWORD)-1) - abort (); -} - -/* Initializes self_key. */ -static void -init_self_key (void) -{ - gl_once_define(static, once) - gl_once (once, do_init_self_key); -} - -/* This structure contains information about a thread. - It is stored in TLS under key self_key. */ -struct gl_thread_struct -{ - /* Fields for managing the handle. */ - HANDLE volatile handle; - CRITICAL_SECTION handle_lock; - /* Fields for managing the exit value. */ - void * volatile result; - /* Fields for managing the thread start. */ - void * (*func) (void *); - void *arg; -}; - -/* Return a real HANDLE object for the current thread. */ -static HANDLE -get_current_thread_handle (void) -{ - HANDLE this_handle; - - /* GetCurrentThread() returns a pseudo-handle, i.e. only a symbolic - identifier, not a real handle. */ - if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), - GetCurrentProcess (), &this_handle, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - abort (); - return this_handle; -} - -gl_thread_t -gl_thread_self_func (void) -{ - gl_thread_t thread; - - if (self_key == (DWORD)-1) - init_self_key (); - thread = TlsGetValue (self_key); - if (thread == NULL) - { - /* This happens only in threads that have not been created through - glthread_create(), such as the main thread. */ - for (;;) - { - thread = - (struct gl_thread_struct *) - malloc (sizeof (struct gl_thread_struct)); - if (thread != NULL) - break; - /* Memory allocation failed. There is not much we can do. Have to - busy-loop, waiting for the availability of memory. */ - Sleep (1); - } - - thread->handle = get_current_thread_handle (); - InitializeCriticalSection (&thread->handle_lock); - thread->result = NULL; /* just to be deterministic */ - TlsSetValue (self_key, thread); - } - return thread; -} - -/* The main function of a freshly creating thread. It's a wrapper around - the FUNC and ARG arguments passed to glthread_create_func. */ -static unsigned int WINAPI -wrapper_func (void *varg) -{ - struct gl_thread_struct *thread = (struct gl_thread_struct *)varg; - - EnterCriticalSection (&thread->handle_lock); - /* Create a new handle for the thread only if the parent thread did not yet - fill in the handle. */ - if (thread->handle == NULL) - thread->handle = get_current_thread_handle (); - LeaveCriticalSection (&thread->handle_lock); - - if (self_key == (DWORD)-1) - init_self_key (); - TlsSetValue (self_key, thread); - - /* Run the thread. Store the exit value if the thread was not terminated - otherwise. */ - thread->result = thread->func (thread->arg); - return 0; -} - -int -glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg) -{ - struct gl_thread_struct *thread = - (struct gl_thread_struct *) malloc (sizeof (struct gl_thread_struct)); - if (thread == NULL) - return ENOMEM; - thread->handle = NULL; - InitializeCriticalSection (&thread->handle_lock); - thread->result = NULL; /* just to be deterministic */ - thread->func = func; - thread->arg = arg; - - { - unsigned int thread_id; - HANDLE thread_handle; - - thread_handle = (HANDLE) - _beginthreadex (NULL, 100000, wrapper_func, thread, 0, &thread_id); - /* calls CreateThread with the same arguments */ - if (thread_handle == NULL) - { - DeleteCriticalSection (&thread->handle_lock); - free (thread); - return EAGAIN; - } - - EnterCriticalSection (&thread->handle_lock); - if (thread->handle == NULL) - thread->handle = thread_handle; - else - /* thread->handle was already set by the thread itself. */ - CloseHandle (thread_handle); - LeaveCriticalSection (&thread->handle_lock); - - *threadp = thread; - return 0; - } -} - -int -glthread_join_func (gl_thread_t thread, void **retvalp) -{ - if (thread == NULL) - return EINVAL; - - if (thread == gl_thread_self ()) - return EDEADLK; - - if (WaitForSingleObject (thread->handle, INFINITE) == WAIT_FAILED) - return EINVAL; - - if (retvalp != NULL) - *retvalp = thread->result; - - DeleteCriticalSection (&thread->handle_lock); - CloseHandle (thread->handle); - free (thread); - - return 0; -} - -int -gl_thread_exit_func (void *retval) -{ - gl_thread_t thread = gl_thread_self (); - thread->result = retval; - _endthreadex (0); /* calls ExitThread (0) */ - abort (); -} - #endif /* ========================================================================= */ |