Back to index

glibc  2.9
tst-cond12.c
Go to the documentation of this file.
00001 /* Copyright (C) 2003 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 <signal.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 #include <sys/mman.h>
00027 #include <sys/wait.h>
00028 
00029 
00030 static char fname[] = "/tmp/tst-cond12-XXXXXX";
00031 static int fd;
00032 
00033 
00034 static void prepare (void);
00035 #define PREPARE(argc, argv) prepare ()
00036 
00037 static int do_test (void);
00038 #define TEST_FUNCTION do_test ()
00039 
00040 #include "../test-skeleton.c"
00041 
00042 
00043 static void
00044 prepare (void)
00045 {
00046   fd = mkstemp (fname);
00047   if (fd == -1)
00048     {
00049       printf ("mkstemp failed: %m\n");
00050       exit (1);
00051     }
00052   add_temp_file (fname);
00053   if (ftruncate (fd, 1000) < 0)
00054     {
00055       printf ("ftruncate failed: %m\n");
00056       exit (1);
00057     }
00058 }
00059 
00060 
00061 static int
00062 do_test (void)
00063 {
00064   struct
00065   {
00066     pthread_mutex_t m;
00067     pthread_cond_t c;
00068     int var;
00069   } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
00070   if (p == MAP_FAILED)
00071     {
00072       printf ("initial mmap failed: %m\n");
00073       return 1;
00074     }
00075 
00076   pthread_mutexattr_t ma;
00077   if (pthread_mutexattr_init (&ma) != 0)
00078     {
00079       puts ("mutexattr_init failed");
00080       return 1;
00081     }
00082   if (pthread_mutexattr_setpshared (&ma, 1) != 0)
00083     {
00084       puts ("mutexattr_setpshared failed");
00085       return 1;
00086     }
00087   if (pthread_mutex_init (&p->m, &ma) != 0)
00088     {
00089       puts ("mutex_init failed");
00090       return 1;
00091     }
00092   if (pthread_mutexattr_destroy (&ma) != 0)
00093     {
00094       puts ("mutexattr_destroy failed");
00095       return 1;
00096     }
00097 
00098   pthread_condattr_t ca;
00099   if (pthread_condattr_init (&ca) != 0)
00100     {
00101       puts ("condattr_init failed");
00102       return 1;
00103     }
00104   if (pthread_condattr_setpshared (&ca, 1) != 0)
00105     {
00106       puts ("condattr_setpshared failed");
00107       return 1;
00108     }
00109   if (pthread_cond_init (&p->c, &ca) != 0)
00110     {
00111       puts ("mutex_init failed");
00112       return 1;
00113     }
00114   if (pthread_condattr_destroy (&ca) != 0)
00115     {
00116       puts ("condattr_destroy failed");
00117       return 1;
00118     }
00119 
00120   if (pthread_mutex_lock (&p->m) != 0)
00121     {
00122       puts ("initial mutex_lock failed");
00123       return 1;
00124     }
00125 
00126   p->var = 42;
00127 
00128   pid_t pid = fork ();
00129   if (pid == -1)
00130     {
00131       printf ("fork failed: %m\n");
00132       return 1;
00133     }
00134 
00135   if (pid == 0)
00136     {
00137       void *oldp = p;
00138       p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
00139 
00140       if (p == oldp)
00141        {
00142          puts ("child: mapped to same address");
00143          kill (getppid (), SIGKILL);
00144          exit (1);
00145        }
00146 
00147       munmap (oldp, sizeof (*p));
00148 
00149       if (pthread_mutex_lock (&p->m) != 0)
00150        {
00151          puts ("child: mutex_lock failed");
00152          kill (getppid (), SIGKILL);
00153          exit (1);
00154        }
00155 
00156       p->var = 0;
00157 
00158 #ifndef USE_COND_SIGNAL
00159       if (pthread_cond_broadcast (&p->c) != 0)
00160        {
00161          puts ("child: cond_broadcast failed");
00162          kill (getppid (), SIGKILL);
00163          exit (1);
00164        }
00165 #else
00166       if (pthread_cond_signal (&p->c) != 0)
00167        {
00168          puts ("child: cond_signal failed");
00169          kill (getppid (), SIGKILL);
00170          exit (1);
00171        }
00172 #endif
00173 
00174       if (pthread_mutex_unlock (&p->m) != 0)
00175        {
00176          puts ("child: mutex_unlock failed");
00177          kill (getppid (), SIGKILL);
00178          exit (1);
00179        }
00180 
00181       exit (0);
00182     }
00183 
00184   do
00185     pthread_cond_wait (&p->c, &p->m);
00186   while (p->var != 0);
00187 
00188   if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid)
00189     {
00190       printf ("waitpid failed: %m\n");
00191       kill (pid, SIGKILL);
00192       return 1;
00193     }
00194 
00195   return 0;
00196 }