Back to index

glibc  2.9
tst-mutex4.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 <stdint.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <unistd.h>
00027 #include <sys/mman.h>
00028 #include <sys/wait.h>
00029 
00030 
00031 static int
00032 do_test (void)
00033 {
00034   size_t ps = sysconf (_SC_PAGESIZE);
00035   char tmpfname[] = "/tmp/tst-mutex4.XXXXXX";
00036   char data[ps];
00037   void *mem;
00038   int fd;
00039   pthread_mutex_t *m;
00040   pthread_mutexattr_t a;
00041   pid_t pid;
00042   char *p;
00043   int err;
00044   int s;
00045   pthread_barrier_t *b;
00046   pthread_barrierattr_t ba;
00047 
00048   fd = mkstemp (tmpfname);
00049   if (fd == -1)
00050     {
00051       printf ("cannot open temporary file: %m\n");
00052       return 1;
00053     }
00054 
00055   /* Make sure it is always removed.  */
00056   unlink (tmpfname);
00057 
00058   /* Create one page of data.  */
00059   memset (data, '\0', ps);
00060 
00061   /* Write the data to the file.  */
00062   if (write (fd, data, ps) != (ssize_t) ps)
00063     {
00064       puts ("short write");
00065       return 1;
00066     }
00067 
00068   mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
00069   if (mem == MAP_FAILED)
00070     {
00071       printf ("mmap failed: %m\n");
00072       return 1;
00073     }
00074 
00075   m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t) - 1)
00076                         & ~(__alignof (pthread_mutex_t) - 1));
00077   b = (pthread_barrier_t *) (((uintptr_t) (m + 1)
00078                            + __alignof (pthread_barrier_t) - 1)
00079                           & ~(__alignof (pthread_barrier_t) - 1));
00080   p = (char *) (b + 1);
00081 
00082   if (pthread_mutexattr_init (&a) != 0)
00083     {
00084       puts ("mutexattr_init failed");
00085       return 1;
00086     }
00087 
00088   if (pthread_mutexattr_getpshared (&a, &s) != 0)
00089     {
00090       puts ("1st mutexattr_getpshared failed");
00091       return 1;
00092     }
00093 
00094   if (s != PTHREAD_PROCESS_PRIVATE)
00095     {
00096       puts ("default pshared value wrong");
00097       return 1;
00098     }
00099 
00100   if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
00101     {
00102       puts ("mutexattr_setpshared failed");
00103       return 1;
00104     }
00105 
00106   if (pthread_mutexattr_getpshared (&a, &s) != 0)
00107     {
00108       puts ("2nd mutexattr_getpshared failed");
00109       return 1;
00110     }
00111 
00112   if (s != PTHREAD_PROCESS_SHARED)
00113     {
00114       puts ("pshared value after setpshared call wrong");
00115       return 1;
00116     }
00117 
00118 #ifdef ENABLE_PI
00119   if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
00120     {
00121       puts ("pthread_mutexattr_setprotocol failed");
00122       return 1;
00123     }
00124 #endif
00125 
00126   if ((err = pthread_mutex_init (m, &a)) != 0)
00127     {
00128 #ifdef ENABLE_PI
00129       if (err == ENOTSUP)
00130        {
00131          puts ("PI mutexes unsupported");
00132          return 0;
00133        }
00134 #endif
00135       puts ("mutex_init failed");
00136       return 1;
00137     }
00138 
00139   if (pthread_mutex_lock (m) != 0)
00140     {
00141       puts ("mutex_lock failed");
00142       return 1;
00143     }
00144 
00145   if (pthread_mutexattr_destroy (&a) != 0)
00146     {
00147       puts ("mutexattr_destroy failed");
00148       return 1;
00149     }
00150 
00151   if (pthread_barrierattr_init (&ba) != 0)
00152     {
00153       puts ("barrierattr_init failed");
00154       return 1;
00155     }
00156 
00157   if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
00158     {
00159       puts ("barrierattr_setpshared failed");
00160       return 1;
00161     }
00162 
00163   if (pthread_barrier_init (b, &ba, 2) != 0)
00164     {
00165       puts ("barrier_init failed");
00166       return 1;
00167     }
00168 
00169   if (pthread_barrierattr_destroy (&ba) != 0)
00170     {
00171       puts ("barrierattr_destroy failed");
00172       return 1;
00173     }
00174 
00175   err = pthread_mutex_trylock (m);
00176   if (err == 0)
00177     {
00178       puts ("mutex_trylock succeeded");
00179       return 1;
00180     }
00181   else if (err != EBUSY)
00182     {
00183       puts ("mutex_trylock didn't return EBUSY");
00184       return 1;
00185     }
00186 
00187   *p = 0;
00188 
00189   if (pthread_mutex_unlock (m) != 0)
00190     {
00191       puts ("parent: 1st mutex_unlock failed");
00192       return 1;
00193     }
00194 
00195   puts ("going to fork now");
00196   pid = fork ();
00197   if (pid == -1)
00198     {
00199       puts ("fork failed");
00200       return 1;
00201     }
00202   else if (pid == 0)
00203     {
00204       if (pthread_mutex_lock (m) != 0)
00205        {
00206          puts ("child: mutex_lock failed");
00207          return 1;
00208        }
00209 
00210       int e = pthread_barrier_wait (b);
00211       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00212        {
00213          puts ("child: barrier_wait failed");
00214          return 1;
00215        }
00216 
00217       if ((*p)++ != 0)
00218        {
00219          puts ("child: *p != 0");
00220          return 1;
00221        }
00222 
00223       if (pthread_mutex_unlock (m) != 0)
00224        {
00225          puts ("child: mutex_unlock failed");
00226          return 1;
00227        }
00228 
00229       puts ("child done");
00230     }
00231   else
00232     {
00233       int e = pthread_barrier_wait (b);
00234       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00235        {
00236          puts ("parent: barrier_wait failed");
00237          return 1;
00238        }
00239 
00240       if (pthread_mutex_lock (m) != 0)
00241        {
00242          puts ("parent: 2nd mutex_lock failed");
00243          return 1;
00244        }
00245 
00246       if (*p != 1)
00247        {
00248          puts ("*p != 1");
00249          return 1;
00250        }
00251 
00252       if (pthread_mutex_unlock (m) != 0)
00253        {
00254          puts ("parent: 2nd mutex_unlock failed");
00255          return 1;
00256        }
00257 
00258       if (pthread_mutex_destroy (m) != 0)
00259        {
00260          puts ("mutex_destroy failed");
00261          return 1;
00262        }
00263 
00264       if (pthread_barrier_destroy (b) != 0)
00265        {
00266          puts ("barrier_destroy failed");
00267          return 1;
00268        }
00269 
00270       puts ("parent done");
00271     }
00272 
00273   return 0;
00274 }
00275 
00276 #define TIMEOUT 4
00277 #define TEST_FUNCTION do_test ()
00278 #include "../test-skeleton.c"