From: Bruno Haible Date: Sat, 27 Apr 2019 22:14:03 +0000 (+0200) Subject: build: Remove duplicate copy of test-lock. X-Git-Tag: v0.20~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a6ee4c502485811f69ab85abd5ad5ecccc7e7444;p=thirdparty%2Fgettext.git build: Remove duplicate copy of test-lock. The master copy lives in gnulib now. * gettext-runtime/tests/test-lock.c: Remove file. * gettext-runtime/tests/Makefile.am (TESTS, check_PROGRAMS): Remove test-lock. (test_lock_SOURCES, test_lock_LDADD): Remove variables. --- diff --git a/gettext-runtime/tests/Makefile.am b/gettext-runtime/tests/Makefile.am index 715a04a4f..86c945bc8 100644 --- a/gettext-runtime/tests/Makefile.am +++ b/gettext-runtime/tests/Makefile.am @@ -1,5 +1,5 @@ ## Makefile for the gettext-runtime/tests subdirectory of GNU gettext -## Copyright (C) 2005-2006, 2008-2009, 2014-2015 Free Software Foundation, Inc. +## Copyright (C) 2005-2006, 2008-2009, 2014-2015, 2019 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 @@ -19,15 +19,13 @@ AUTOMAKE_OPTIONS = 1.11 gnits no-dependencies color-tests subdir-objects EXTRA_DIST = -TESTS = test-lock +TESTS = AM_CPPFLAGS = \ -I.. \ -I$(srcdir)/../intl -check_PROGRAMS = test-lock -test_lock_SOURCES = test-lock.c ../intl/lock.c ../intl/threadlib.c -test_lock_LDADD = @LIBMULTITHREAD@ @LIBSCHED@ +check_PROGRAMS = # Clean up after Solaris cc. clean-local: diff --git a/gettext-runtime/tests/test-lock.c b/gettext-runtime/tests/test-lock.c deleted file mode 100644 index 2468ba9eb..000000000 --- a/gettext-runtime/tests/test-lock.c +++ /dev/null @@ -1,870 +0,0 @@ -/* Test of locking in multithreaded situations. - Copyright (C) 2005, 2008-2017 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by Bruno Haible , 2005. */ - -#include - -#if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WINDOWS_THREADS - -#if USE_POSIX_THREADS -# define TEST_POSIX_THREADS 1 -#endif -#if USE_SOLARIS_THREADS -# define TEST_SOLARIS_THREADS 1 -#endif -#if USE_PTH_THREADS -# define TEST_PTH_THREADS 1 -#endif -#if USE_WINDOWS_THREADS -# define TEST_WINDOWS_THREADS 1 -#endif - -/* Whether to enable locking. - Uncomment this to get a test program without locking, to verify that - it crashes. */ -#define ENABLE_LOCKING 1 - -/* Which tests to perform. - Uncomment some of these, to verify that all tests crash if no locking - is enabled. */ -#define DO_TEST_LOCK 1 -#define DO_TEST_RWLOCK 1 -#define DO_TEST_RECURSIVE_LOCK 1 -#define DO_TEST_ONCE 1 - -/* Whether to help the scheduler through explicit yield(). - Uncomment this to see if the operating system has a fair scheduler. */ -#define EXPLICIT_YIELD 1 - -/* Whether to use 'volatile' on some variables that communicate information - between threads. If set to 0, a semaphore or a lock is used to protect - these variables. If set to 1, 'volatile' is used; this is theoretically - equivalent but can lead to much slower execution (e.g. 30x slower total - run time on a 40-core machine), because 'volatile' does not imply any - synchronization/communication between different CPUs. */ -#define USE_VOLATILE 0 - -#if USE_POSIX_THREADS && HAVE_SEMAPHORE_H -/* Whether to use a semaphore to communicate information between threads. - If set to 0, a lock is used. If set to 1, a semaphore is used. - Uncomment this to reduce the dependencies of this test. */ -# define USE_SEMAPHORE 1 -/* Mac OS X provides only named semaphores (sem_open); its facility for - unnamed semaphores (sem_init) does not work. */ -# if defined __APPLE__ && defined __MACH__ -# define USE_NAMED_SEMAPHORE 1 -# else -# define USE_UNNAMED_SEMAPHORE 1 -# endif -#endif - -/* Whether to print debugging messages. */ -#define ENABLE_DEBUGGING 0 - -/* Number of simultaneous threads. */ -#define THREAD_COUNT 10 - -/* Number of operations performed in each thread. - This is quite high, because with a smaller count, say 5000, we often get - an "OK" result even without ENABLE_LOCKING (on Linux/x86). */ -#define REPEAT_COUNT 50000 - -#include -#include -#include - -#if !ENABLE_LOCKING -# undef USE_POSIX_THREADS -# undef USE_SOLARIS_THREADS -# undef USE_PTH_THREADS -# undef USE_WINDOWS_THREADS -#endif -#include "lock.h" - -#if USE_SEMAPHORE -# include -# include -# include -# include -#endif - -#if ENABLE_DEBUGGING -# define dbgprintf printf -#else -# define dbgprintf if (0) printf -#endif - -#if TEST_POSIX_THREADS -# include -# ifndef __KLIBC__ -# include -# else -# define sched_yield() pthread_yield() -# endif -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 **retvalp) -{ - if (pthread_join (thread, retvalp) != 0) - abort (); -} -static inline void gl_thread_yield (void) -{ - sched_yield (); -} -static inline void * gl_thread_self_pointer (void) -{ -# ifdef PTW32_VERSION - return pthread_self ().p; -# else - return (void *) pthread_self (); -# endif -} -#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, void **retvalp) -{ - if (!pth_join (thread, retvalp)) - abort (); -} -static inline void gl_thread_yield (void) -{ - pth_yield (NULL); -} -static inline void * gl_thread_self_pointer (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 **retvalp) -{ - if (thr_join (thread, NULL, retvalp) != 0) - abort (); -} -static inline void gl_thread_yield (void) -{ - thr_yield (); -} -static inline void * gl_thread_self_pointer (void) -{ - return (void *) thr_self (); -} -#endif -#if TEST_WINDOWS_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, void **retvalp) -{ - (void) retvalp; - 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_pointer (void) -{ - return (void *) GetCurrentThreadId (); -} -#endif -#if EXPLICIT_YIELD -# define yield() gl_thread_yield () -#else -# define yield() -#endif - -#if USE_VOLATILE -struct atomic_int { - volatile int value; -}; -static void -init_atomic_int (struct atomic_int *ai) -{ -} -static int -get_atomic_int_value (struct atomic_int *ai) -{ - return ai->value; -} -static void -set_atomic_int_value (struct atomic_int *ai, int new_value) -{ - ai->value = new_value; -} -#elif USE_SEMAPHORE -/* This atomic_int implementation can only support the values 0 and 1. - It is initially 0 and can be set to 1 only once. */ -# if USE_UNNAMED_SEMAPHORE -struct atomic_int { - sem_t semaphore; -}; -#define atomic_int_semaphore(ai) (&(ai)->semaphore) -static void -init_atomic_int (struct atomic_int *ai) -{ - sem_init (&ai->semaphore, 0, 0); -} -# endif -# if USE_NAMED_SEMAPHORE -struct atomic_int { - sem_t *semaphore; -}; -#define atomic_int_semaphore(ai) ((ai)->semaphore) -static void -init_atomic_int (struct atomic_int *ai) -{ - sem_t *s; - unsigned int count; - for (count = 0; ; count++) - { - char name[80]; - /* Use getpid() in the name, so that different processes running at the - same time will not interfere. Use ai in the name, so that different - atomic_int in the same process will not interfere. Use a count in - the name, so that even in the (unlikely) case that a semaphore with - the specified name already exists, we can try a different name. */ - sprintf (name, "test-lock-%lu-%p-%u", - (unsigned long) getpid (), ai, count); - s = sem_open (name, O_CREAT | O_EXCL, 0600, 0); - if (s == SEM_FAILED) - { - if (errno == EEXIST) - /* Retry with a different name. */ - continue; - else - { - perror ("sem_open failed"); - abort (); - } - } - else - { - /* Try not to leave a semaphore hanging around on the file system - eternally, if we can avoid it. */ - sem_unlink (name); - break; - } - } - ai->semaphore = s; -} -# endif -static int -get_atomic_int_value (struct atomic_int *ai) -{ - if (sem_trywait (atomic_int_semaphore (ai)) == 0) - { - if (sem_post (atomic_int_semaphore (ai))) - abort (); - return 1; - } - else if (errno == EAGAIN) - return 0; - else - abort (); -} -static void -set_atomic_int_value (struct atomic_int *ai, int new_value) -{ - if (new_value == 0) - /* It's already initialized with 0. */ - return; - /* To set the value 1: */ - if (sem_post (atomic_int_semaphore (ai))) - abort (); -} -#else -struct atomic_int { - gl_lock_define (, lock) - int value; -}; -static void -init_atomic_int (struct atomic_int *ai) -{ - gl_lock_init (ai->lock); -} -static int -get_atomic_int_value (struct atomic_int *ai) -{ - gl_lock_lock (ai->lock); - int ret = ai->value; - gl_lock_unlock (ai->lock); - return ret; -} -static void -set_atomic_int_value (struct atomic_int *ai, int new_value) -{ - gl_lock_lock (ai->lock); - ai->value = new_value; - gl_lock_unlock (ai->lock); -} -#endif - -#define ACCOUNT_COUNT 4 - -static int account[ACCOUNT_COUNT]; - -static int -random_account (void) -{ - return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT; -} - -static void -check_accounts (void) -{ - int i, sum; - - sum = 0; - for (i = 0; i < ACCOUNT_COUNT; i++) - sum += account[i]; - if (sum != ACCOUNT_COUNT * 1000) - abort (); -} - - -/* ------------------- Test normal (non-recursive) locks ------------------- */ - -/* Test normal locks by having several bank accounts and several threads - which shuffle around money between the accounts and another thread - checking that all the money is still there. */ - -gl_lock_define_initialized(static, my_lock) - -static void * -lock_mutator_thread (void *arg) -{ - int repeat; - - for (repeat = REPEAT_COUNT; repeat > 0; repeat--) - { - int i1, i2, value; - - dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ()); - gl_lock_lock (my_lock); - dbgprintf ("Mutator %p after lock\n", gl_thread_self_pointer ()); - - i1 = random_account (); - i2 = random_account (); - value = ((unsigned int) rand () >> 3) % 10; - account[i1] += value; - account[i2] -= value; - - dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ()); - gl_lock_unlock (my_lock); - dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ()); - - dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ()); - gl_lock_lock (my_lock); - check_accounts (); - gl_lock_unlock (my_lock); - dbgprintf ("Mutator %p after check unlock\n", gl_thread_self_pointer ()); - - yield (); - } - - dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ()); - return NULL; -} - -static struct atomic_int lock_checker_done; - -static void * -lock_checker_thread (void *arg) -{ - while (get_atomic_int_value (&lock_checker_done) == 0) - { - dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ()); - gl_lock_lock (my_lock); - check_accounts (); - gl_lock_unlock (my_lock); - dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ()); - - yield (); - } - - dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ()); - return NULL; -} - -static void -test_lock (void) -{ - int i; - gl_thread_t checkerthread; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialization. */ - for (i = 0; i < ACCOUNT_COUNT; i++) - account[i] = 1000; - init_atomic_int (&lock_checker_done); - set_atomic_int_value (&lock_checker_done, 0); - - /* Spawn the threads. */ - checkerthread = gl_thread_create (lock_checker_thread, NULL); - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (lock_mutator_thread, NULL); - - /* Wait for the threads to terminate. */ - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i], NULL); - set_atomic_int_value (&lock_checker_done, 1); - gl_thread_join (checkerthread, NULL); - check_accounts (); -} - - -/* ----------------- Test read-write (non-recursive) locks ----------------- */ - -/* Test read-write locks by having several bank accounts and several threads - which shuffle around money between the accounts and several other threads - that check that all the money is still there. */ - -gl_rwlock_define_initialized(static, my_rwlock) - -static void * -rwlock_mutator_thread (void *arg) -{ - int repeat; - - for (repeat = REPEAT_COUNT; repeat > 0; repeat--) - { - int i1, i2, value; - - dbgprintf ("Mutator %p before wrlock\n", gl_thread_self_pointer ()); - gl_rwlock_wrlock (my_rwlock); - dbgprintf ("Mutator %p after wrlock\n", gl_thread_self_pointer ()); - - i1 = random_account (); - i2 = random_account (); - value = ((unsigned int) rand () >> 3) % 10; - account[i1] += value; - account[i2] -= value; - - dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ()); - gl_rwlock_unlock (my_rwlock); - dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ()); - - yield (); - } - - dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ()); - return NULL; -} - -static struct atomic_int rwlock_checker_done; - -static void * -rwlock_checker_thread (void *arg) -{ - while (get_atomic_int_value (&rwlock_checker_done) == 0) - { - dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ()); - gl_rwlock_rdlock (my_rwlock); - check_accounts (); - gl_rwlock_unlock (my_rwlock); - dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ()); - - yield (); - } - - dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ()); - return NULL; -} - -static void -test_rwlock (void) -{ - int i; - gl_thread_t checkerthreads[THREAD_COUNT]; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialization. */ - for (i = 0; i < ACCOUNT_COUNT; i++) - account[i] = 1000; - init_atomic_int (&rwlock_checker_done); - set_atomic_int_value (&rwlock_checker_done, 0); - - /* Spawn the threads. */ - for (i = 0; i < THREAD_COUNT; i++) - checkerthreads[i] = gl_thread_create (rwlock_checker_thread, NULL); - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (rwlock_mutator_thread, NULL); - - /* Wait for the threads to terminate. */ - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i], NULL); - set_atomic_int_value (&rwlock_checker_done, 1); - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (checkerthreads[i], NULL); - check_accounts (); -} - - -/* -------------------------- Test recursive locks -------------------------- */ - -/* Test recursive locks by having several bank accounts and several threads - which shuffle around money between the accounts (recursively) and another - thread checking that all the money is still there. */ - -gl_recursive_lock_define_initialized(static, my_reclock) - -static void -recshuffle (void) -{ - int i1, i2, value; - - dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ()); - gl_recursive_lock_lock (my_reclock); - dbgprintf ("Mutator %p after lock\n", gl_thread_self_pointer ()); - - i1 = random_account (); - i2 = random_account (); - value = ((unsigned int) rand () >> 3) % 10; - account[i1] += value; - account[i2] -= value; - - /* Recursive with probability 0.5. */ - if (((unsigned int) rand () >> 3) % 2) - recshuffle (); - - dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ()); - gl_recursive_lock_unlock (my_reclock); - dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ()); -} - -static void * -reclock_mutator_thread (void *arg) -{ - int repeat; - - for (repeat = REPEAT_COUNT; repeat > 0; repeat--) - { - recshuffle (); - - dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ()); - gl_recursive_lock_lock (my_reclock); - check_accounts (); - gl_recursive_lock_unlock (my_reclock); - dbgprintf ("Mutator %p after check unlock\n", gl_thread_self_pointer ()); - - yield (); - } - - dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ()); - return NULL; -} - -static struct atomic_int reclock_checker_done; - -static void * -reclock_checker_thread (void *arg) -{ - while (get_atomic_int_value (&reclock_checker_done) == 0) - { - dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ()); - gl_recursive_lock_lock (my_reclock); - check_accounts (); - gl_recursive_lock_unlock (my_reclock); - dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ()); - - yield (); - } - - dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ()); - return NULL; -} - -static void -test_recursive_lock (void) -{ - int i; - gl_thread_t checkerthread; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialization. */ - for (i = 0; i < ACCOUNT_COUNT; i++) - account[i] = 1000; - init_atomic_int (&reclock_checker_done); - set_atomic_int_value (&reclock_checker_done, 0); - - /* Spawn the threads. */ - checkerthread = gl_thread_create (reclock_checker_thread, NULL); - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (reclock_mutator_thread, NULL); - - /* Wait for the threads to terminate. */ - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i], NULL); - set_atomic_int_value (&reclock_checker_done, 1); - gl_thread_join (checkerthread, NULL); - check_accounts (); -} - - -/* ------------------------ Test once-only execution ------------------------ */ - -/* Test once-only execution by having several threads attempt to grab a - once-only task simultaneously (triggered by releasing a read-write lock). */ - -gl_once_define(static, fresh_once) -static int ready[THREAD_COUNT]; -static gl_lock_t ready_lock[THREAD_COUNT]; -#if ENABLE_LOCKING -static gl_rwlock_t fire_signal[REPEAT_COUNT]; -#else -static volatile int fire_signal_state; -#endif -static gl_once_t once_control; -static int performed; -gl_lock_define_initialized(static, performed_lock) - -static void -once_execute (void) -{ - gl_lock_lock (performed_lock); - performed++; - gl_lock_unlock (performed_lock); -} - -static void * -once_contender_thread (void *arg) -{ - int id = (int) (long) arg; - int repeat; - - for (repeat = 0; repeat <= REPEAT_COUNT; repeat++) - { - /* Tell the main thread that we're ready. */ - gl_lock_lock (ready_lock[id]); - ready[id] = 1; - gl_lock_unlock (ready_lock[id]); - - if (repeat == REPEAT_COUNT) - break; - - dbgprintf ("Contender %p waiting for signal for round %d\n", - gl_thread_self_pointer (), repeat); -#if ENABLE_LOCKING - /* Wait for the signal to go. */ - gl_rwlock_rdlock (fire_signal[repeat]); - /* And don't hinder the others (if the scheduler is unfair). */ - gl_rwlock_unlock (fire_signal[repeat]); -#else - /* Wait for the signal to go. */ - while (fire_signal_state <= repeat) - yield (); -#endif - dbgprintf ("Contender %p got the signal for round %d\n", - gl_thread_self_pointer (), repeat); - - /* Contend for execution. */ - gl_once (once_control, once_execute); - } - - return NULL; -} - -static void -test_once (void) -{ - int i, repeat; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialize all variables. */ - for (i = 0; i < THREAD_COUNT; i++) - { - ready[i] = 0; - gl_lock_init (ready_lock[i]); - } -#if ENABLE_LOCKING - for (i = 0; i < REPEAT_COUNT; i++) - gl_rwlock_init (fire_signal[i]); -#else - fire_signal_state = 0; -#endif - - /* Block all fire_signals. */ - for (i = REPEAT_COUNT-1; i >= 0; i--) - gl_rwlock_wrlock (fire_signal[i]); - - /* Spawn the threads. */ - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (once_contender_thread, (void *) (long) i); - - for (repeat = 0; repeat <= REPEAT_COUNT; repeat++) - { - /* Wait until every thread is ready. */ - dbgprintf ("Main thread before synchronizing for round %d\n", repeat); - for (;;) - { - int ready_count = 0; - for (i = 0; i < THREAD_COUNT; i++) - { - gl_lock_lock (ready_lock[i]); - ready_count += ready[i]; - gl_lock_unlock (ready_lock[i]); - } - if (ready_count == THREAD_COUNT) - break; - yield (); - } - dbgprintf ("Main thread after synchronizing for round %d\n", repeat); - - if (repeat > 0) - { - /* Check that exactly one thread executed the once_execute() - function. */ - if (performed != 1) - abort (); - } - - if (repeat == REPEAT_COUNT) - break; - - /* Preparation for the next round: Initialize once_control. */ - memcpy (&once_control, &fresh_once, sizeof (gl_once_t)); - - /* Preparation for the next round: Reset the performed counter. */ - performed = 0; - - /* Preparation for the next round: Reset the ready flags. */ - for (i = 0; i < THREAD_COUNT; i++) - { - gl_lock_lock (ready_lock[i]); - ready[i] = 0; - gl_lock_unlock (ready_lock[i]); - } - - /* Signal all threads simultaneously. */ - dbgprintf ("Main thread giving signal for round %d\n", repeat); -#if ENABLE_LOCKING - gl_rwlock_unlock (fire_signal[repeat]); -#else - fire_signal_state = repeat + 1; -#endif - } - - /* Wait for the threads to terminate. */ - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i], NULL); -} - - -/* -------------------------------------------------------------------------- */ - -int -main () -{ -#if TEST_PTH_THREADS - if (!pth_init ()) - abort (); -#endif - -#if DO_TEST_LOCK - printf ("Starting test_lock ..."); fflush (stdout); - test_lock (); - printf (" OK\n"); fflush (stdout); -#endif -#if DO_TEST_RWLOCK - printf ("Starting test_rwlock ..."); fflush (stdout); - test_rwlock (); - printf (" OK\n"); fflush (stdout); -#endif -#if DO_TEST_RECURSIVE_LOCK - printf ("Starting test_recursive_lock ..."); fflush (stdout); - test_recursive_lock (); - printf (" OK\n"); fflush (stdout); -#endif -#if DO_TEST_ONCE - printf ("Starting test_once ..."); fflush (stdout); - test_once (); - printf (" OK\n"); fflush (stdout); -#endif - - return 0; -} - -#else - -/* No multithreading available. */ - -#include - -int -main () -{ - fputs ("Skipping test: multithreading not enabled\n", stderr); - return 77; -} - -#endif