From b20e8afb0b2cc9548fac073d71fcd19ede29ce60 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 5 Jan 2017 23:49:34 +0100 Subject: [PATCH] lock tests: Prefer semaphore over mutex. * tests/test-lock.c (USE_SEMAPHORE): New constant. (struct atomic_int, init_atomic_int, get_atomic_int_value, set_atomic_int_value) [USE_SEMAPHORE]: Define using a POSIX semaphore. Suggested by Torvald Riegel . --- ChangeLog | 8 +++++++ tests/test-lock.c | 55 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11b8eaa571..ebd491f846 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,14 @@ thus supporting parallel processing of each one, particularly build-coverage, which builds and runs tests. +2017-01-05 Bruno Haible + + lock tests: Prefer semaphore over mutex. + * tests/test-lock.c (USE_SEMAPHORE): New constant. + (struct atomic_int, init_atomic_int, get_atomic_int_value, + set_atomic_int_value) [USE_SEMAPHORE]: Define using a POSIX semaphore. + Suggested by Torvald Riegel . + 2017-01-05 Bruno Haible lock: Provide guarantee to avoid writer starvation for rwlocks. diff --git a/tests/test-lock.c b/tests/test-lock.c index 095511ecf8..f3da4ccdfd 100644 --- a/tests/test-lock.c +++ b/tests/test-lock.c @@ -51,12 +51,20 @@ #define EXPLICIT_YIELD 1 /* Whether to use 'volatile' on some variables that communicate information - between threads. If set to 0, 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. */ + 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 +/* 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 +#endif + /* Whether to print debugging messages. */ #define ENABLE_DEBUGGING 0 @@ -97,6 +105,10 @@ #include "glthread/thread.h" #include "glthread/yield.h" +#if USE_SEMAPHORE +# include +# include +#endif #if ENABLE_DEBUGGING # define dbgprintf printf @@ -128,6 +140,41 @@ 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. */ +struct atomic_int { + sem_t semaphore; +}; +static void +init_atomic_int (struct atomic_int *ai) +{ + sem_init (&ai->semaphore, 0, 0); +} +static int +get_atomic_int_value (struct atomic_int *ai) +{ + if (sem_trywait (&ai->semaphore) == 0) + { + if (sem_post (&ai->semaphore)) + 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 (&ai->semaphore)) + abort (); +} #else struct atomic_int { gl_lock_define (, lock) -- 2.39.5