Back to index

glibc  2.9
tst-spin2.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004 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-spin2.XXXXXX";
00036   char data[ps];
00037   void *mem;
00038   int fd;
00039   pthread_spinlock_t *s;
00040   pid_t pid;
00041   char *p;
00042   int err;
00043 
00044   fd = mkstemp (tmpfname);
00045   if (fd == -1)
00046     {
00047       printf ("cannot open temporary file: %m\n");
00048       return 1;
00049     }
00050 
00051   /* Make sure it is always removed.  */
00052   unlink (tmpfname);
00053 
00054   /* Create one page of data.  */
00055   memset (data, '\0', ps);
00056 
00057   /* Write the data to the file.  */
00058   if (write (fd, data, ps) != (ssize_t) ps)
00059     {
00060       puts ("short write");
00061       return 1;
00062     }
00063 
00064   mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
00065   if (mem == MAP_FAILED)
00066     {
00067       printf ("mmap failed: %m\n");
00068       return 1;
00069     }
00070 
00071   s = (pthread_spinlock_t *) (((uintptr_t) mem
00072                             + __alignof (pthread_spinlock_t))
00073                            & ~(__alignof (pthread_spinlock_t) - 1));
00074   p = (char *) (s + 1);
00075 
00076   if (pthread_spin_init (s, PTHREAD_PROCESS_SHARED) != 0)
00077     {
00078       puts ("spin_init failed");
00079       return 1;
00080     }
00081 
00082   if (pthread_spin_lock (s) != 0)
00083     {
00084       puts ("spin_lock failed");
00085       return 1;
00086     }
00087 
00088   err = pthread_spin_trylock (s);
00089   if (err == 0)
00090     {
00091       puts ("1st spin_trylock succeeded");
00092       return 1;
00093     }
00094   else if (err != EBUSY)
00095     {
00096       puts ("1st spin_trylock didn't return EBUSY");
00097       return 1;
00098     }
00099 
00100   err = pthread_spin_unlock (s);
00101   if (err != 0)
00102     {
00103       puts ("parent: spin_unlock failed");
00104       return 1;
00105     }
00106 
00107   err = pthread_spin_trylock (s);
00108   if (err != 0)
00109     {
00110       puts ("2nd spin_trylock failed");
00111       return 1;
00112     }
00113 
00114   *p = 0;
00115 
00116   puts ("going to fork now");
00117   pid = fork ();
00118   if (pid == -1)
00119     {
00120       puts ("fork failed");
00121       return 1;
00122     }
00123   else if (pid == 0)
00124     {
00125       /* Play some lock ping-pong.  It's our turn to unlock first.  */
00126       if ((*p)++ != 0)
00127        {
00128          puts ("child: *p != 0");
00129          return 1;
00130        }
00131 
00132       if (pthread_spin_unlock (s) != 0)
00133        {
00134          puts ("child: 1st spin_unlock failed");
00135          return 1;
00136        }
00137 
00138       puts ("child done");
00139     }
00140   else
00141     {
00142       if (pthread_spin_lock (s) != 0)
00143        {
00144          puts ("parent: 2nd spin_lock failed");
00145          return 1;
00146        }
00147 
00148       puts ("waiting for child");
00149 
00150       waitpid (pid, NULL, 0);
00151 
00152       puts ("parent done");
00153     }
00154 
00155   return 0;
00156 }
00157 
00158 #define TEST_FUNCTION do_test ()
00159 #include "../test-skeleton.c"