Back to index

glibc  2.9
tst-mutex5.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004, 2006 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 <stdio.h>
00023 #include <time.h>
00024 #include <unistd.h>
00025 #include <sys/time.h>
00026 
00027 
00028 #ifndef TYPE
00029 # define TYPE PTHREAD_MUTEX_NORMAL
00030 #endif
00031 
00032 
00033 static int
00034 do_test (void)
00035 {
00036   pthread_mutex_t m;
00037   struct timespec ts;
00038   struct timeval tv;
00039   struct timeval tv2;
00040   int err;
00041   pthread_mutexattr_t a;
00042 
00043   if (pthread_mutexattr_init (&a) != 0)
00044     {
00045       puts ("mutexattr_init failed");
00046       return 1;
00047     }
00048 
00049   if (pthread_mutexattr_settype (&a, TYPE) != 0)
00050     {
00051       puts ("mutexattr_settype failed");
00052       return 1;
00053     }
00054 
00055 #ifdef ENABLE_PI
00056   if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
00057     {
00058       puts ("pthread_mutexattr_setprotocol failed");
00059       return 1;
00060     }
00061 #endif
00062 
00063   err = pthread_mutex_init (&m, &a);
00064   if (err != 0)
00065     {
00066 #ifdef ENABLE_PI
00067       if (err == ENOTSUP)
00068        {
00069          puts ("PI mutexes unsupported");
00070          return 0;
00071        }
00072 #endif
00073       puts ("mutex_init failed");
00074       return 1;
00075     }
00076 
00077   if (pthread_mutexattr_destroy (&a) != 0)
00078     {
00079       puts ("mutexattr_destroy failed");
00080       return 1;
00081     }
00082 
00083   if (pthread_mutex_lock (&m) != 0)
00084     {
00085       puts ("mutex_lock failed");
00086       return 1;
00087     }
00088 
00089   if (pthread_mutex_trylock (&m) == 0)
00090     {
00091       puts ("mutex_trylock succeeded");
00092       return 1;
00093     }
00094 
00095   gettimeofday (&tv, NULL);
00096   TIMEVAL_TO_TIMESPEC (&tv, &ts);
00097 
00098   ts.tv_sec += 2;    /* Wait 2 seconds.  */
00099 
00100   err = pthread_mutex_timedlock (&m, &ts);
00101   if (err == 0)
00102     {
00103       puts ("timedlock succeeded");
00104       return 1;
00105     }
00106   else if (err != ETIMEDOUT)
00107     {
00108       printf ("timedlock error != ETIMEDOUT: %d\n", err);
00109       return 1;
00110     }
00111   else
00112     {
00113       int clk_tck = sysconf (_SC_CLK_TCK);
00114 
00115       gettimeofday (&tv2, NULL);
00116 
00117       tv2.tv_sec -= tv.tv_sec;
00118       tv2.tv_usec -= tv.tv_usec;
00119       if (tv2.tv_usec < 0)
00120        {
00121          tv2.tv_usec += 1000000;
00122          tv2.tv_sec -= 1;
00123        }
00124 
00125       /* Be a bit tolerant, add one CLK_TCK.  */
00126       tv2.tv_usec += 1000000 / clk_tck;
00127       if (tv2.tv_usec >= 1000000)
00128        {
00129          tv2.tv_usec -= 1000000;
00130          ++tv2.tv_sec;
00131        }
00132 
00133       if (tv2.tv_sec < 2)
00134        {
00135          printf ("premature timeout: %ld.%06ld difference\n",
00136                 tv2.tv_sec, tv2.tv_usec);
00137          return 1;
00138        }
00139     }
00140 
00141   (void) gettimeofday (&tv, NULL);
00142   TIMEVAL_TO_TIMESPEC (&tv, &ts);
00143 
00144   ts.tv_sec += 2;    /* Wait 2 seconds.  */
00145   /* The following makes the ts value invalid.  */
00146   ts.tv_nsec += 1000000000;
00147 
00148   err = pthread_mutex_timedlock (&m, &ts);
00149   if (err == 0)
00150     {
00151       puts ("2nd timedlock succeeded");
00152       return 1;
00153     }
00154   else if (err != EINVAL)
00155     {
00156       printf ("2nd timedlock error != EINVAL: %d\n", err);
00157       return 1;
00158     }
00159 
00160   if (pthread_mutex_unlock (&m) != 0)
00161     {
00162       puts ("mutex_unlock failed");
00163       return 1;
00164     }
00165 
00166   (void) gettimeofday (&tv, NULL);
00167   TIMEVAL_TO_TIMESPEC (&tv, &ts);
00168 
00169   ts.tv_sec += 2;    /* Wait 2 seconds.  */
00170   if (pthread_mutex_timedlock (&m, &ts) != 0)
00171     {
00172       puts ("3rd timedlock failed");
00173     }
00174 
00175   (void) gettimeofday (&tv2, NULL);
00176 
00177   /* Check that timedlock didn't delay.  We use a limit of 0.1 secs.  */
00178   timersub (&tv2, &tv, &tv2);
00179   if (tv2.tv_sec > 0 || tv2.tv_usec > 100000)
00180     {
00181       puts ("3rd timedlock didn't return right away");
00182       return 1;
00183     }
00184 
00185   if (pthread_mutex_unlock (&m) != 0)
00186     {
00187       puts ("final mutex_unlock failed");
00188       return 1;
00189     }
00190 
00191   if (pthread_mutex_destroy (&m) != 0)
00192     {
00193       puts ("mutex_destroy failed");
00194       return 1;
00195     }
00196 
00197   return 0;
00198 }
00199 
00200 #define TIMEOUT 4
00201 #define TEST_FUNCTION do_test ()
00202 #include "../test-skeleton.c"