1 /* Test rwlock with PREFER_WRITER_NONRECURSIVE_NP (bug 23861). 2 Copyright (C) 2018-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <pthread.h> 23 #include <support/xthread.h> 24 25 /* We choose 10 iterations because this happens to be able to trigger the 26 stall on contemporary hardware. */ 27 #define LOOPS 10 28 /* We need 3 threads to trigger bug 23861. One thread as a writer, and 29 two reader threads. The test verifies that the second-to-last reader 30 is able to notify the *last* reader that it should be done waiting. 31 If the second-to-last reader fails to notify the last reader or does 32 so incorrectly then the last reader may stall indefinitely. */ 33 #define NTHREADS 3 34 35 _Atomic int do_exit; 36 pthread_rwlockattr_t mylock_attr; 37 pthread_rwlock_t mylock; 38 39 void * run_loop(void * a)40run_loop (void *a) 41 { 42 while (!do_exit) 43 { 44 if (random () & 1) 45 { 46 xpthread_rwlock_wrlock (&mylock); 47 xpthread_rwlock_unlock (&mylock); 48 } 49 else 50 { 51 xpthread_rwlock_rdlock (&mylock); 52 xpthread_rwlock_unlock (&mylock); 53 } 54 } 55 return NULL; 56 } 57 58 int do_test(void)59do_test (void) 60 { 61 xpthread_rwlockattr_init (&mylock_attr); 62 xpthread_rwlockattr_setkind_np (&mylock_attr, 63 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 64 xpthread_rwlock_init (&mylock, &mylock_attr); 65 66 for (int n = 0; n < LOOPS; n++) 67 { 68 pthread_t tids[NTHREADS]; 69 do_exit = 0; 70 for (int i = 0; i < NTHREADS; i++) 71 tids[i] = xpthread_create (NULL, run_loop, NULL); 72 /* Let the threads run for some time. */ 73 sleep (1); 74 printf ("Exiting..."); 75 fflush (stdout); 76 do_exit = 1; 77 for (int i = 0; i < NTHREADS; i++) 78 xpthread_join (tids[i]); 79 printf ("done.\n"); 80 } 81 pthread_rwlock_destroy (&mylock); 82 pthread_rwlockattr_destroy (&mylock_attr); 83 return 0; 84 } 85 86 #define TIMEOUT (DEFAULT_TIMEOUT + 3 * LOOPS) 87 #include <support/test-driver.c> 88