maint: update copyright
[gnulib.git] / tests / test-tls.c
index f8c971c..9eb0b13 100644 (file)
@@ -1,10 +1,10 @@
 /* Test of thread-local storage in multithreaded situations.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2008-2014 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or modify
+   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
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2005.  */
 
 #include <config.h>
 
-#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
@@ -30,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().
@@ -51,7 +50,9 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "tls.h"
+#include "glthread/tls.h"
+#include "glthread/thread.h"
+#include "glthread/yield.h"
 
 #if ENABLE_DEBUGGING
 # define dbgprintf printf
 # define dbgprintf if (0) printf
 #endif
 
-#if TEST_POSIX_THREADS
-# include <pthread.h>
-# include <sched.h>
-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 <pth.h>
-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 <thread.h>
-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 <windows.h>
-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
@@ -196,6 +75,9 @@ perhaps_yield (void)
     yield ();
 }
 
+
+/* ----------------------- Test thread-local storage ----------------------- */
+
 #define KEYS_COUNT 4
 
 static gl_tls_key_t mykeys[KEYS_COUNT];
@@ -207,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;
@@ -277,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 ()
 {
@@ -315,9 +200,12 @@ main ()
 
 /* No multithreading available.  */
 
+#include <stdio.h>
+
 int
 main ()
 {
+  fputs ("Skipping test: multithreading not enabled\n", stderr);
   return 77;
 }