X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=tests%2Ftest-tls.c;h=8f7d516a13e94c4cb9639ce21f22ce10746c8d94;hb=d93e239a6a447bb45b77121739015760aad15584;hp=89107752affc0531b880dd537d34fdb641cbd45a;hpb=57fdfd3f8ec62b105c53bcdf6f127c35c7fe7391;p=gnulib.git diff --git a/tests/test-tls.c b/tests/test-tls.c index 89107752a..8f7d516a1 100644 --- a/tests/test-tls.c +++ b/tests/test-tls.c @@ -1,5 +1,5 @@ /* Test of thread-local storage in multithreaded situations. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2008-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ #include -#if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WIN32_THREADS +#if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WINDOWS_THREADS #if USE_POSIX_THREADS # define TEST_POSIX_THREADS 1 @@ -29,8 +29,8 @@ #if USE_PTH_THREADS # define TEST_PTH_THREADS 1 #endif -#if USE_WIN32_THREADS -# define TEST_WIN32_THREADS 1 +#if USE_WINDOWS_THREADS +# define TEST_WINDOWS_THREADS 1 #endif /* Whether to help the scheduler through explicit yield(). @@ -50,7 +50,9 @@ #include #include -#include "tls.h" +#include "glthread/tls.h" +#include "glthread/thread.h" +#include "glthread/yield.h" #if ENABLE_DEBUGGING # define dbgprintf printf @@ -58,135 +60,13 @@ # define dbgprintf if (0) printf #endif -#if TEST_POSIX_THREADS -# include -# include -typedef pthread_t gl_thread_t; -static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg) -{ - pthread_t thread; - if (pthread_create (&thread, NULL, func, arg) != 0) - abort (); - return thread; -} -static inline void gl_thread_join (gl_thread_t thread) -{ - void *retval; - if (pthread_join (thread, &retval) != 0) - abort (); -} -static inline void gl_thread_yield (void) -{ - sched_yield (); -} -static inline void * gl_thread_self (void) -{ - return (void *) pthread_self (); -} -#endif -#if TEST_PTH_THREADS -# include -typedef pth_t gl_thread_t; -static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg) -{ - pth_t thread = pth_spawn (NULL, func, arg); - if (thread == NULL) - abort (); - return thread; -} -static inline void gl_thread_join (gl_thread_t thread) -{ - if (!pth_join (thread, NULL)) - abort (); -} -static inline void gl_thread_yield (void) -{ - pth_yield (NULL); -} -static inline void * gl_thread_self (void) -{ - return pth_self (); -} -#endif -#if TEST_SOLARIS_THREADS -# include -typedef thread_t gl_thread_t; -static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg) -{ - thread_t thread; - if (thr_create (NULL, 0, func, arg, 0, &thread) != 0) - abort (); - return thread; -} -static inline void gl_thread_join (gl_thread_t thread) -{ - void *retval; - if (thr_join (thread, NULL, &retval) != 0) - abort (); -} -static inline void gl_thread_yield (void) -{ - thr_yield (); -} -static inline void * gl_thread_self (void) -{ - return (void *) thr_self (); -} -#endif -#if TEST_WIN32_THREADS -# include -typedef HANDLE gl_thread_t; -/* Use a wrapper function, instead of adding WINAPI through a cast. */ -struct wrapper_args { void * (*func) (void *); void *arg; }; -static DWORD WINAPI wrapper_func (void *varg) -{ - struct wrapper_args *warg = (struct wrapper_args *)varg; - void * (*func) (void *) = warg->func; - void *arg = warg->arg; - free (warg); - func (arg); - return 0; -} -static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg) -{ - struct wrapper_args *warg = - (struct wrapper_args *) malloc (sizeof (struct wrapper_args)); - if (warg == NULL) - abort (); - warg->func = func; - warg->arg = arg; - { - DWORD thread_id; - HANDLE thread = - CreateThread (NULL, 100000, wrapper_func, warg, 0, &thread_id); - if (thread == NULL) - abort (); - return thread; - } -} -static inline void gl_thread_join (gl_thread_t thread) -{ - if (WaitForSingleObject (thread, INFINITE) == WAIT_FAILED) - abort (); - if (!CloseHandle (thread)) - abort (); -} -static inline void gl_thread_yield (void) -{ - Sleep (0); -} -static inline void * gl_thread_self (void) -{ - return (void *) GetCurrentThreadId (); -} -#endif #if EXPLICIT_YIELD # define yield() gl_thread_yield () #else # define yield() #endif -static inline void +static void perhaps_yield (void) { /* Call yield () only with a certain probability, otherwise with GNU Pth @@ -195,6 +75,9 @@ perhaps_yield (void) yield (); } + +/* ----------------------- Test thread-local storage ----------------------- */ + #define KEYS_COUNT 4 static gl_tls_key_t mykeys[KEYS_COUNT]; @@ -206,67 +89,67 @@ worker_thread (void *arg) int i, j, repeat; unsigned int values[KEYS_COUNT]; - dbgprintf ("Worker %p started\n", gl_thread_self ()); + dbgprintf ("Worker %p started\n", gl_thread_self_pointer ()); /* Initialize the per-thread storage. */ for (i = 0; i < KEYS_COUNT; i++) { - values[i] = (((unsigned int) rand() >> 3) % 1000000) * THREAD_COUNT + id; + values[i] = (((unsigned int) rand () >> 3) % 1000000) * THREAD_COUNT + id; /* Hopefully no arithmetic overflow. */ if ((values[i] % THREAD_COUNT) != id) - abort (); + abort (); } perhaps_yield (); /* Verify that the initial value is NULL. */ - dbgprintf ("Worker %p before initial verify\n", gl_thread_self ()); + dbgprintf ("Worker %p before initial verify\n", gl_thread_self_pointer ()); for (i = 0; i < KEYS_COUNT; i++) if (gl_tls_get (mykeys[i]) != NULL) abort (); - dbgprintf ("Worker %p after initial verify\n", gl_thread_self ()); + dbgprintf ("Worker %p after initial verify\n", gl_thread_self_pointer ()); perhaps_yield (); /* Initialize the per-thread storage. */ - dbgprintf ("Worker %p before first tls_set\n", gl_thread_self ()); + dbgprintf ("Worker %p before first tls_set\n", gl_thread_self_pointer ()); for (i = 0; i < KEYS_COUNT; i++) { unsigned int *ptr = (unsigned int *) malloc (sizeof (unsigned int)); *ptr = values[i]; gl_tls_set (mykeys[i], ptr); } - dbgprintf ("Worker %p after first tls_set\n", gl_thread_self ()); + dbgprintf ("Worker %p after first tls_set\n", gl_thread_self_pointer ()); perhaps_yield (); /* Shuffle around the pointers. */ for (repeat = REPEAT_COUNT; repeat > 0; repeat--) { - dbgprintf ("Worker %p doing value swapping\n", gl_thread_self ()); - i = ((unsigned int) rand() >> 3) % KEYS_COUNT; - j = ((unsigned int) rand() >> 3) % KEYS_COUNT; + dbgprintf ("Worker %p doing value swapping\n", gl_thread_self_pointer ()); + i = ((unsigned int) rand () >> 3) % KEYS_COUNT; + j = ((unsigned int) rand () >> 3) % KEYS_COUNT; if (i != j) - { - void *vi = gl_tls_get (mykeys[i]); - void *vj = gl_tls_get (mykeys[j]); + { + void *vi = gl_tls_get (mykeys[i]); + void *vj = gl_tls_get (mykeys[j]); - gl_tls_set (mykeys[i], vj); - gl_tls_set (mykeys[j], vi); - } + gl_tls_set (mykeys[i], vj); + gl_tls_set (mykeys[j], vi); + } perhaps_yield (); } /* Verify that all the values are from this thread. */ - dbgprintf ("Worker %p before final verify\n", gl_thread_self ()); + dbgprintf ("Worker %p before final verify\n", gl_thread_self_pointer ()); for (i = 0; i < KEYS_COUNT; i++) if ((*(unsigned int *) gl_tls_get (mykeys[i]) % THREAD_COUNT) != id) abort (); - dbgprintf ("Worker %p after final verify\n", gl_thread_self ()); + dbgprintf ("Worker %p after final verify\n", gl_thread_self_pointer ()); perhaps_yield (); - dbgprintf ("Worker %p dying.\n", gl_thread_self ()); + dbgprintf ("Worker %p dying.\n", gl_thread_self_pointer ()); return NULL; } -void +static void test_tls (void) { int pass, i; @@ -276,25 +159,28 @@ test_tls (void) gl_thread_t threads[THREAD_COUNT]; if (pass == 0) - for (i = 0; i < KEYS_COUNT; i++) - gl_tls_key_init (mykeys[i], free); + for (i = 0; i < KEYS_COUNT; i++) + gl_tls_key_init (mykeys[i], free); else - for (i = KEYS_COUNT - 1; i >= 0; i--) - gl_tls_key_init (mykeys[i], free); + for (i = KEYS_COUNT - 1; i >= 0; i--) + gl_tls_key_init (mykeys[i], free); /* Spawn the threads. */ for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (worker_thread, NULL); + threads[i] = gl_thread_create (worker_thread, NULL); /* Wait for the threads to terminate. */ for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i]); + gl_thread_join (threads[i], NULL); for (i = 0; i < KEYS_COUNT; i++) - gl_tls_key_destroy (mykeys[i]); + gl_tls_key_destroy (mykeys[i]); } } + +/* -------------------------------------------------------------------------- */ + int main () { @@ -314,9 +200,12 @@ main () /* No multithreading available. */ +#include + int main () { + fputs ("Skipping test: multithreading not enabled\n", stderr); return 77; }