Back to index

glibc  2.9
tst-robust8.c
Go to the documentation of this file.
00001 #include <pthread.h>
00002 #include <signal.h>
00003 #include <stdint.h>
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include <string.h>
00007 #include <unistd.h>
00008 #include <sys/mman.h>
00009 #include <sys/wait.h>
00010 
00011 
00012 
00013 
00014 static void prepare (void);
00015 #define PREPARE(argc, argv) prepare ()
00016 static int do_test (void);
00017 #define TEST_FUNCTION do_test ()
00018 #define TIMEOUT 5
00019 #include "../test-skeleton.c"
00020 
00021 
00022 static int fd;
00023 #define N 100
00024 
00025 static void
00026 prepare (void)
00027 {
00028   fd = create_temp_file ("tst-robust8", NULL);
00029   if (fd == -1)
00030     exit (1);
00031 }
00032 
00033 
00034 #define THESIGNAL SIGKILL
00035 #define ROUNDS 5
00036 #define THREADS 9
00037 
00038 
00039 static const struct timespec before = { 0, 0 };
00040 
00041 
00042 static pthread_mutex_t *map;
00043 
00044 
00045 static void *
00046 tf (void *arg)
00047 {
00048   long int nr = (long int) arg;
00049   int fct = nr % 3;
00050 
00051   uint8_t state[N];
00052   memset (state, '\0', sizeof (state));
00053 
00054   while (1)
00055     {
00056       int r = random () % N;
00057       if (state[r] == 0)
00058        {
00059          int e;
00060 
00061          switch (fct)
00062            {
00063            case 0:
00064              e = pthread_mutex_lock (&map[r]);
00065              if (e != 0)
00066               {
00067                 printf ("mutex_lock of %d in thread %ld failed with %d\n",
00068                        r, nr, e);
00069                 exit (1);
00070               }
00071              state[r] = 1;
00072              break;
00073            case 1:
00074              e = pthread_mutex_timedlock (&map[r], &before);
00075              if (e != 0 && e != ETIMEDOUT)
00076               {
00077                 printf ("\
00078 mutex_timedlock of %d in thread %ld failed with %d\n",
00079                        r, nr, e);
00080                 exit (1);
00081               }
00082              break;
00083            default:
00084              e = pthread_mutex_trylock (&map[r]);
00085              if (e != 0 && e != EBUSY)
00086               {
00087                 printf ("mutex_trylock of %d in thread %ld failed with %d\n",
00088                        r, nr, e);
00089                 exit (1);
00090               }
00091              break;
00092            }
00093 
00094          if (e == EOWNERDEAD)
00095            pthread_mutex_consistent_np (&map[r]);
00096 
00097          if (e == 0 || e == EOWNERDEAD)
00098            state[r] = 1;
00099        }
00100       else
00101        {
00102          int e = pthread_mutex_unlock (&map[r]);
00103          if (e != 0)
00104            {
00105              printf ("mutex_unlock of %d in thread %ld failed with %d\n",
00106                     r, nr, e);
00107              exit (1);
00108            }
00109 
00110          state[r] = 0;
00111        }
00112     }
00113 }
00114 
00115 
00116 static void
00117 child (int round)
00118 {
00119   for (int thread = 1; thread <= THREADS; ++thread)
00120     {
00121       pthread_t th;
00122       if (pthread_create (&th, NULL, tf, (void *) (long int) thread) != 0)
00123        {
00124          printf ("cannot create thread %d in round %d\n", thread, round);
00125          exit (1);
00126        }
00127     }
00128 
00129   struct timespec ts;
00130   ts.tv_sec = 0;
00131   ts.tv_nsec = 1000000000 / ROUNDS;
00132   while (nanosleep (&ts, &ts) != 0)
00133     /* nothing */;
00134 
00135   /* Time to die.  */
00136   kill (getpid (), THESIGNAL);
00137 
00138   /* We better never get here.  */
00139   abort ();
00140 }
00141 
00142 
00143 static int
00144 do_test (void)
00145 {
00146   if (ftruncate (fd, N * sizeof (pthread_mutex_t)) != 0)
00147     {
00148       puts ("cannot size new file");
00149       return 1;
00150     }
00151 
00152   map = mmap (NULL, N * sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE,
00153              MAP_SHARED, fd, 0);
00154   if (map == MAP_FAILED)
00155     {
00156       puts ("mapping failed");
00157       return 1;
00158     }
00159 
00160   pthread_mutexattr_t ma;
00161   if (pthread_mutexattr_init (&ma) != 0)
00162     {
00163       puts ("mutexattr_init failed");
00164       return 0;
00165     }
00166   if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0)
00167     {
00168       puts ("mutexattr_setrobust failed");
00169       return 1;
00170     }
00171   if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
00172     {
00173       puts ("mutexattr_setpshared failed");
00174       return 1;
00175     }
00176 #ifdef ENABLE_PI
00177   if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0)
00178     {
00179       puts ("pthread_mutexattr_setprotocol failed");
00180       return 1;
00181     }
00182 #endif
00183 
00184   for (int round = 1; round <= ROUNDS; ++round)
00185     {
00186       for (int n = 0; n < N; ++n)
00187        {
00188          int e = pthread_mutex_init (&map[n], &ma);
00189          if (e == ENOTSUP)
00190            {
00191 #ifdef ENABLE_PI
00192              puts ("cannot support pshared robust PI mutexes");
00193 #else
00194              puts ("cannot support pshared robust mutexes");
00195 #endif
00196              return 0;
00197            }
00198          if (e != 0)
00199            {
00200              printf ("mutex_init %d in round %d failed\n", n + 1, round);
00201              return 1;
00202            }
00203        }
00204 
00205       pid_t p = fork ();
00206       if (p == -1)
00207        {
00208          printf ("fork in round %d failed\n", round);
00209          return 1;
00210        }
00211       if (p == 0)
00212        child (round);
00213 
00214       int status;
00215       if (TEMP_FAILURE_RETRY (waitpid (p, &status, 0)) != p)
00216        {
00217          printf ("waitpid in round %d failed\n", round);
00218          return 1;
00219        }
00220       if (!WIFSIGNALED (status))
00221        {
00222          printf ("child did not die of a signal in round %d\n", round);
00223          return 1;
00224        }
00225       if (WTERMSIG (status) != THESIGNAL)
00226        {
00227          printf ("child did not die of signal %d in round %d\n",
00228                 THESIGNAL, round);
00229          return 1;
00230        }
00231 
00232       for (int n = 0; n < N; ++n)
00233        {
00234          int e = pthread_mutex_lock (&map[n]);
00235          if (e != 0 && e != EOWNERDEAD)
00236            {
00237              printf ("mutex_lock %d failed in round %d\n", n + 1, round);
00238              return 1;
00239            }
00240        }
00241 
00242       for (int n = 0; n < N; ++n)
00243        if (pthread_mutex_unlock (&map[n]) != 0)
00244          {
00245            printf ("mutex_unlock %d failed in round %d\n", n + 1, round);
00246            return 1;
00247          }
00248 
00249       for (int n = 0; n < N; ++n)
00250        {
00251          int e = pthread_mutex_destroy (&map[n]);
00252          if (e != 0)
00253            {
00254              printf ("mutex_destroy %d in round %d failed with %d\n",
00255                     n + 1, round, e);
00256              printf("nusers = %d\n", (int) map[n].__data.__nusers);
00257              return 1;
00258            }
00259        }
00260     }
00261 
00262   if (pthread_mutexattr_destroy (&ma) != 0)
00263     {
00264       puts ("mutexattr_destroy failed");
00265       return 1;
00266     }
00267 
00268   if (munmap (map, N * sizeof (pthread_mutex_t)) != 0)
00269     {
00270       puts ("munmap failed");
00271       return 1;
00272     }
00273 
00274   return 0;
00275 }