LCOV - code coverage report
Current view: top level - lib/gltests - test-lock.c (source / functions) Hit Total Coverage
Test: GNU Libidn Lines: 184 188 97.9 %
Date: 2020-07-22 17:53:13 Functions: 16 16 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Test of locking in multithreaded situations.
       2             :    Copyright (C) 2005, 2008-2020 Free Software Foundation, Inc.
       3             : 
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation; either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16             : 
      17             : /* Written by Bruno Haible <bruno@clisp.org>, 2005.  */
      18             : 
      19             : #include <config.h>
      20             : 
      21             : #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
      22             : 
      23             : #if USE_ISOC_THREADS
      24             : # define TEST_ISOC_THREADS 1
      25             : #endif
      26             : #if USE_POSIX_THREADS
      27             : # define TEST_POSIX_THREADS 1
      28             : #endif
      29             : #if USE_ISOC_AND_POSIX_THREADS
      30             : # define TEST_ISOC_AND_POSIX_THREADS 1
      31             : #endif
      32             : #if USE_WINDOWS_THREADS
      33             : # define TEST_WINDOWS_THREADS 1
      34             : #endif
      35             : 
      36             : /* Whether to enable locking.
      37             :    Uncomment this to get a test program without locking, to verify that
      38             :    it crashes.  */
      39             : #define ENABLE_LOCKING 1
      40             : 
      41             : /* Which tests to perform.
      42             :    Uncomment some of these, to verify that all tests crash if no locking
      43             :    is enabled.  */
      44             : #define DO_TEST_LOCK 1
      45             : #define DO_TEST_RWLOCK 1
      46             : #define DO_TEST_RECURSIVE_LOCK 1
      47             : #define DO_TEST_ONCE 1
      48             : 
      49             : /* Whether to help the scheduler through explicit yield().
      50             :    Uncomment this to see if the operating system has a fair scheduler.  */
      51             : #define EXPLICIT_YIELD 1
      52             : 
      53             : /* Whether to print debugging messages.  */
      54             : #define ENABLE_DEBUGGING 0
      55             : 
      56             : /* Number of simultaneous threads.  */
      57             : #define THREAD_COUNT 10
      58             : 
      59             : /* Number of operations performed in each thread.
      60             :    This is quite high, because with a smaller count, say 5000, we often get
      61             :    an "OK" result even without ENABLE_LOCKING (on Linux/x86).  */
      62             : #define REPEAT_COUNT 50000
      63             : 
      64             : #include <stdint.h>
      65             : #include <stdio.h>
      66             : #include <stdlib.h>
      67             : #include <string.h>
      68             : 
      69             : #if !ENABLE_LOCKING
      70             : # undef USE_ISOC_THREADS
      71             : # undef USE_POSIX_THREADS
      72             : # undef USE_ISOC_AND_POSIX_THREADS
      73             : # undef USE_WINDOWS_THREADS
      74             : #endif
      75             : #include "glthread/lock.h"
      76             : 
      77             : #if !ENABLE_LOCKING
      78             : # if TEST_ISOC_THREADS
      79             : #  define USE_ISOC_THREADS 1
      80             : # endif
      81             : # if TEST_POSIX_THREADS
      82             : #  define USE_POSIX_THREADS 1
      83             : # endif
      84             : # if TEST_ISOC_AND_POSIX_THREADS
      85             : #  define USE_ISOC_AND_POSIX_THREADS 1
      86             : # endif
      87             : # if TEST_WINDOWS_THREADS
      88             : #  define USE_WINDOWS_THREADS 1
      89             : # endif
      90             : #endif
      91             : 
      92             : #include "glthread/thread.h"
      93             : #include "glthread/yield.h"
      94             : 
      95             : #if HAVE_DECL_ALARM
      96             : # include <signal.h>
      97             : # include <unistd.h>
      98             : #endif
      99             : 
     100             : #include "atomic-int-gnulib.h"
     101             : 
     102             : #if ENABLE_DEBUGGING
     103             : # define dbgprintf printf
     104             : #else
     105             : # define dbgprintf if (0) printf
     106             : #endif
     107             : 
     108             : #if EXPLICIT_YIELD
     109             : # define yield() gl_thread_yield ()
     110             : #else
     111             : # define yield()
     112             : #endif
     113             : 
     114             : #define ACCOUNT_COUNT 4
     115             : 
     116             : static int account[ACCOUNT_COUNT];
     117             : 
     118             : static int
     119     4002468 : random_account (void)
     120             : {
     121     4002468 :   return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
     122             : }
     123             : 
     124             : static void
     125     1397026 : check_accounts (void)
     126             : {
     127             :   int i, sum;
     128             : 
     129     1397026 :   sum = 0;
     130     6981277 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     131     5584251 :     sum += account[i];
     132     1397026 :   if (sum != ACCOUNT_COUNT * 1000)
     133           0 :     abort ();
     134     1397026 : }
     135             : 
     136             : 
     137             : /* ------------------- Test normal (non-recursive) locks ------------------- */
     138             : 
     139             : /* Test normal locks by having several bank accounts and several threads
     140             :    which shuffle around money between the accounts and another thread
     141             :    checking that all the money is still there.  */
     142             : 
     143             : gl_lock_define_initialized(static, my_lock)
     144             : 
     145             : static void *
     146          10 : lock_mutator_thread (void *arg)
     147             : {
     148             :   int repeat;
     149             : 
     150      495030 :   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     151             :     {
     152             :       int i1, i2, value;
     153             : 
     154             :       dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
     155      494481 :       gl_lock_lock (my_lock);
     156             :       dbgprintf ("Mutator %p after  lock\n", gl_thread_self_pointer ());
     157             : 
     158      500000 :       i1 = random_account ();
     159      500000 :       i2 = random_account ();
     160      500000 :       value = ((unsigned int) rand () >> 3) % 10;
     161      500000 :       account[i1] += value;
     162      500000 :       account[i2] -= value;
     163             : 
     164             :       dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
     165      500000 :       gl_lock_unlock (my_lock);
     166             :       dbgprintf ("Mutator %p after  unlock\n", gl_thread_self_pointer ());
     167             : 
     168             :       dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
     169      498429 :       gl_lock_lock (my_lock);
     170      500000 :       check_accounts ();
     171      500000 :       gl_lock_unlock (my_lock);
     172             :       dbgprintf ("Mutator %p after  check unlock\n", gl_thread_self_pointer ());
     173             : 
     174      498477 :       yield ();
     175             :     }
     176             : 
     177             :   dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
     178         549 :   return NULL;
     179             : }
     180             : 
     181             : static struct atomic_int lock_checker_done;
     182             : 
     183             : static void *
     184           1 : lock_checker_thread (void *arg)
     185             : {
     186       91689 :   while (get_atomic_int_value (&lock_checker_done) == 0)
     187             :     {
     188             :       dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
     189       91688 :       gl_lock_lock (my_lock);
     190       91688 :       check_accounts ();
     191       91688 :       gl_lock_unlock (my_lock);
     192             :       dbgprintf ("Checker %p after  check unlock\n", gl_thread_self_pointer ());
     193             : 
     194       91688 :       yield ();
     195             :     }
     196             : 
     197             :   dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
     198           1 :   return NULL;
     199             : }
     200             : 
     201             : static void
     202           1 : test_lock (void)
     203             : {
     204             :   int i;
     205             :   gl_thread_t checkerthread;
     206             :   gl_thread_t threads[THREAD_COUNT];
     207             : 
     208             :   /* Initialization.  */
     209           5 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     210           4 :     account[i] = 1000;
     211           1 :   init_atomic_int (&lock_checker_done);
     212           1 :   set_atomic_int_value (&lock_checker_done, 0);
     213             : 
     214             :   /* Spawn the threads.  */
     215           1 :   checkerthread = gl_thread_create (lock_checker_thread, NULL);
     216          11 :   for (i = 0; i < THREAD_COUNT; i++)
     217          10 :     threads[i] = gl_thread_create (lock_mutator_thread, NULL);
     218             : 
     219             :   /* Wait for the threads to terminate.  */
     220          11 :   for (i = 0; i < THREAD_COUNT; i++)
     221          10 :     gl_thread_join (threads[i], NULL);
     222           1 :   set_atomic_int_value (&lock_checker_done, 1);
     223           1 :   gl_thread_join (checkerthread, NULL);
     224           1 :   check_accounts ();
     225           1 : }
     226             : 
     227             : 
     228             : /* ----------------- Test read-write (non-recursive) locks ----------------- */
     229             : 
     230             : /* Test read-write locks by having several bank accounts and several threads
     231             :    which shuffle around money between the accounts and several other threads
     232             :    that check that all the money is still there.  */
     233             : 
     234             : gl_rwlock_define_initialized(static, my_rwlock)
     235             : 
     236             : static void *
     237          10 : rwlock_mutator_thread (void *arg)
     238             : {
     239             :   int repeat;
     240             : 
     241      495508 :   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     242             :     {
     243             :       int i1, i2, value;
     244             : 
     245             :       dbgprintf ("Mutator %p before wrlock\n", gl_thread_self_pointer ());
     246      494318 :       gl_rwlock_wrlock (my_rwlock);
     247             :       dbgprintf ("Mutator %p after  wrlock\n", gl_thread_self_pointer ());
     248             : 
     249      500000 :       i1 = random_account ();
     250      500000 :       i2 = random_account ();
     251      500000 :       value = ((unsigned int) rand () >> 3) % 10;
     252      500000 :       account[i1] += value;
     253      500000 :       account[i2] -= value;
     254             : 
     255             :       dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
     256      500000 :       gl_rwlock_unlock (my_rwlock);
     257             :       dbgprintf ("Mutator %p after  unlock\n", gl_thread_self_pointer ());
     258             : 
     259      498107 :       yield ();
     260             :     }
     261             : 
     262             :   dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
     263        1190 :   return NULL;
     264             : }
     265             : 
     266             : static struct atomic_int rwlock_checker_done;
     267             : 
     268             : static void *
     269          10 : rwlock_checker_thread (void *arg)
     270             : {
     271      208396 :   while (get_atomic_int_value (&rwlock_checker_done) == 0)
     272             :     {
     273             :       dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
     274      209493 :       gl_rwlock_rdlock (my_rwlock);
     275      217431 :       check_accounts ();
     276      216803 :       gl_rwlock_unlock (my_rwlock);
     277             :       dbgprintf ("Checker %p after  check unlock\n", gl_thread_self_pointer ());
     278             : 
     279      217779 :       yield ();
     280             :     }
     281             : 
     282             :   dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
     283          10 :   return NULL;
     284             : }
     285             : 
     286             : static void
     287           1 : test_rwlock (void)
     288             : {
     289             :   int i;
     290             :   gl_thread_t checkerthreads[THREAD_COUNT];
     291             :   gl_thread_t threads[THREAD_COUNT];
     292             : 
     293             :   /* Initialization.  */
     294           5 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     295           4 :     account[i] = 1000;
     296           1 :   init_atomic_int (&rwlock_checker_done);
     297           1 :   set_atomic_int_value (&rwlock_checker_done, 0);
     298             : 
     299             :   /* Spawn the threads.  */
     300          11 :   for (i = 0; i < THREAD_COUNT; i++)
     301          10 :     checkerthreads[i] = gl_thread_create (rwlock_checker_thread, NULL);
     302          11 :   for (i = 0; i < THREAD_COUNT; i++)
     303          10 :     threads[i] = gl_thread_create (rwlock_mutator_thread, NULL);
     304             : 
     305             :   /* Wait for the threads to terminate.  */
     306          11 :   for (i = 0; i < THREAD_COUNT; i++)
     307          10 :     gl_thread_join (threads[i], NULL);
     308           1 :   set_atomic_int_value (&rwlock_checker_done, 1);
     309          11 :   for (i = 0; i < THREAD_COUNT; i++)
     310          10 :     gl_thread_join (checkerthreads[i], NULL);
     311           1 :   check_accounts ();
     312           1 : }
     313             : 
     314             : 
     315             : /* -------------------------- Test recursive locks -------------------------- */
     316             : 
     317             : /* Test recursive locks by having several bank accounts and several threads
     318             :    which shuffle around money between the accounts (recursively) and another
     319             :    thread checking that all the money is still there.  */
     320             : 
     321             : gl_recursive_lock_define_initialized(static, my_reclock)
     322             : 
     323             : static void
     324      993012 : recshuffle (void)
     325             : {
     326             :   int i1, i2, value;
     327             : 
     328             :   dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
     329      993012 :   gl_recursive_lock_lock (my_reclock);
     330             :   dbgprintf ("Mutator %p after  lock\n", gl_thread_self_pointer ());
     331             : 
     332     1001234 :   i1 = random_account ();
     333     1001234 :   i2 = random_account ();
     334     1001234 :   value = ((unsigned int) rand () >> 3) % 10;
     335     1001234 :   account[i1] += value;
     336     1001234 :   account[i2] -= value;
     337             : 
     338             :   /* Recursive with probability 0.5.  */
     339     1001234 :   if (((unsigned int) rand () >> 3) % 2)
     340      501234 :     recshuffle ();
     341             : 
     342             :   dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
     343     1001234 :   gl_recursive_lock_unlock (my_reclock);
     344             :   dbgprintf ("Mutator %p after  unlock\n", gl_thread_self_pointer ());
     345      997630 : }
     346             : 
     347             : static void *
     348          10 : reclock_mutator_thread (void *arg)
     349             : {
     350             :   int repeat;
     351             : 
     352      495348 :   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     353             :     {
     354      496150 :       recshuffle ();
     355             : 
     356             :       dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
     357      496871 :       gl_recursive_lock_lock (my_reclock);
     358      500000 :       check_accounts ();
     359      500000 :       gl_recursive_lock_unlock (my_reclock);
     360             :       dbgprintf ("Mutator %p after  check unlock\n", gl_thread_self_pointer ());
     361             : 
     362      497482 :       yield ();
     363             :     }
     364             : 
     365             :   dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
     366           0 :   return NULL;
     367             : }
     368             : 
     369             : static struct atomic_int reclock_checker_done;
     370             : 
     371             : static void *
     372           1 : reclock_checker_thread (void *arg)
     373             : {
     374       88467 :   while (get_atomic_int_value (&reclock_checker_done) == 0)
     375             :     {
     376             :       dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
     377       88466 :       gl_recursive_lock_lock (my_reclock);
     378       88466 :       check_accounts ();
     379       88466 :       gl_recursive_lock_unlock (my_reclock);
     380             :       dbgprintf ("Checker %p after  check unlock\n", gl_thread_self_pointer ());
     381             : 
     382       88466 :       yield ();
     383             :     }
     384             : 
     385             :   dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
     386           1 :   return NULL;
     387             : }
     388             : 
     389             : static void
     390           1 : test_recursive_lock (void)
     391             : {
     392             :   int i;
     393             :   gl_thread_t checkerthread;
     394             :   gl_thread_t threads[THREAD_COUNT];
     395             : 
     396             :   /* Initialization.  */
     397           5 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     398           4 :     account[i] = 1000;
     399           1 :   init_atomic_int (&reclock_checker_done);
     400           1 :   set_atomic_int_value (&reclock_checker_done, 0);
     401             : 
     402             :   /* Spawn the threads.  */
     403           1 :   checkerthread = gl_thread_create (reclock_checker_thread, NULL);
     404          11 :   for (i = 0; i < THREAD_COUNT; i++)
     405          10 :     threads[i] = gl_thread_create (reclock_mutator_thread, NULL);
     406             : 
     407             :   /* Wait for the threads to terminate.  */
     408          11 :   for (i = 0; i < THREAD_COUNT; i++)
     409          10 :     gl_thread_join (threads[i], NULL);
     410           1 :   set_atomic_int_value (&reclock_checker_done, 1);
     411           1 :   gl_thread_join (checkerthread, NULL);
     412           1 :   check_accounts ();
     413           1 : }
     414             : 
     415             : 
     416             : /* ------------------------ Test once-only execution ------------------------ */
     417             : 
     418             : /* Test once-only execution by having several threads attempt to grab a
     419             :    once-only task simultaneously (triggered by releasing a read-write lock).  */
     420             : 
     421             : gl_once_define(static, fresh_once)
     422             : static int ready[THREAD_COUNT];
     423             : static gl_lock_t ready_lock[THREAD_COUNT];
     424             : #if ENABLE_LOCKING
     425             : static gl_rwlock_t fire_signal[REPEAT_COUNT];
     426             : #else
     427             : static volatile int fire_signal_state;
     428             : #endif
     429             : static gl_once_t once_control;
     430             : static int performed;
     431             : gl_lock_define_initialized(static, performed_lock)
     432             : 
     433             : static void
     434       50000 : once_execute (void)
     435             : {
     436       50000 :   gl_lock_lock (performed_lock);
     437       50000 :   performed++;
     438       50000 :   gl_lock_unlock (performed_lock);
     439       50000 : }
     440             : 
     441             : static void *
     442          10 : once_contender_thread (void *arg)
     443             : {
     444          10 :   int id = (int) (intptr_t) arg;
     445             :   int repeat;
     446             : 
     447      497250 :   for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
     448             :     {
     449             :       /* Tell the main thread that we're ready.  */
     450      497681 :       gl_lock_lock (ready_lock[id]);
     451      498530 :       ready[id] = 1;
     452      498530 :       gl_lock_unlock (ready_lock[id]);
     453             : 
     454      498299 :       if (repeat == REPEAT_COUNT)
     455          10 :         break;
     456             : 
     457             :       dbgprintf ("Contender %p waiting for signal for round %d\n",
     458             :                  gl_thread_self_pointer (), repeat);
     459             : #if ENABLE_LOCKING
     460             :       /* Wait for the signal to go.  */
     461      498289 :       gl_rwlock_rdlock (fire_signal[repeat]);
     462             :       /* And don't hinder the others (if the scheduler is unfair).  */
     463      499643 :       gl_rwlock_unlock (fire_signal[repeat]);
     464             : #else
     465             :       /* Wait for the signal to go.  */
     466             :       while (fire_signal_state <= repeat)
     467             :         yield ();
     468             : #endif
     469             :       dbgprintf ("Contender %p got the     signal for round %d\n",
     470             :                  gl_thread_self_pointer (), repeat);
     471             : 
     472             :       /* Contend for execution.  */
     473      499549 :       gl_once (once_control, once_execute);
     474             :     }
     475             : 
     476           0 :   return NULL;
     477             : }
     478             : 
     479             : static void
     480           1 : test_once (void)
     481             : {
     482             :   int i, repeat;
     483             :   gl_thread_t threads[THREAD_COUNT];
     484             : 
     485             :   /* Initialize all variables.  */
     486          11 :   for (i = 0; i < THREAD_COUNT; i++)
     487             :     {
     488          10 :       ready[i] = 0;
     489          10 :       gl_lock_init (ready_lock[i]);
     490             :     }
     491             : #if ENABLE_LOCKING
     492       50001 :   for (i = 0; i < REPEAT_COUNT; i++)
     493       50000 :     gl_rwlock_init (fire_signal[i]);
     494             : #else
     495             :   fire_signal_state = 0;
     496             : #endif
     497             : 
     498             : #if ENABLE_LOCKING
     499             :   /* Block all fire_signals.  */
     500       50001 :   for (i = REPEAT_COUNT-1; i >= 0; i--)
     501       50000 :     gl_rwlock_wrlock (fire_signal[i]);
     502             : #endif
     503             : 
     504             :   /* Spawn the threads.  */
     505          11 :   for (i = 0; i < THREAD_COUNT; i++)
     506          10 :     threads[i] =
     507          10 :       gl_thread_create (once_contender_thread, (void *) (intptr_t) i);
     508             : 
     509       50001 :   for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
     510             :     {
     511             :       /* Wait until every thread is ready.  */
     512             :       dbgprintf ("Main thread before synchronizing for round %d\n", repeat);
     513             :       for (;;)
     514      133943 :         {
     515      183944 :           int ready_count = 0;
     516     2023384 :           for (i = 0; i < THREAD_COUNT; i++)
     517             :             {
     518     1839440 :               gl_lock_lock (ready_lock[i]);
     519     1839440 :               ready_count += ready[i];
     520     1839440 :               gl_lock_unlock (ready_lock[i]);
     521             :             }
     522      183944 :           if (ready_count == THREAD_COUNT)
     523       50001 :             break;
     524      133943 :           yield ();
     525             :         }
     526             :       dbgprintf ("Main thread after  synchronizing for round %d\n", repeat);
     527             : 
     528       50001 :       if (repeat > 0)
     529             :         {
     530             :           /* Check that exactly one thread executed the once_execute()
     531             :              function.  */
     532       50000 :           if (performed != 1)
     533           0 :             abort ();
     534             :         }
     535             : 
     536       50001 :       if (repeat == REPEAT_COUNT)
     537           1 :         break;
     538             : 
     539             :       /* Preparation for the next round: Initialize once_control.  */
     540       50000 :       memcpy (&once_control, &fresh_once, sizeof (gl_once_t));
     541             : 
     542             :       /* Preparation for the next round: Reset the performed counter.  */
     543       50000 :       performed = 0;
     544             : 
     545             :       /* Preparation for the next round: Reset the ready flags.  */
     546      550000 :       for (i = 0; i < THREAD_COUNT; i++)
     547             :         {
     548      500000 :           gl_lock_lock (ready_lock[i]);
     549      500000 :           ready[i] = 0;
     550      500000 :           gl_lock_unlock (ready_lock[i]);
     551             :         }
     552             : 
     553             :       /* Signal all threads simultaneously.  */
     554             :       dbgprintf ("Main thread giving signal for round %d\n", repeat);
     555             : #if ENABLE_LOCKING
     556       50000 :       gl_rwlock_unlock (fire_signal[repeat]);
     557             : #else
     558             :       fire_signal_state = repeat + 1;
     559             : #endif
     560             :     }
     561             : 
     562             :   /* Wait for the threads to terminate.  */
     563          11 :   for (i = 0; i < THREAD_COUNT; i++)
     564          10 :     gl_thread_join (threads[i], NULL);
     565           1 : }
     566             : 
     567             : 
     568             : /* -------------------------------------------------------------------------- */
     569             : 
     570             : int
     571           1 : main ()
     572             : {
     573             : #if HAVE_DECL_ALARM
     574             :   /* Declare failure if test takes too long, by using default abort
     575             :      caused by SIGALRM.  */
     576           1 :   int alarm_value = 600;
     577           1 :   signal (SIGALRM, SIG_DFL);
     578           1 :   alarm (alarm_value);
     579             : #endif
     580             : 
     581             : #if DO_TEST_LOCK
     582           1 :   printf ("Starting test_lock ..."); fflush (stdout);
     583           1 :   test_lock ();
     584           1 :   printf (" OK\n"); fflush (stdout);
     585             : #endif
     586             : #if DO_TEST_RWLOCK
     587           1 :   printf ("Starting test_rwlock ..."); fflush (stdout);
     588           1 :   test_rwlock ();
     589           1 :   printf (" OK\n"); fflush (stdout);
     590             : #endif
     591             : #if DO_TEST_RECURSIVE_LOCK
     592           1 :   printf ("Starting test_recursive_lock ..."); fflush (stdout);
     593           1 :   test_recursive_lock ();
     594           1 :   printf (" OK\n"); fflush (stdout);
     595             : #endif
     596             : #if DO_TEST_ONCE
     597           1 :   printf ("Starting test_once ..."); fflush (stdout);
     598           1 :   test_once ();
     599           1 :   printf (" OK\n"); fflush (stdout);
     600             : #endif
     601             : 
     602           1 :   return 0;
     603             : }
     604             : 
     605             : #else
     606             : 
     607             : /* No multithreading available.  */
     608             : 
     609             : #include <stdio.h>
     610             : 
     611             : int
     612             : main ()
     613             : {
     614             :   fputs ("Skipping test: multithreading not enabled\n", stderr);
     615             :   return 77;
     616             : }
     617             : 
     618             : #endif

Generated by: LCOV version 1.13