Back to index

glibc  2.9
tst-rwlock6.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the 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; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <pthread.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <sys/time.h>
00026 
00027 
00028 static int kind[] =
00029   {
00030     PTHREAD_RWLOCK_PREFER_READER_NP,
00031     PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
00032     PTHREAD_RWLOCK_PREFER_WRITER_NP,
00033   };
00034 
00035 
00036 static void *
00037 tf (void *arg)
00038 {
00039   pthread_rwlock_t *r = arg;
00040 
00041   /* Timeout: 0.3 secs.  */
00042   struct timeval tv;
00043   (void) gettimeofday (&tv, NULL);
00044 
00045   struct timespec ts;
00046   TIMEVAL_TO_TIMESPEC (&tv, &ts);
00047   ts.tv_nsec += 300000000;
00048   if (ts.tv_nsec >= 1000000000)
00049     {
00050       ts.tv_nsec -= 1000000000;
00051       ++ts.tv_sec;
00052     }
00053 
00054   puts ("child calling timedrdlock");
00055 
00056   int err = pthread_rwlock_timedrdlock (r, &ts);
00057   if (err == 0)
00058     {
00059       puts ("rwlock_timedrdlock returned");
00060       pthread_exit ((void *) 1l);
00061     }
00062 
00063   if (err != ETIMEDOUT)
00064     {
00065       printf ("err = %s (%d), expected %s (%d)\n",
00066              strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT);
00067       pthread_exit ((void *) 1l);
00068     }
00069 
00070   puts ("1st child timedrdlock done");
00071 
00072   struct timeval tv2;
00073   (void) gettimeofday (&tv2, NULL);
00074 
00075   timersub (&tv2, &tv, &tv);
00076 
00077   if (tv.tv_usec < 200000)
00078     {
00079       puts ("timeout too short");
00080       pthread_exit ((void *) 1l);
00081     }
00082 
00083   (void) gettimeofday (&tv, NULL);
00084   TIMEVAL_TO_TIMESPEC (&tv, &ts);
00085   ts.tv_sec += 10;
00086   /* Note that the following operation makes ts invalid.  */
00087   ts.tv_nsec += 1000000000;
00088 
00089   err = pthread_rwlock_timedrdlock (r, &ts);
00090   if (err == 0)
00091     {
00092       puts ("2nd timedrdlock succeeded");
00093       pthread_exit ((void *) 1l);
00094     }
00095   if (err != EINVAL)
00096     {
00097       puts ("2nd timedrdlock did not return EINVAL");
00098       pthread_exit ((void *) 1l);
00099     }
00100 
00101   puts ("2nd child timedrdlock done");
00102 
00103   return NULL;
00104 }
00105 
00106 
00107 static int
00108 do_test (void)
00109 {
00110   size_t cnt;
00111   for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
00112     {
00113       pthread_rwlock_t r;
00114       pthread_rwlockattr_t a;
00115 
00116       if (pthread_rwlockattr_init (&a) != 0)
00117        {
00118          printf ("round %Zu: rwlockattr_t failed\n", cnt);
00119          exit (1);
00120        }
00121 
00122       if (pthread_rwlockattr_setkind_np (&a, kind[cnt]) != 0)
00123        {
00124          printf ("round %Zu: rwlockattr_setkind failed\n", cnt);
00125          exit (1);
00126        }
00127 
00128       if (pthread_rwlock_init (&r, &a) != 0)
00129        {
00130          printf ("round %Zu: rwlock_init failed\n", cnt);
00131          exit (1);
00132        }
00133 
00134       if (pthread_rwlockattr_destroy (&a) != 0)
00135        {
00136          printf ("round %Zu: rwlockattr_destroy failed\n", cnt);
00137          exit (1);
00138        }
00139 
00140       struct timeval tv;
00141       (void) gettimeofday (&tv, NULL);
00142 
00143       struct timespec ts;
00144       TIMEVAL_TO_TIMESPEC (&tv, &ts);
00145 
00146       ++ts.tv_sec;
00147 
00148       /* Get a write lock.  */
00149       int e = pthread_rwlock_timedwrlock (&r, &ts);
00150       if (e != 0)
00151        {
00152          printf ("round %Zu: rwlock_timedwrlock failed (%d)\n", cnt, e);
00153          exit (1);
00154        }
00155 
00156       puts ("1st timedwrlock done");
00157 
00158       (void) gettimeofday (&tv, NULL);
00159       TIMEVAL_TO_TIMESPEC (&tv, &ts);
00160       ++ts.tv_sec;
00161       e = pthread_rwlock_timedrdlock (&r, &ts);
00162       if (e == 0)
00163        {
00164          puts ("timedrdlock succeeded");
00165          exit (1);
00166        }
00167       if (e != EDEADLK)
00168        {
00169          puts ("timedrdlock did not return EDEADLK");
00170          exit (1);
00171        }
00172 
00173       puts ("1st timedrdlock done");
00174 
00175       (void) gettimeofday (&tv, NULL);
00176       TIMEVAL_TO_TIMESPEC (&tv, &ts);
00177       ++ts.tv_sec;
00178       e = pthread_rwlock_timedwrlock (&r, &ts);
00179       if (e == 0)
00180        {
00181          puts ("2nd timedwrlock succeeded");
00182          exit (1);
00183        }
00184       if (e != EDEADLK)
00185        {
00186          puts ("2nd timedwrlock did not return EDEADLK");
00187          exit (1);
00188        }
00189 
00190       puts ("2nd timedwrlock done");
00191 
00192       pthread_t th;
00193       if (pthread_create (&th, NULL, tf, &r) != 0)
00194        {
00195          printf ("round %Zu: create failed\n", cnt);
00196          exit (1);
00197        }
00198 
00199       puts ("started thread");
00200 
00201       void *status;
00202       if (pthread_join (th, &status) != 0)
00203        {
00204          printf ("round %Zu: join failed\n", cnt);
00205          exit (1);
00206        }
00207       if (status != NULL)
00208        {
00209          printf ("failure in round %Zu\n", cnt);
00210          exit (1);
00211        }
00212 
00213       puts ("joined thread");
00214 
00215       if (pthread_rwlock_destroy (&r) != 0)
00216        {
00217          printf ("round %Zu: rwlock_destroy failed\n", cnt);
00218          exit (1);
00219        }
00220     }
00221 
00222   return 0;
00223 }
00224 
00225 #define TEST_FUNCTION do_test ()
00226 #include "../test-skeleton.c"