Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / regress / sys / kern / select / select.c
blob88b6fd04ef233f28d020cf786386af5162c38189
1 /* $NetBSD: select.c,v 1.1 2008/03/21 12:27:12 yamt Exp $ */
3 /*-
4 * Copyright (c)2008 YAMAMOTO Takashi,
5 * All rights reserved.
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.
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.
29 #define FD_SETSIZE 65536
30 #include <sys/select.h>
31 #include <sys/atomic.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <pthread.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
41 #define NPIPE 128
42 #define NTHREAD 64
43 #define VERBOSE 0
45 #if !defined(RANDOM_MAX)
46 #define RANDOM_MAX ((1UL << 31) - 1)
47 #endif
49 int fds[NPIPE][2];
51 unsigned count;
53 pthread_barrier_t barrier;
55 static void
56 dowrite(void)
58 char buf[1];
59 int fd;
60 int i;
62 i = random() % NPIPE;
63 fd = fds[i][1];
64 #if VERBOSE
65 printf("[%p] write %d\n", (void *)pthread_self(), fd);
66 #endif
67 if (write(fd, buf, sizeof(buf)) == -1) {
68 perror("write");
69 abort();
73 static void *
74 f(void *dummy)
77 pthread_barrier_wait(&barrier);
79 for (;;) {
80 struct timeval to;
81 fd_set oset;
82 fd_set set;
83 int maxfd = -1;
84 int nfd = 0;
85 int ret;
86 int fd;
87 int i;
89 FD_ZERO(&set);
90 do {
91 for (i = 0; i < NPIPE; i++) {
92 fd = fds[i][0];
93 if (fd > FD_SETSIZE) {
94 fprintf(stderr,
95 "fd(%d) > FD_SETSIZE(%d)\n",
96 fd, FD_SETSIZE);
97 abort();
99 if (random() & 1) {
100 FD_SET(fd, &set);
101 if (fd > maxfd) {
102 maxfd = fd;
103 nfd++;
107 } while (nfd == 0);
108 memcpy(&oset, &set, sizeof(oset));
109 memset(&to, 0, sizeof(to));
110 to.tv_sec = random() % 10;
111 to.tv_usec = random() % 1000000;
112 #if VERBOSE
113 printf("[%p] select start to=%lu\n", (void *)pthread_self(),
114 (unsigned long)to.tv_sec);
115 #endif
116 ret = select(maxfd + 1, &set, NULL, NULL, &to);
117 #if VERBOSE
118 printf("[%p] select done ret=%d\n",
119 (void *)pthread_self(), ret);
120 #endif
121 if (ret == -1) {
122 perror("select");
123 abort();
125 if (ret > nfd) {
126 fprintf(stderr, "[%p] unexpected return value %d\n",
127 (void *)pthread_self(), ret);
128 abort();
130 nfd = 0;
131 for (fd = 0; fd <= maxfd; fd++) {
132 if (FD_ISSET(fd, &set)) {
133 char buf[1];
135 #if VERBOSE
136 printf("[%p] read %d\n",
137 (void *)pthread_self(), fd);
138 #endif
139 if (!FD_ISSET(fd, &oset)) {
140 fprintf(stderr, "[%p] unexpected\n",
141 (void *)pthread_self());
142 abort();
144 if (read(fd, buf, sizeof(buf)) == -1) {
145 if (errno != EAGAIN) {
146 perror("read");
147 abort();
149 } else {
150 dowrite();
151 atomic_inc_uint(&count);
153 nfd++;
156 if (ret != nfd) {
157 fprintf(stderr, "[%p] ret(%d) != nfd(%d)\n",
158 (void *)pthread_self(), ret, nfd);
159 abort();
165 main(int argc, char *argv[])
167 pthread_t pt[NTHREAD];
168 int i;
169 unsigned int secs;
171 secs = atoi(argv[1]);
173 for (i = 0; i < NPIPE; i++) {
174 if (pipe(fds[i])) {
175 perror("pipe");
176 abort();
178 if (fcntl(fds[i][0], F_SETFL, O_NONBLOCK) == -1) {
179 perror("fcntl");
180 abort();
183 pthread_barrier_init(&barrier, NULL, NTHREAD + 1);
184 for (i = 0; i < NTHREAD; i++) {
185 int error = pthread_create(&pt[i], NULL, f, NULL);
186 if (error) {
187 errno = error;
188 perror("pthread_create");
189 abort();
192 pthread_barrier_wait(&barrier);
193 dowrite();
194 dowrite();
195 dowrite();
196 dowrite();
198 sleep(secs);
199 printf("%u / %u = %lf\n", count, secs, (double)count / secs);
200 exit(EXIT_SUCCESS);