Back to index

glibc  2.9
tst-rwlock9.c
Go to the documentation of this file.
00001 /* Test program for timedout read/write lock functions.
00002    Copyright (C) 2000, 2003 Free Software Foundation, Inc.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public License as
00007    published by the Free Software Foundation; either version 2.1 of the
00008    License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00017    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.  */
00019 
00020 #include <errno.h>
00021 #include <error.h>
00022 #include <pthread.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <time.h>
00026 #include <unistd.h>
00027 #include <sys/time.h>
00028 
00029 
00030 #define NWRITERS 15
00031 #define WRITETRIES 10
00032 #define NREADERS 15
00033 #define READTRIES 15
00034 
00035 #define TIMEOUT 1000000
00036 #define DELAY   1000000
00037 
00038 #ifndef INIT
00039 # define INIT PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
00040 #endif
00041 
00042 static pthread_rwlock_t lock = INIT;
00043 
00044 
00045 static void *
00046 writer_thread (void *nr)
00047 {
00048   struct timespec ts;
00049   struct timespec delay;
00050   int n;
00051 
00052   delay.tv_sec = 0;
00053   delay.tv_nsec = DELAY;
00054 
00055   for (n = 0; n < WRITETRIES; ++n)
00056     {
00057       int e;
00058       do
00059        {
00060          struct timeval tv;
00061          (void) gettimeofday (&tv, NULL);
00062          TIMEVAL_TO_TIMESPEC (&tv, &ts);
00063 
00064          ts.tv_nsec += 2 * TIMEOUT;
00065          if (ts.tv_nsec >= 1000000000)
00066            {
00067              ts.tv_nsec -= 1000000000;
00068              ++ts.tv_sec;
00069            }
00070 
00071          printf ("writer thread %ld tries again\n", (long int) nr);
00072 
00073          e = pthread_rwlock_timedwrlock (&lock, &ts);
00074          if (e != 0 && e != ETIMEDOUT)
00075            {
00076              puts ("timedwrlock failed");
00077              exit (1);
00078            }
00079        }
00080       while (e == ETIMEDOUT);
00081 
00082       printf ("writer thread %ld succeeded\n", (long int) nr);
00083 
00084       nanosleep (&delay, NULL);
00085 
00086       if (pthread_rwlock_unlock (&lock) != 0)
00087        {
00088          puts ("unlock for writer failed");
00089          exit (1);
00090        }
00091 
00092       printf ("writer thread %ld released\n", (long int) nr);
00093     }
00094 
00095   return NULL;
00096 }
00097 
00098 
00099 static void *
00100 reader_thread (void *nr)
00101 {
00102   struct timespec ts;
00103   struct timespec delay;
00104   int n;
00105 
00106   delay.tv_sec = 0;
00107   delay.tv_nsec = DELAY;
00108 
00109   for (n = 0; n < READTRIES; ++n)
00110     {
00111       int e;
00112       do
00113        {
00114          struct timeval tv;
00115          (void) gettimeofday (&tv, NULL);
00116          TIMEVAL_TO_TIMESPEC (&tv, &ts);
00117 
00118          ts.tv_nsec += TIMEOUT;
00119          if (ts.tv_nsec >= 1000000000)
00120            {
00121              ts.tv_nsec -= 1000000000;
00122              ++ts.tv_sec;
00123            }
00124 
00125          printf ("reader thread %ld tries again\n", (long int) nr);
00126 
00127          e = pthread_rwlock_timedrdlock (&lock, &ts);
00128          if (e != 0 && e != ETIMEDOUT)
00129            {
00130              puts ("timedrdlock failed");
00131              exit (1);
00132            }
00133        }
00134       while (e == ETIMEDOUT);
00135 
00136       printf ("reader thread %ld succeeded\n", (long int) nr);
00137 
00138       nanosleep (&delay, NULL);
00139 
00140       if (pthread_rwlock_unlock (&lock) != 0)
00141        {
00142          puts ("unlock for reader failed");
00143          exit (1);
00144        }
00145 
00146       printf ("reader thread %ld released\n", (long int) nr);
00147     }
00148 
00149   return NULL;
00150 }
00151 
00152 
00153 static int
00154 do_test (void)
00155 {
00156   pthread_t thwr[NWRITERS];
00157   pthread_t thrd[NREADERS];
00158   int n;
00159   void *res;
00160 
00161   /* Make standard error the same as standard output.  */
00162   dup2 (1, 2);
00163 
00164   /* Make sure we see all message, even those on stdout.  */
00165   setvbuf (stdout, NULL, _IONBF, 0);
00166 
00167   for (n = 0; n < NWRITERS; ++n)
00168     if (pthread_create (&thwr[n], NULL, writer_thread,
00169                      (void *) (long int) n) != 0)
00170       {
00171        puts ("writer create failed");
00172        exit (1);
00173       }
00174 
00175   for (n = 0; n < NREADERS; ++n)
00176     if (pthread_create (&thrd[n], NULL, reader_thread,
00177                      (void *) (long int) n) != 0)
00178       {
00179        puts ("reader create failed");
00180        exit (1);
00181       }
00182 
00183   /* Wait for all the threads.  */
00184   for (n = 0; n < NWRITERS; ++n)
00185     if (pthread_join (thwr[n], &res) != 0)
00186       {
00187        puts ("writer join failed");
00188        exit (1);
00189       }
00190   for (n = 0; n < NREADERS; ++n)
00191     if (pthread_join (thrd[n], &res) != 0)
00192       {
00193        puts ("reader join failed");
00194        exit (1);
00195       }
00196 
00197   return 0;
00198 }
00199 
00200 #undef TIMEOUT
00201 #define TIMEOUT 30
00202 #define TEST_FUNCTION do_test ()
00203 #include "../test-skeleton.c"