OSDN Git Service

d14f6f633e025006dc3a4f4e01f3731b1cfb5c4e
[uclinux-h8/uClibc.git] / test / nptl / tst-sem3.c
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <errno.h>
20 #include <semaphore.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/mman.h>
27 #include <sys/wait.h>
28
29
30 int
31 main (void)
32 {
33   size_t ps = sysconf (_SC_PAGESIZE);
34   char tmpfname[] = "/tmp/tst-sem3.XXXXXX";
35   char data[ps];
36   void *mem;
37   int fd;
38   sem_t *s;
39   pid_t pid;
40   char *p;
41
42   fd = mkstemp (tmpfname);
43   if (fd == -1)
44     {
45       printf ("cannot open temporary file: %m\n");
46       exit (1);
47     }
48
49   /* Make sure it is always removed.  */
50   unlink (tmpfname);
51
52   /* Create one page of data.  */
53   memset (data, '\0', ps);
54
55   /* Write the data to the file.  */
56   if (write (fd, data, ps) != (ssize_t) ps)
57     {
58       puts ("short write");
59       exit (1);
60     }
61
62   mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
63   if (mem == MAP_FAILED)
64     {
65       printf ("mmap failed: %m\n");
66       exit (1);
67     }
68
69   s = (sem_t *) (((uintptr_t) mem + __alignof (sem_t))
70                  & ~(__alignof (sem_t) - 1));
71   p = (char *) (s + 1);
72
73   if (sem_init (s, 1, 1) == -1)
74     {
75       puts ("init failed");
76       exit (1);
77     }
78
79   if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
80     {
81       puts ("1st wait failed");
82       exit (1);
83     }
84
85   errno = 0;
86   if (TEMP_FAILURE_RETRY (sem_trywait (s)) != -1)
87     {
88       puts ("trywait succeeded");
89       exit (1);
90     }
91   else if (errno != EAGAIN)
92     {
93       puts ("trywait didn't return EAGAIN");
94       exit (1);
95     }
96
97   *p = 0;
98
99   puts ("going to fork now");
100   pid = fork ();
101   if (pid == -1)
102     {
103       puts ("fork failed");
104       exit (1);
105     }
106   else if (pid == 0)
107     {
108       /* Play some lock ping-pong.  It's our turn to unlock first.  */
109       if ((*p)++ != 0)
110         {
111           puts ("child: *p != 0");
112           exit (1);
113         }
114
115       if (sem_post (s) == -1)
116         {
117           puts ("child: 1st post failed");
118           exit (1);
119         }
120
121       puts ("child done");
122     }
123   else
124     {
125       if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
126         {
127           printf ("parent: 2nd wait failed: %m\n");
128           exit (1);
129         }
130
131       if (*p != 1)
132         {
133           puts ("*p != 1");
134           exit (1);
135         }
136
137       puts ("parent done");
138     }
139
140   exit (0);
141 }