select.c revision 1.2.2.2 1 1.2.2.2 matt /* $NetBSD: select.c,v 1.2.2.2 2008/03/23 00:43:00 matt Exp $ */
2 1.2.2.2 matt
3 1.2.2.2 matt /*-
4 1.2.2.2 matt * Copyright (c)2008 YAMAMOTO Takashi,
5 1.2.2.2 matt * All rights reserved.
6 1.2.2.2 matt *
7 1.2.2.2 matt * Redistribution and use in source and binary forms, with or without
8 1.2.2.2 matt * modification, are permitted provided that the following conditions
9 1.2.2.2 matt * are met:
10 1.2.2.2 matt * 1. Redistributions of source code must retain the above copyright
11 1.2.2.2 matt * notice, this list of conditions and the following disclaimer.
12 1.2.2.2 matt * 2. Redistributions in binary form must reproduce the above copyright
13 1.2.2.2 matt * notice, this list of conditions and the following disclaimer in the
14 1.2.2.2 matt * documentation and/or other materials provided with the distribution.
15 1.2.2.2 matt *
16 1.2.2.2 matt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 1.2.2.2 matt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.2.2.2 matt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.2.2.2 matt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 1.2.2.2 matt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.2.2.2 matt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.2.2.2 matt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.2.2.2 matt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.2.2.2 matt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.2.2.2 matt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.2.2.2 matt * SUCH DAMAGE.
27 1.2.2.2 matt */
28 1.2.2.2 matt
29 1.2.2.2 matt #define FD_SETSIZE 65536
30 1.2.2.2 matt #include <sys/select.h>
31 1.2.2.2 matt #include <sys/atomic.h>
32 1.2.2.2 matt
33 1.2.2.2 matt #include <errno.h>
34 1.2.2.2 matt #include <fcntl.h>
35 1.2.2.2 matt #include <pthread.h>
36 1.2.2.2 matt #include <stdio.h>
37 1.2.2.2 matt #include <stdlib.h>
38 1.2.2.2 matt #include <string.h>
39 1.2.2.2 matt #include <unistd.h>
40 1.2.2.2 matt
41 1.2.2.2 matt #define NPIPE 128
42 1.2.2.2 matt #define NTHREAD 64
43 1.2.2.2 matt #define VERBOSE 0
44 1.2.2.2 matt
45 1.2.2.2 matt #if !defined(RANDOM_MAX)
46 1.2.2.2 matt #define RANDOM_MAX ((1UL << 31) - 1)
47 1.2.2.2 matt #endif
48 1.2.2.2 matt
49 1.2.2.2 matt int fds[NPIPE][2];
50 1.2.2.2 matt
51 1.2.2.2 matt unsigned count;
52 1.2.2.2 matt
53 1.2.2.2 matt pthread_barrier_t barrier;
54 1.2.2.2 matt
55 1.2.2.2 matt static void
56 1.2.2.2 matt dowrite(void)
57 1.2.2.2 matt {
58 1.2.2.2 matt char buf[1];
59 1.2.2.2 matt int fd;
60 1.2.2.2 matt int i;
61 1.2.2.2 matt
62 1.2.2.2 matt i = random() % NPIPE;
63 1.2.2.2 matt fd = fds[i][1];
64 1.2.2.2 matt #if VERBOSE
65 1.2.2.2 matt printf("[%p] write %d\n", (void *)pthread_self(), fd);
66 1.2.2.2 matt #endif
67 1.2.2.2 matt if (write(fd, buf, sizeof(buf)) == -1) {
68 1.2.2.2 matt perror("write");
69 1.2.2.2 matt abort();
70 1.2.2.2 matt }
71 1.2.2.2 matt }
72 1.2.2.2 matt
73 1.2.2.2 matt static void *
74 1.2.2.2 matt f(void *dummy)
75 1.2.2.2 matt {
76 1.2.2.2 matt
77 1.2.2.2 matt pthread_barrier_wait(&barrier);
78 1.2.2.2 matt
79 1.2.2.2 matt for (;;) {
80 1.2.2.2 matt struct timeval to;
81 1.2.2.2 matt fd_set oset;
82 1.2.2.2 matt fd_set set;
83 1.2.2.2 matt int maxfd = -1;
84 1.2.2.2 matt int nfd = 0;
85 1.2.2.2 matt int ret;
86 1.2.2.2 matt int fd;
87 1.2.2.2 matt int i;
88 1.2.2.2 matt
89 1.2.2.2 matt FD_ZERO(&set);
90 1.2.2.2 matt do {
91 1.2.2.2 matt for (i = 0; i < NPIPE; i++) {
92 1.2.2.2 matt fd = fds[i][0];
93 1.2.2.2 matt if (fd > FD_SETSIZE) {
94 1.2.2.2 matt fprintf(stderr,
95 1.2.2.2 matt "fd(%d) > FD_SETSIZE(%d)\n",
96 1.2.2.2 matt fd, FD_SETSIZE);
97 1.2.2.2 matt abort();
98 1.2.2.2 matt }
99 1.2.2.2 matt if (random() & 1) {
100 1.2.2.2 matt FD_SET(fd, &set);
101 1.2.2.2 matt if (fd > maxfd) {
102 1.2.2.2 matt maxfd = fd;
103 1.2.2.2 matt nfd++;
104 1.2.2.2 matt }
105 1.2.2.2 matt }
106 1.2.2.2 matt }
107 1.2.2.2 matt } while (nfd == 0);
108 1.2.2.2 matt memcpy(&oset, &set, sizeof(oset));
109 1.2.2.2 matt memset(&to, 0, sizeof(to));
110 1.2.2.2 matt to.tv_sec = random() % 10;
111 1.2.2.2 matt to.tv_usec = random() % 1000000;
112 1.2.2.2 matt #if VERBOSE
113 1.2.2.2 matt printf("[%p] select start to=%lu\n", (void *)pthread_self(),
114 1.2.2.2 matt (unsigned long)to.tv_sec);
115 1.2.2.2 matt #endif
116 1.2.2.2 matt ret = select(maxfd + 1, &set, NULL, NULL, &to);
117 1.2.2.2 matt #if VERBOSE
118 1.2.2.2 matt printf("[%p] select done ret=%d\n",
119 1.2.2.2 matt (void *)pthread_self(), ret);
120 1.2.2.2 matt #endif
121 1.2.2.2 matt if (ret == -1) {
122 1.2.2.2 matt perror("select");
123 1.2.2.2 matt abort();
124 1.2.2.2 matt }
125 1.2.2.2 matt if (ret > nfd) {
126 1.2.2.2 matt fprintf(stderr, "[%p] unexpected return value %d\n",
127 1.2.2.2 matt (void *)pthread_self(), ret);
128 1.2.2.2 matt abort();
129 1.2.2.2 matt }
130 1.2.2.2 matt nfd = 0;
131 1.2.2.2 matt for (fd = 0; fd <= maxfd; fd++) {
132 1.2.2.2 matt if (FD_ISSET(fd, &set)) {
133 1.2.2.2 matt char buf[1];
134 1.2.2.2 matt
135 1.2.2.2 matt #if VERBOSE
136 1.2.2.2 matt printf("[%p] read %d\n",
137 1.2.2.2 matt (void *)pthread_self(), fd);
138 1.2.2.2 matt #endif
139 1.2.2.2 matt if (!FD_ISSET(fd, &oset)) {
140 1.2.2.2 matt fprintf(stderr, "[%p] unexpected\n",
141 1.2.2.2 matt (void *)pthread_self());
142 1.2.2.2 matt abort();
143 1.2.2.2 matt }
144 1.2.2.2 matt if (read(fd, buf, sizeof(buf)) == -1) {
145 1.2.2.2 matt if (errno != EAGAIN) {
146 1.2.2.2 matt perror("read");
147 1.2.2.2 matt abort();
148 1.2.2.2 matt }
149 1.2.2.2 matt } else {
150 1.2.2.2 matt dowrite();
151 1.2.2.2 matt atomic_inc_uint(&count);
152 1.2.2.2 matt }
153 1.2.2.2 matt nfd++;
154 1.2.2.2 matt }
155 1.2.2.2 matt }
156 1.2.2.2 matt if (ret != nfd) {
157 1.2.2.2 matt fprintf(stderr, "[%p] ret(%d) != nfd(%d)\n",
158 1.2.2.2 matt (void *)pthread_self(), ret, nfd);
159 1.2.2.2 matt abort();
160 1.2.2.2 matt }
161 1.2.2.2 matt }
162 1.2.2.2 matt }
163 1.2.2.2 matt
164 1.2.2.2 matt int
165 1.2.2.2 matt main(int argc, char *argv[])
166 1.2.2.2 matt {
167 1.2.2.2 matt pthread_t pt[NTHREAD];
168 1.2.2.2 matt int i;
169 1.2.2.2 matt unsigned int secs;
170 1.2.2.2 matt
171 1.2.2.2 matt secs = atoi(argv[1]);
172 1.2.2.2 matt
173 1.2.2.2 matt for (i = 0; i < NPIPE; i++) {
174 1.2.2.2 matt if (pipe(fds[i])) {
175 1.2.2.2 matt perror("pipe");
176 1.2.2.2 matt abort();
177 1.2.2.2 matt }
178 1.2.2.2 matt if (fcntl(fds[i][0], F_SETFL, O_NONBLOCK) == -1) {
179 1.2.2.2 matt perror("fcntl");
180 1.2.2.2 matt abort();
181 1.2.2.2 matt }
182 1.2.2.2 matt }
183 1.2.2.2 matt pthread_barrier_init(&barrier, NULL, NTHREAD + 1);
184 1.2.2.2 matt for (i = 0; i < NTHREAD; i++) {
185 1.2.2.2 matt int error = pthread_create(&pt[i], NULL, f, NULL);
186 1.2.2.2 matt if (error) {
187 1.2.2.2 matt errno = error;
188 1.2.2.2 matt perror("pthread_create");
189 1.2.2.2 matt abort();
190 1.2.2.2 matt }
191 1.2.2.2 matt }
192 1.2.2.2 matt pthread_barrier_wait(&barrier);
193 1.2.2.2 matt dowrite();
194 1.2.2.2 matt dowrite();
195 1.2.2.2 matt dowrite();
196 1.2.2.2 matt dowrite();
197 1.2.2.2 matt
198 1.2.2.2 matt sleep(secs);
199 1.2.2.2 matt printf("%u / %u = %lf\n", count, secs, (double)count / secs);
200 1.2.2.2 matt exit(EXIT_SUCCESS);
201 1.2.2.2 matt }
202