Back to index

glibc  2.9
tst-mutex9.c
Go to the documentation of this file.
00001 /* Copyright (C) 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>, 2003.
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 <string.h>
00024 #include <unistd.h>
00025 #include <sys/mman.h>
00026 #include <sys/wait.h>
00027 
00028 
00029 static int
00030 do_test (void)
00031 {
00032   size_t ps = sysconf (_SC_PAGESIZE);
00033   char tmpfname[] = "/tmp/tst-mutex9.XXXXXX";
00034   char data[ps];
00035   void *mem;
00036   int fd;
00037   pthread_mutex_t *m;
00038   pthread_mutexattr_t a;
00039   pid_t pid;
00040   char *p;
00041 
00042   fd = mkstemp (tmpfname);
00043   if (fd == -1)
00044     {
00045       printf ("cannot open temporary file: %m\n");
00046       return 1;
00047     }
00048 
00049   /* Make sure it is always removed.  */
00050   unlink (tmpfname);
00051 
00052   /* Create one page of data.  */
00053   memset (data, '\0', ps);
00054 
00055   /* Write the data to the file.  */
00056   if (write (fd, data, ps) != (ssize_t) ps)
00057     {
00058       puts ("short write");
00059       return 1;
00060     }
00061 
00062   mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
00063   if (mem == MAP_FAILED)
00064     {
00065       printf ("mmap failed: %m\n");
00066       return 1;
00067     }
00068 
00069   m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
00070                         & ~(__alignof (pthread_mutex_t) - 1));
00071   p = (char *) (m + 1);
00072 
00073   if (pthread_mutexattr_init (&a) != 0)
00074     {
00075       puts ("mutexattr_init failed");
00076       return 1;
00077     }
00078 
00079   if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
00080     {
00081       puts ("mutexattr_setpshared failed");
00082       return 1;
00083     }
00084 
00085   if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0)
00086     {
00087       puts ("mutexattr_settype failed");
00088       return 1;
00089     }
00090 
00091 #ifdef ENABLE_PI
00092   if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
00093     {
00094       puts ("pthread_mutexattr_setprotocol failed");
00095       return 1;
00096     }
00097 #endif
00098 
00099   int e;
00100   if ((e = pthread_mutex_init (m, &a)) != 0)
00101     {
00102 #ifdef ENABLE_PI
00103       if (e == ENOTSUP)
00104        {
00105          puts ("PI mutexes unsupported");
00106          return 0;
00107        }
00108 #endif
00109       puts ("mutex_init failed");
00110       return 1;
00111     }
00112 
00113   if (pthread_mutex_lock (m) != 0)
00114     {
00115       puts ("mutex_lock failed");
00116       return 1;
00117     }
00118 
00119   if (pthread_mutexattr_destroy (&a) != 0)
00120     {
00121       puts ("mutexattr_destroy failed");
00122       return 1;
00123     }
00124 
00125   puts ("going to fork now");
00126   pid = fork ();
00127   if (pid == -1)
00128     {
00129       puts ("fork failed");
00130       return 1;
00131     }
00132   else if (pid == 0)
00133     {
00134       if (pthread_mutex_trylock (m) == 0)
00135        {
00136          puts ("child: mutex_trylock succeeded");
00137          exit (1);
00138        }
00139 
00140       if (pthread_mutex_unlock (m) == 0)
00141        {
00142          puts ("child: mutex_unlock succeeded");
00143          exit (1);
00144        }
00145 
00146       struct timeval tv;
00147       gettimeofday (&tv, NULL);
00148       struct timespec ts;
00149       TIMEVAL_TO_TIMESPEC (&tv, &ts);
00150       ts.tv_nsec += 500000000;
00151       if (ts.tv_nsec >= 1000000000)
00152        {
00153          ++ts.tv_sec;
00154          ts.tv_nsec -= 1000000000;
00155        }
00156 
00157       e = pthread_mutex_timedlock (m, &ts);
00158       if (e == 0)
00159        {
00160          puts ("child: mutex_timedlock succeeded");
00161          exit (1);
00162        }
00163       if (e != ETIMEDOUT)
00164        {
00165          puts ("child: mutex_timedlock didn't time out");
00166          exit (1);
00167        }
00168 
00169       alarm (1);
00170 
00171       pthread_mutex_lock (m);
00172 
00173       puts ("child: mutex_lock returned");
00174 
00175       exit (0);
00176     }
00177 
00178   sleep (2);
00179 
00180   int status;
00181   if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
00182     {
00183       puts ("waitpid failed");
00184       return 1;
00185     }
00186   if (! WIFSIGNALED (status))
00187     {
00188       puts ("child not killed by signal");
00189       return 1;
00190     }
00191   if (WTERMSIG (status) != SIGALRM)
00192     {
00193       puts ("child not killed by SIGALRM");
00194       return 1;
00195     }
00196 
00197   return 0;
00198 }
00199 
00200 #define TIMEOUT 3
00201 #define TEST_FUNCTION do_test ()
00202 #include "../test-skeleton.c"