LCOV - GNU Libidn - lib/gltests/test-lock.c

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

AltStyle によって変換されたページ (->オリジナル) /