Back to index

glibc  2.9
tst-robust7.c
Go to the documentation of this file.
00001 /* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
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 <stdbool.h>
00023 #include <stdio.h>
00024 
00025 
00026 static pthread_barrier_t b;
00027 static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
00028 static pthread_mutex_t m;
00029 static bool first = true;
00030 
00031 
00032 static void *
00033 tf (void *arg)
00034 {
00035   long int n = (long int) arg;
00036 
00037   if (pthread_mutex_lock (&m) != 0)
00038     {
00039       printf ("thread %ld: mutex_lock failed\n", n + 1);
00040       exit (1);
00041     }
00042 
00043   int e = pthread_barrier_wait (&b);
00044   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00045     {
00046       printf ("thread %ld: barrier_wait failed\n", n + 1);
00047       exit (1);
00048     }
00049 
00050   e = pthread_cond_wait (&c, &m);
00051   if (first)
00052     {
00053       if (e != 0)
00054        {
00055          printf ("thread %ld: cond_wait failed\n", n + 1);
00056          exit (1);
00057        }
00058       first = false;
00059     }
00060   else
00061     {
00062       if (e != EOWNERDEAD)
00063        {
00064          printf ("thread %ld: cond_wait did not return EOWNERDEAD\n", n + 1);
00065          exit (1);
00066        }
00067     }
00068 
00069   if (pthread_cancel (pthread_self ()) != 0)
00070     {
00071       printf ("thread %ld: cancel failed\n", n + 1);
00072       exit (1);
00073     }
00074 
00075   pthread_testcancel ();
00076 
00077   printf ("thread %ld: testcancel returned\n", n + 1);
00078   exit (1);
00079 }
00080 
00081 
00082 static int
00083 do_test (void)
00084 {
00085   pthread_mutexattr_t a;
00086   if (pthread_mutexattr_init (&a) != 0)
00087     {
00088       puts ("mutexattr_init failed");
00089       return 1;
00090     }
00091 
00092   if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0)
00093     {
00094       puts ("mutexattr_setrobust failed");
00095       return 1;
00096     }
00097 
00098 #ifdef ENABLE_PI
00099   if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
00100     {
00101       puts ("pthread_mutexattr_setprotocol failed");
00102       return 1;
00103     }
00104 #endif
00105 
00106   int e;
00107   e = pthread_mutex_init (&m, &a);
00108   if (e != 0)
00109     {
00110 #ifdef ENABLE_PI
00111       if (e == ENOTSUP)
00112        {
00113          puts ("PI robust mutexes not supported");
00114          return 0;
00115        }
00116 #endif
00117       puts ("mutex_init failed");
00118       return 1;
00119     }
00120 
00121   if (pthread_mutexattr_destroy (&a) != 0)
00122     {
00123       puts ("mutexattr_destroy failed");
00124       return 1;
00125     }
00126 
00127   if (pthread_barrier_init (&b, NULL, 2) != 0)
00128     {
00129       puts ("barrier_init failed");
00130       return 1;
00131     }
00132 
00133 #define N 5
00134   pthread_t th[N];
00135   for (long int n = 0; n < N; ++n)
00136     {
00137       if (pthread_create (&th[n], NULL, tf, (void *) n) != 0)
00138        {
00139          printf ("pthread_create loop %ld failed\n", n + 1);
00140          return 1;
00141        }
00142 
00143       e = pthread_barrier_wait (&b);
00144       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00145        {
00146          printf ("parent: barrier_wait failed in round %ld\n", n + 1);
00147          return 1;
00148        }
00149     }
00150 
00151   if (pthread_mutex_lock (&m) != 0)
00152     {
00153       puts ("parent: mutex_lock failed");
00154       return 1;
00155     }
00156 
00157   if (pthread_mutex_unlock (&m) != 0)
00158     {
00159       puts ("parent: mutex_unlock failed");
00160       return 1;
00161     }
00162 
00163   if (pthread_cond_broadcast (&c) != 0)
00164     {
00165       puts ("cond_broadcast failed");
00166       return 1;
00167     }
00168 
00169   for (int n = 0; n < N; ++n)
00170     {
00171       void *res;
00172       if (pthread_join (th[n], &res) != 0)
00173        {
00174          printf ("join round %d failed\n", n + 1);
00175          return 1;
00176        }
00177       if (res != PTHREAD_CANCELED)
00178        {
00179          printf ("thread %d not canceled\n", n + 1);
00180          return 1;
00181        }
00182     }
00183 
00184   e = pthread_mutex_lock (&m);
00185   if (e == 0)
00186     {
00187       puts ("parent: 2nd mutex_lock succeeded");
00188       return 1;
00189     }
00190   if (e != EOWNERDEAD)
00191     {
00192       puts ("parent: mutex_lock did not return EOWNERDEAD");
00193       return 1;
00194     }
00195 
00196   if (pthread_mutex_unlock (&m) != 0)
00197     {
00198       puts ("parent: 2nd mutex_unlock failed");
00199       return 1;
00200     }
00201 
00202   if (pthread_mutex_destroy (&m) != 0)
00203     {
00204       puts ("mutex_destroy failed");
00205       return 1;
00206     }
00207 
00208   return 0;
00209 }
00210 
00211 #define TEST_FUNCTION do_test ()
00212 #include "../test-skeleton.c"