]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/test/stress2/misc/select.sh
Merge llvm-project main llvmorg-12-init-17869-g8e464dd76bef
[FreeBSD/FreeBSD.git] / tools / test / stress2 / misc / select.sh
1 #!/bin/sh
2
3 #
4 # Copyright (c) 2016 EMC Corp.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 # 1. Redistributions of source code must retain the above copyright
11 #    notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 #    notice, this list of conditions and the following disclaimer in the
14 #    documentation and/or other materials provided with the distribution.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 # SUCH DAMAGE.
27 #
28
29 # The combination of ualarm() firing before and after the select(2) timeout
30 # triggers select() to return EINTR a number of times.
31 # Problem only seen on i386.
32
33 # Test scenario suggestion by kib@
34
35 # "FAIL n = 2389" seen on r302369, no debug build.
36 # Fixed by: r302573.
37
38 . ../default.cfg
39
40 dir=/tmp
41 odir=`pwd`
42 cd $dir
43 sed '1,/^EOF/d' < $odir/$0 > $dir/select.c
44 mycc -o select -Wall -Wextra -O0 -g select.c -lpthread || exit 1
45 rm -f select.c
46 cd $odir
47
48 /tmp/select
49 s=$?
50
51 rm -f /tmp/select
52 exit $s
53 EOF
54 #include <sys/param.h>
55 #include <sys/mman.h>
56 #include <sys/stat.h>
57 #include <sys/wait.h>
58
59 #include <err.h>
60 #include <errno.h>
61 #include <fcntl.h>
62 #include <pthread.h>
63 #include <signal.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <time.h>
68 #include <unistd.h>
69
70 static pthread_barrier_t barr;
71 static sig_atomic_t alarms;
72 static int lines;
73
74 #define LINES 128000
75 #define N 2000 /* also seen fail with N = 20.000 */
76 #define PARALLEL 16 /* Fails seen with 1 - 16 */
77 #define RUNTIME (10 * 60)
78
79 static void
80 handler(int i __unused) {
81         alarms++;
82 }
83
84 static void
85 test(void)
86 {
87         struct timeval tv;
88         int i, n, r, s;
89
90         r = pthread_barrier_wait(&barr);
91         if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
92             errc(1, r, "pthread_barrier_wait");
93
94         signal(SIGALRM, handler);
95         s = 0;
96         for (i = 0; i < lines; i++) {
97                 alarms = 0;
98                 if (arc4random() % 100 < 50)
99                         ualarm(N / 2, 0);
100                 else
101                         ualarm(N * 2, 0);
102                 tv.tv_sec  = 0;
103                 tv.tv_usec = N;
104                 n = 0;
105                 do {
106                         r = select(1, NULL, NULL, NULL, &tv);
107                         n++;
108                 } while (r == -1 && errno == EINTR);
109                 if (r == -1)
110                         err(1, "select");
111                 ualarm(0, 0);
112                 if (n > 2) {
113                         fprintf(stderr, "FAIL n = %d, tv = %ld.%06ld\n",
114                             n, (long)tv.tv_sec, tv.tv_usec);
115                         s = 1;
116                         break;
117                 }
118                 if (alarms >  1) {
119                         fprintf(stderr, "FAIL alarms = %d\n", (int)alarms);
120                         s = 2;
121                         break;
122                 }
123
124         }
125
126         exit(s);
127 }
128
129 int
130 main(void)
131 {
132         pthread_barrierattr_t attr;
133         time_t start;
134         int e, i, j, pids[PARALLEL], r, status;
135
136         lines = LINES / PARALLEL;
137         if (lines == 0)
138                 lines = 1;
139         e = 0;
140         if ((r = pthread_barrierattr_init(&attr)) != 0)
141                 errc(1, r, "pthread_barrierattr_init");
142         if ((r = pthread_barrierattr_setpshared(&attr,
143             PTHREAD_PROCESS_SHARED)) != 0)
144                 errc(1, r, "pthread_barrierattr_setpshared");
145         if ((r = pthread_barrier_init(&barr, &attr, PARALLEL)) != 0)
146                 errc(1, r, "pthread_barrier_init");
147
148         start = time(NULL);
149         while ((time(NULL) - start) < RUNTIME && e == 0) {
150                 for (i = 0; i < PARALLEL; i++) {
151                         if ((pids[i] = fork()) == 0)
152                                 test();
153                 }
154                 for (i = 0; i < PARALLEL; i++) {
155                         waitpid(pids[i], &status, 0);
156                         e += status == 0 ? 0 : 1;
157                         if (status != 0) {
158                                 for (j = i + 1; j < PARALLEL; j++)
159                                         kill(pids[j], SIGINT);
160                         }
161                 }
162         }
163
164         if ((r = pthread_barrier_destroy(&barr)) > 0)
165                 errc(1, r, "pthread_barrier_destroy");
166
167         return (e);
168 }