LCOV - code coverage report
Current view: top level - lib/gltests - test-lock.c (source / functions) Hit Total Coverage
Test: GNU Libidn Lines: 179 181 98.9 %
Date: 2014-08-10 Functions: 16 16 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 146 217 67.3 %

           Branch data     Line data    Source code
       1                 :            : /* Test of locking in multithreaded situations.
       2                 :            :    Copyright (C) 2005, 2008-2014 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 <http://www.gnu.org/licenses/>.  */
      16                 :            : 
      17                 :            : /* Written by Bruno Haible <bruno@clisp.org>, 2005.  */
      18                 :            : 
      19                 :            : #include <config.h>
      20                 :            : 
      21                 :            : #if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WINDOWS_THREADS
      22                 :            : 
      23                 :            : #if USE_POSIX_THREADS
      24                 :            : # define TEST_POSIX_THREADS 1
      25                 :            : #endif
      26                 :            : #if USE_SOLARIS_THREADS
      27                 :            : # define TEST_SOLARIS_THREADS 1
      28                 :            : #endif
      29                 :            : #if USE_PTH_THREADS
      30                 :            : # define TEST_PTH_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 <stdio.h>
      65                 :            : #include <stdlib.h>
      66                 :            : #include <string.h>
      67                 :            : 
      68                 :            : #if !ENABLE_LOCKING
      69                 :            : # undef USE_POSIX_THREADS
      70                 :            : # undef USE_SOLARIS_THREADS
      71                 :            : # undef USE_PTH_THREADS
      72                 :            : # undef USE_WINDOWS_THREADS
      73                 :            : #endif
      74                 :            : #include "glthread/lock.h"
      75                 :            : 
      76                 :            : #if !ENABLE_LOCKING
      77                 :            : # if TEST_POSIX_THREADS
      78                 :            : #  define USE_POSIX_THREADS 1
      79                 :            : # endif
      80                 :            : # if TEST_SOLARIS_THREADS
      81                 :            : #  define USE_SOLARIS_THREADS 1
      82                 :            : # endif
      83                 :            : # if TEST_PTH_THREADS
      84                 :            : #  define USE_PTH_THREADS 1
      85                 :            : # endif
      86                 :            : # if TEST_WINDOWS_THREADS
      87                 :            : #  define USE_WINDOWS_THREADS 1
      88                 :            : # endif
      89                 :            : #endif
      90                 :            : 
      91                 :            : #include "glthread/thread.h"
      92                 :            : #include "glthread/yield.h"
      93                 :            : 
      94                 :            : #if ENABLE_DEBUGGING
      95                 :            : # define dbgprintf printf
      96                 :            : #else
      97                 :            : # define dbgprintf if (0) printf
      98                 :            : #endif
      99                 :            : 
     100                 :            : #if EXPLICIT_YIELD
     101                 :            : # define yield() gl_thread_yield ()
     102                 :            : #else
     103                 :            : # define yield()
     104                 :            : #endif
     105                 :            : 
     106                 :            : #define ACCOUNT_COUNT 4
     107                 :            : 
     108                 :            : static int account[ACCOUNT_COUNT];
     109                 :            : 
     110                 :            : static int
     111                 :    4002468 : random_account (void)
     112                 :            : {
     113                 :    4002468 :   return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
     114                 :            : }
     115                 :            : 
     116                 :            : static void
     117                 :    1870011 : check_accounts (void)
     118                 :            : {
     119                 :            :   int i, sum;
     120                 :            : 
     121                 :    1870011 :   sum = 0;
     122         [ +  + ]:    9336096 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     123                 :    7466085 :     sum += account[i];
     124         [ -  + ]:    1870011 :   if (sum != ACCOUNT_COUNT * 1000)
     125                 :          0 :     abort ();
     126                 :    1870011 : }
     127                 :            : 
     128                 :            : 
     129                 :            : /* ------------------- Test normal (non-recursive) locks ------------------- */
     130                 :            : 
     131                 :            : /* Test normal locks by having several bank accounts and several threads
     132                 :            :    which shuffle around money between the accounts and another thread
     133                 :            :    checking that all the money is still there.  */
     134                 :            : 
     135                 :            : gl_lock_define_initialized(static, my_lock)
     136                 :            : 
     137                 :            : static void *
     138                 :       4529 : lock_mutator_thread (void *arg)
     139                 :            : {
     140                 :            :   int repeat;
     141                 :            : 
     142         [ +  + ]:     492893 :   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     143                 :            :     {
     144                 :            :       int i1, i2, value;
     145                 :            : 
     146                 :            :       dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
     147 [ +  + ][ -  + ]:     492883 :       gl_lock_lock (my_lock);
     148                 :            :       dbgprintf ("Mutator %p after  lock\n", gl_thread_self_pointer ());
     149                 :            : 
     150                 :     502483 :       i1 = random_account ();
     151                 :     500000 :       i2 = random_account ();
     152                 :     500000 :       value = ((unsigned int) rand () >> 3) % 10;
     153                 :     500000 :       account[i1] += value;
     154                 :     500000 :       account[i2] -= value;
     155                 :            : 
     156                 :            :       dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
     157 [ +  - ][ -  + ]:     500000 :       gl_lock_unlock (my_lock);
     158                 :            :       dbgprintf ("Mutator %p after  unlock\n", gl_thread_self_pointer ());
     159                 :            : 
     160                 :            :       dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
     161    [ + ][ -  + ]:     498398 :       gl_lock_lock (my_lock);
     162                 :     499663 :       check_accounts ();
     163 [ +  - ][ -  + ]:     500000 :       gl_lock_unlock (my_lock);
     164                 :            :       dbgprintf ("Mutator %p after  check unlock\n", gl_thread_self_pointer ());
     165                 :            : 
     166                 :     495438 :       yield ();
     167                 :            :     }
     168                 :            : 
     169                 :            :   dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
     170                 :         10 :   return NULL;
     171                 :            : }
     172                 :            : 
     173                 :            : static volatile int lock_checker_done;
     174                 :            : 
     175                 :            : static void *
     176                 :          1 : lock_checker_thread (void *arg)
     177                 :            : {
     178         [ +  + ]:      80542 :   while (!lock_checker_done)
     179                 :            :     {
     180                 :            :       dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
     181 [ +  - ][ -  + ]:      80541 :       gl_lock_lock (my_lock);
     182                 :      80541 :       check_accounts ();
     183 [ +  - ][ -  + ]:      80541 :       gl_lock_unlock (my_lock);
     184                 :            :       dbgprintf ("Checker %p after  check unlock\n", gl_thread_self_pointer ());
     185                 :            : 
     186                 :      80541 :       yield ();
     187                 :            :     }
     188                 :            : 
     189                 :            :   dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
     190                 :          1 :   return NULL;
     191                 :            : }
     192                 :            : 
     193                 :            : static void
     194                 :          1 : test_lock (void)
     195                 :            : {
     196                 :            :   int i;
     197                 :            :   gl_thread_t checkerthread;
     198                 :            :   gl_thread_t threads[THREAD_COUNT];
     199                 :            : 
     200                 :            :   /* Initialization.  */
     201         [ +  + ]:          5 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     202                 :          4 :     account[i] = 1000;
     203                 :          1 :   lock_checker_done = 0;
     204                 :            : 
     205                 :            :   /* Spawn the threads.  */
     206                 :          1 :   checkerthread = gl_thread_create (lock_checker_thread, NULL);
     207         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     208                 :         10 :     threads[i] = gl_thread_create (lock_mutator_thread, NULL);
     209                 :            : 
     210                 :            :   /* Wait for the threads to terminate.  */
     211         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     212 [ +  - ][ -  + ]:         10 :     gl_thread_join (threads[i], NULL);
     213                 :          1 :   lock_checker_done = 1;
     214 [ +  - ][ -  + ]:          1 :   gl_thread_join (checkerthread, NULL);
     215                 :          1 :   check_accounts ();
     216                 :          1 : }
     217                 :            : 
     218                 :            : 
     219                 :            : /* ----------------- Test read-write (non-recursive) locks ----------------- */
     220                 :            : 
     221                 :            : /* Test read-write locks by having several bank accounts and several threads
     222                 :            :    which shuffle around money between the accounts and several other threads
     223                 :            :    that check that all the money is still there.  */
     224                 :            : 
     225                 :            : gl_rwlock_define_initialized(static, my_rwlock)
     226                 :            : 
     227                 :            : static void *
     228                 :       3678 : rwlock_mutator_thread (void *arg)
     229                 :            : {
     230                 :            :   int repeat;
     231                 :            : 
     232         [ +  + ]:     492556 :   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     233                 :            :     {
     234                 :            :       int i1, i2, value;
     235                 :            : 
     236                 :            :       dbgprintf ("Mutator %p before wrlock\n", gl_thread_self_pointer ());
     237 [ +  + ][ -  + ]:     492546 :       gl_rwlock_wrlock (my_rwlock);
     238                 :            :       dbgprintf ("Mutator %p after  wrlock\n", gl_thread_self_pointer ());
     239                 :            : 
     240                 :     500805 :       i1 = random_account ();
     241                 :     500000 :       i2 = random_account ();
     242                 :     500000 :       value = ((unsigned int) rand () >> 3) % 10;
     243                 :     500000 :       account[i1] += value;
     244                 :     500000 :       account[i2] -= value;
     245                 :            : 
     246                 :            :       dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
     247 [ +  - ][ -  + ]:     500000 :       gl_rwlock_unlock (my_rwlock);
     248                 :            :       dbgprintf ("Mutator %p after  unlock\n", gl_thread_self_pointer ());
     249                 :            : 
     250                 :     494823 :       yield ();
     251                 :            :     }
     252                 :            : 
     253                 :            :   dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
     254                 :         10 :   return NULL;
     255                 :            : }
     256                 :            : 
     257                 :            : static volatile int rwlock_checker_done;
     258                 :            : 
     259                 :            : static void *
     260                 :         10 : rwlock_checker_thread (void *arg)
     261                 :            : {
     262         [ +  + ]:     669850 :   while (!rwlock_checker_done)
     263                 :            :     {
     264                 :            :       dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
     265 [ +  + ][ -  + ]:     669840 :       gl_rwlock_rdlock (my_rwlock);
     266                 :     695513 :       check_accounts ();
     267    [ + ][ -  + ]:     693255 :       gl_rwlock_unlock (my_rwlock);
     268                 :            :       dbgprintf ("Checker %p after  check unlock\n", gl_thread_self_pointer ());
     269                 :            : 
     270                 :     686835 :       yield ();
     271                 :            :     }
     272                 :            : 
     273                 :            :   dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
     274                 :         10 :   return NULL;
     275                 :            : }
     276                 :            : 
     277                 :            : static void
     278                 :          1 : test_rwlock (void)
     279                 :            : {
     280                 :            :   int i;
     281                 :            :   gl_thread_t checkerthreads[THREAD_COUNT];
     282                 :            :   gl_thread_t threads[THREAD_COUNT];
     283                 :            : 
     284                 :            :   /* Initialization.  */
     285         [ +  + ]:          5 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     286                 :          4 :     account[i] = 1000;
     287                 :          1 :   rwlock_checker_done = 0;
     288                 :            : 
     289                 :            :   /* Spawn the threads.  */
     290         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     291                 :         10 :     checkerthreads[i] = gl_thread_create (rwlock_checker_thread, NULL);
     292         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     293                 :         10 :     threads[i] = gl_thread_create (rwlock_mutator_thread, NULL);
     294                 :            : 
     295                 :            :   /* Wait for the threads to terminate.  */
     296         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     297 [ +  - ][ -  + ]:         10 :     gl_thread_join (threads[i], NULL);
     298                 :          1 :   rwlock_checker_done = 1;
     299         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     300 [ +  - ][ -  + ]:         10 :     gl_thread_join (checkerthreads[i], NULL);
     301                 :          1 :   check_accounts ();
     302                 :          1 : }
     303                 :            : 
     304                 :            : 
     305                 :            : /* -------------------------- Test recursive locks -------------------------- */
     306                 :            : 
     307                 :            : /* Test recursive locks by having several bank accounts and several threads
     308                 :            :    which shuffle around money between the accounts (recursively) and another
     309                 :            :    thread checking that all the money is still there.  */
     310                 :            : 
     311                 :            : gl_recursive_lock_define_initialized(static, my_reclock)
     312                 :            : 
     313                 :            : static void
     314                 :     989588 : recshuffle (void)
     315                 :            : {
     316                 :            :   int i1, i2, value;
     317                 :            : 
     318                 :            :   dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
     319    [ + ][ -  + ]:     989588 :   gl_recursive_lock_lock (my_reclock);
     320                 :            :   dbgprintf ("Mutator %p after  lock\n", gl_thread_self_pointer ());
     321                 :            : 
     322                 :     999057 :   i1 = random_account ();
     323                 :    1001234 :   i2 = random_account ();
     324                 :    1001234 :   value = ((unsigned int) rand () >> 3) % 10;
     325                 :    1001234 :   account[i1] += value;
     326                 :    1001234 :   account[i2] -= value;
     327                 :            : 
     328                 :            :   /* Recursive with probability 0.5.  */
     329         [ +  + ]:    1001234 :   if (((unsigned int) rand () >> 3) % 2)
     330                 :     501234 :     recshuffle ();
     331                 :            : 
     332                 :            :   dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
     333 [ +  - ][ -  + ]:    1001234 :   gl_recursive_lock_unlock (my_reclock);
     334                 :            :   dbgprintf ("Mutator %p after  unlock\n", gl_thread_self_pointer ());
     335                 :     997091 : }
     336                 :            : 
     337                 :            : static void *
     338                 :       3211 : reclock_mutator_thread (void *arg)
     339                 :            : {
     340                 :            :   int repeat;
     341                 :            : 
     342         [ +  + ]:     495810 :   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     343                 :            :     {
     344                 :     495800 :       recshuffle ();
     345                 :            : 
     346                 :            :       dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
     347    [ + ][ -  + ]:     492706 :       gl_recursive_lock_lock (my_reclock);
     348                 :     495779 :       check_accounts ();
     349 [ +  - ][ -  + ]:     500000 :       gl_recursive_lock_unlock (my_reclock);
     350                 :            :       dbgprintf ("Mutator %p after  check unlock\n", gl_thread_self_pointer ());
     351                 :            : 
     352                 :     492777 :       yield ();
     353                 :            :     }
     354                 :            : 
     355                 :            :   dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
     356                 :         10 :   return NULL;
     357                 :            : }
     358                 :            : 
     359                 :            : static volatile int reclock_checker_done;
     360                 :            : 
     361                 :            : static void *
     362                 :          1 : reclock_checker_thread (void *arg)
     363                 :            : {
     364         [ +  + ]:      94460 :   while (!reclock_checker_done)
     365                 :            :     {
     366                 :            :       dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
     367 [ +  - ][ -  + ]:      94459 :       gl_recursive_lock_lock (my_reclock);
     368                 :      94459 :       check_accounts ();
     369 [ +  - ][ -  + ]:      94459 :       gl_recursive_lock_unlock (my_reclock);
     370                 :            :       dbgprintf ("Checker %p after  check unlock\n", gl_thread_self_pointer ());
     371                 :            : 
     372                 :      94459 :       yield ();
     373                 :            :     }
     374                 :            : 
     375                 :            :   dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
     376                 :          1 :   return NULL;
     377                 :            : }
     378                 :            : 
     379                 :            : static void
     380                 :          1 : test_recursive_lock (void)
     381                 :            : {
     382                 :            :   int i;
     383                 :            :   gl_thread_t checkerthread;
     384                 :            :   gl_thread_t threads[THREAD_COUNT];
     385                 :            : 
     386                 :            :   /* Initialization.  */
     387         [ +  + ]:          5 :   for (i = 0; i < ACCOUNT_COUNT; i++)
     388                 :          4 :     account[i] = 1000;
     389                 :          1 :   reclock_checker_done = 0;
     390                 :            : 
     391                 :            :   /* Spawn the threads.  */
     392                 :          1 :   checkerthread = gl_thread_create (reclock_checker_thread, NULL);
     393         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     394                 :         10 :     threads[i] = gl_thread_create (reclock_mutator_thread, NULL);
     395                 :            : 
     396                 :            :   /* Wait for the threads to terminate.  */
     397         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     398 [ +  - ][ -  + ]:         10 :     gl_thread_join (threads[i], NULL);
     399                 :          1 :   reclock_checker_done = 1;
     400 [ +  - ][ -  + ]:          1 :   gl_thread_join (checkerthread, NULL);
     401                 :          1 :   check_accounts ();
     402                 :          1 : }
     403                 :            : 
     404                 :            : 
     405                 :            : /* ------------------------ Test once-only execution ------------------------ */
     406                 :            : 
     407                 :            : /* Test once-only execution by having several threads attempt to grab a
     408                 :            :    once-only task simultaneously (triggered by releasing a read-write lock).  */
     409                 :            : 
     410                 :            : gl_once_define(static, fresh_once)
     411                 :            : static int ready[THREAD_COUNT];
     412                 :            : static gl_lock_t ready_lock[THREAD_COUNT];
     413                 :            : #if ENABLE_LOCKING
     414                 :            : static gl_rwlock_t fire_signal[REPEAT_COUNT];
     415                 :            : #else
     416                 :            : static volatile int fire_signal_state;
     417                 :            : #endif
     418                 :            : static gl_once_t once_control;
     419                 :            : static int performed;
     420                 :            : gl_lock_define_initialized(static, performed_lock)
     421                 :            : 
     422                 :            : static void
     423                 :      50000 : once_execute (void)
     424                 :            : {
     425 [ +  - ][ -  + ]:      50000 :   gl_lock_lock (performed_lock);
     426                 :      50000 :   performed++;
     427 [ +  - ][ -  + ]:      50000 :   gl_lock_unlock (performed_lock);
     428                 :      50000 : }
     429                 :            : 
     430                 :            : static void *
     431                 :       4606 : once_contender_thread (void *arg)
     432                 :            : {
     433                 :       4606 :   int id = (int) (long) arg;
     434                 :            :   int repeat;
     435                 :            : 
     436         [ +  - ]:     492102 :   for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
     437                 :            :     {
     438                 :            :       /* Tell the main thread that we're ready.  */
     439    [ + ][ -  + ]:     492102 :       gl_lock_lock (ready_lock[id]);
     440                 :     488925 :       ready[id] = 1;
     441 [ +  + ][ -  + ]:     488925 :       gl_lock_unlock (ready_lock[id]);
     442                 :            : 
     443         [ +  + ]:     498240 :       if (repeat == REPEAT_COUNT)
     444                 :         10 :         break;
     445                 :            : 
     446                 :            :       dbgprintf ("Contender %p waiting for signal for round %d\n",
     447                 :            :                  gl_thread_self_pointer (), repeat);
     448                 :            : #if ENABLE_LOCKING
     449                 :            :       /* Wait for the signal to go.  */
     450 [ +  + ][ -  + ]:     498230 :       gl_rwlock_rdlock (fire_signal[repeat]);
     451                 :            :       /* And don't hinder the others (if the scheduler is unfair).  */
     452 [ +  + ][ -  + ]:     499086 :       gl_rwlock_unlock (fire_signal[repeat]);
     453                 :            : #else
     454                 :            :       /* Wait for the signal to go.  */
     455                 :            :       while (fire_signal_state <= repeat)
     456                 :            :         yield ();
     457                 :            : #endif
     458                 :            :       dbgprintf ("Contender %p got the     signal for round %d\n",
     459                 :            :                  gl_thread_self_pointer (), repeat);
     460                 :            : 
     461                 :            :       /* Contend for execution.  */
     462 [ +  - ][ #  # ]:     496834 :       gl_once (once_control, once_execute);
                 [ -  + ]
     463                 :            :     }
     464                 :            : 
     465                 :         10 :   return NULL;
     466                 :            : }
     467                 :            : 
     468                 :            : static void
     469                 :          1 : test_once (void)
     470                 :            : {
     471                 :            :   int i, repeat;
     472                 :            :   gl_thread_t threads[THREAD_COUNT];
     473                 :            : 
     474                 :            :   /* Initialize all variables.  */
     475         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     476                 :            :     {
     477                 :         10 :       ready[i] = 0;
     478 [ +  - ][ -  + ]:         10 :       gl_lock_init (ready_lock[i]);
     479                 :            :     }
     480                 :            : #if ENABLE_LOCKING
     481         [ +  + ]:      50001 :   for (i = 0; i < REPEAT_COUNT; i++)
     482 [ +  - ][ -  + ]:      50000 :     gl_rwlock_init (fire_signal[i]);
     483                 :            : #else
     484                 :            :   fire_signal_state = 0;
     485                 :            : #endif
     486                 :            : 
     487                 :            :   /* Block all fire_signals.  */
     488         [ +  + ]:      50001 :   for (i = REPEAT_COUNT-1; i >= 0; i--)
     489 [ +  - ][ -  + ]:      50000 :     gl_rwlock_wrlock (fire_signal[i]);
     490                 :            : 
     491                 :            :   /* Spawn the threads.  */
     492         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     493                 :         10 :     threads[i] = gl_thread_create (once_contender_thread, (void *) (long) i);
     494                 :            : 
     495         [ +  - ]:      50001 :   for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
     496                 :            :     {
     497                 :            :       /* Wait until every thread is ready.  */
     498                 :            :       dbgprintf ("Main thread before synchronizing for round %d\n", repeat);
     499                 :            :       for (;;)
     500                 :            :         {
     501                 :     244302 :           int ready_count = 0;
     502         [ +  + ]:    2687322 :           for (i = 0; i < THREAD_COUNT; i++)
     503                 :            :             {
     504 [ +  - ][ -  + ]:    2443020 :               gl_lock_lock (ready_lock[i]);
     505                 :    2443020 :               ready_count += ready[i];
     506 [ +  - ][ -  + ]:    2443020 :               gl_lock_unlock (ready_lock[i]);
     507                 :            :             }
     508         [ +  + ]:     244302 :           if (ready_count == THREAD_COUNT)
     509                 :      50001 :             break;
     510                 :     194301 :           yield ();
     511                 :     194301 :         }
     512                 :            :       dbgprintf ("Main thread after  synchronizing for round %d\n", repeat);
     513                 :            : 
     514         [ +  + ]:      50001 :       if (repeat > 0)
     515                 :            :         {
     516                 :            :           /* Check that exactly one thread executed the once_execute()
     517                 :            :              function.  */
     518         [ -  + ]:      50000 :           if (performed != 1)
     519                 :          0 :             abort ();
     520                 :            :         }
     521                 :            : 
     522         [ +  + ]:      50001 :       if (repeat == REPEAT_COUNT)
     523                 :          1 :         break;
     524                 :            : 
     525                 :            :       /* Preparation for the next round: Initialize once_control.  */
     526                 :      50000 :       memcpy (&once_control, &fresh_once, sizeof (gl_once_t));
     527                 :            : 
     528                 :            :       /* Preparation for the next round: Reset the performed counter.  */
     529                 :      50000 :       performed = 0;
     530                 :            : 
     531                 :            :       /* Preparation for the next round: Reset the ready flags.  */
     532         [ +  + ]:     550000 :       for (i = 0; i < THREAD_COUNT; i++)
     533                 :            :         {
     534 [ +  - ][ -  + ]:     500000 :           gl_lock_lock (ready_lock[i]);
     535                 :     500000 :           ready[i] = 0;
     536 [ +  - ][ -  + ]:     500000 :           gl_lock_unlock (ready_lock[i]);
     537                 :            :         }
     538                 :            : 
     539                 :            :       /* Signal all threads simultaneously.  */
     540                 :            :       dbgprintf ("Main thread giving signal for round %d\n", repeat);
     541                 :            : #if ENABLE_LOCKING
     542 [ +  - ][ -  + ]:      50000 :       gl_rwlock_unlock (fire_signal[repeat]);
     543                 :            : #else
     544                 :            :       fire_signal_state = repeat + 1;
     545                 :            : #endif
     546                 :            :     }
     547                 :            : 
     548                 :            :   /* Wait for the threads to terminate.  */
     549         [ +  + ]:         11 :   for (i = 0; i < THREAD_COUNT; i++)
     550 [ +  - ][ -  + ]:         10 :     gl_thread_join (threads[i], NULL);
     551                 :          1 : }
     552                 :            : 
     553                 :            : 
     554                 :            : /* -------------------------------------------------------------------------- */
     555                 :            : 
     556                 :            : int
     557                 :          1 : main ()
     558                 :            : {
     559                 :            : #if TEST_PTH_THREADS
     560                 :            :   if (!pth_init ())
     561                 :            :     abort ();
     562                 :            : #endif
     563                 :            : 
     564                 :            : #if DO_TEST_LOCK
     565                 :          1 :   printf ("Starting test_lock ..."); fflush (stdout);
     566                 :          1 :   test_lock ();
     567                 :          1 :   printf (" OK\n"); fflush (stdout);
     568                 :            : #endif
     569                 :            : #if DO_TEST_RWLOCK
     570                 :          1 :   printf ("Starting test_rwlock ..."); fflush (stdout);
     571                 :          1 :   test_rwlock ();
     572                 :          1 :   printf (" OK\n"); fflush (stdout);
     573                 :            : #endif
     574                 :            : #if DO_TEST_RECURSIVE_LOCK
     575                 :          1 :   printf ("Starting test_recursive_lock ..."); fflush (stdout);
     576                 :          1 :   test_recursive_lock ();
     577                 :          1 :   printf (" OK\n"); fflush (stdout);
     578                 :            : #endif
     579                 :            : #if DO_TEST_ONCE
     580                 :          1 :   printf ("Starting test_once ..."); fflush (stdout);
     581                 :          1 :   test_once ();
     582                 :          1 :   printf (" OK\n"); fflush (stdout);
     583                 :            : #endif
     584                 :            : 
     585                 :          1 :   return 0;
     586                 :            : }
     587                 :            : 
     588                 :            : #else
     589                 :            : 
     590                 :            : /* No multithreading available.  */
     591                 :            : 
     592                 :            : #include <stdio.h>
     593                 :            : 
     594                 :            : int
     595                 :            : main ()
     596                 :            : {
     597                 :            :   fputs ("Skipping test: multithreading not enabled\n", stderr);
     598                 :            :   return 77;
     599                 :            : }
     600                 :            : 
     601                 :            : #endif

Generated by: LCOV version 1.9