(root)/
glibc-2.38/
nptl/
tst-rwlock19.c
       1  /* Test rdlock overflow.
       2     Copyright (C) 2000-2023 Free Software Foundation, Inc.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation; either version 2.1 of the
       7     License, or (at your option) any later version.
       8  
       9     The GNU C Library 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 GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; see the file COPYING.LIB.  If
      16     not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <error.h>
      20  #include <pthread.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <time.h>
      24  #include <unistd.h>
      25  #include <pthreadP.h>
      26  
      27  
      28  #define NREADERS 15
      29  #define READTRIES 5000
      30  
      31  #define DELAY   1000000
      32  
      33  static pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
      34  static int eagain_returned = 0;
      35  static int success_returned = 0;
      36  
      37  static void *
      38  reader_thread (void *nr)
      39  {
      40    struct timespec delay;
      41    int n;
      42  
      43    delay.tv_sec = 0;
      44    delay.tv_nsec = DELAY;
      45  
      46    for (n = 0; n < READTRIES; ++n)
      47      {
      48        int err = pthread_rwlock_rdlock (&lock);
      49        if (err == EAGAIN)
      50  	{
      51  	  atomic_store_relaxed (&eagain_returned, 1);
      52  	  continue;
      53  	}
      54        else if (err == 0)
      55  	atomic_store_relaxed (&success_returned, 1);
      56        else
      57  	{
      58  	  puts ("rdlock failed");
      59  	  exit (1);
      60  	}
      61  
      62        nanosleep (&delay, NULL);
      63  
      64        if (pthread_rwlock_unlock (&lock) != 0)
      65  	{
      66  	  puts ("unlock for reader failed");
      67  	  exit (1);
      68  	}
      69      }
      70  
      71    return NULL;
      72  }
      73  
      74  
      75  static int
      76  do_test (void)
      77  {
      78    pthread_t thrd[NREADERS];
      79    int n;
      80    void *res;
      81  
      82    /* Set the rwlock so that it's close to a reader overflow.
      83       PTHREAD_RWLOCK_WRPHASE and PTHREAD_RWLOCK_WRLOCK are zero initially.  */
      84    unsigned int readers = PTHREAD_RWLOCK_READER_OVERFLOW
      85        - ((NREADERS / 3) << PTHREAD_RWLOCK_READER_SHIFT);
      86    lock.__data.__readers = readers;
      87  
      88    for (n = 0; n < NREADERS; ++n)
      89      if (pthread_create (&thrd[n], NULL, reader_thread,
      90  			(void *) (long int) n) != 0)
      91        {
      92  	puts ("reader create failed");
      93  	exit (1);
      94        }
      95  
      96    /* Wait for all the threads.  */
      97    for (n = 0; n < NREADERS; ++n)
      98      if (pthread_join (thrd[n], &res) != 0)
      99        {
     100  	puts ("reader join failed");
     101  	exit (1);
     102        }
     103  
     104    if (atomic_load_relaxed (&eagain_returned) == 0)
     105      {
     106        puts ("EAGAIN has never been returned");
     107        exit (1);
     108      }
     109  
     110    if (atomic_load_relaxed (&success_returned) == 0)
     111      {
     112        puts ("rdlock was never successfully acquired");
     113        exit (1);
     114      }
     115  
     116    if (lock.__data.__readers != readers)
     117      {
     118        puts ("__readers in rwlock differs from initial value");
     119        exit (1);
     120      }
     121  
     122    return 0;
     123  }
     124  
     125  #define TIMEOUT 100
     126  #define TEST_FUNCTION do_test ()
     127  #include "../test-skeleton.c"