11 #include <sys/socket.h>
14 static struct timeval tp1,tp2;
16 static void start_timer()
18 gettimeofday(&tp1,NULL);
21 static double end_timer()
23 gettimeofday(&tp2,NULL);
24 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
25 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
28 struct aio_open_args {
36 static int aio_pipe[2];
38 static int aio_open_child(void *ptr)
40 struct aio_open_args *args = ptr;
41 args->ret = open(args->fname, args->flags, args->mode);
43 write(aio_pipe[1], &ptr, sizeof(ptr));
47 static int aio_open(const char *fname, int flags, mode_t mode)
50 struct aio_open_args *args, *a2;
54 args = malloc(sizeof(*args));
59 pid = clone(aio_open_child, stack+sizeof(stack)-32,
60 CLONE_FS|CLONE_FILES|CLONE_VM,
63 if (read(aio_pipe[0], &a2, sizeof(a2)) != sizeof(a2)) {
68 waitpid(pid, &status, __WCLONE);
79 enum aio_clone_op {AIO_CLONE_NOOP, AIO_CLONE_OPEN};
81 struct aio_clone_common {
93 struct aio_clone_common common;
96 struct aio_clone_common common;
103 static int aio_clone_wake(union aio_clone *args)
105 if (write(args->_open.common.fd1[1], &args, sizeof(args)) != sizeof(args)) {
111 static int aio_clone_finished(union aio_clone *args)
113 if (write(args->_open.common.fd2[1], &args, sizeof(args)) != sizeof(args)) {
119 static int aio_clone_wait_child(union aio_clone *args)
121 if (read(args->_open.common.fd1[0], &args, sizeof(args)) != sizeof(args)) {
127 static int aio_clone_wait_parent(union aio_clone *args)
129 if (read(args->_open.common.fd2[0], &args, sizeof(args)) != sizeof(args)) {
135 static int aio_clone_child(void *ptr)
137 union aio_clone *args = ptr;
138 while (aio_clone_wait_child(args) == 0) {
139 struct aio_clone_common *common = &args->_noop.common;
140 switch (common->op) {
145 common->ret = open(args->_open.fname,
150 if (common->ret == -1) {
151 common->error = errno;
153 if (aio_clone_finished(args) != 0) break;
158 static union aio_clone *aio_clone_start(void)
160 union aio_clone *args = calloc(1, sizeof(*args));
161 pipe(args->_noop.common.fd1);
162 pipe(args->_noop.common.fd2);
163 args->_noop.common.pid =
164 clone(aio_clone_child, args->_noop.common.stack+
165 sizeof(args->_noop.common.stack)-32,
166 CLONE_FS|CLONE_FILES|CLONE_VM,
173 static int aio_open2(const char *fname, int flags, mode_t mode)
175 static union aio_clone *args;
179 args = aio_clone_start();
182 args->_open.common.op = AIO_CLONE_OPEN;
183 args->_open.fname = fname;
184 args->_open.flags = flags;
185 args->_open.mode = mode;
187 if (aio_clone_wake(args) != 0) {
192 if (aio_clone_wait_parent(args) != 0) {
197 ret = args->_open.common.ret;
199 errno = args->_open.common.error;
206 static int aio_noop(const char *fname, int flags, mode_t mode)
208 static union aio_clone *args;
212 args = aio_clone_start();
215 args->_noop.common.op = AIO_CLONE_NOOP;
217 if (aio_clone_wake(args) != 0) {
222 if (aio_clone_wait_parent(args) != 0) {
227 ret = args->_open.common.ret;
229 errno = args->_open.common.error;
236 static void run_test(const char *name, int (*fn)(const char *, int, mode_t))
238 const char *fname = "test.dat";
245 while (end_timer() < timeout) {
246 int fd = fn(fname, O_CREAT|O_TRUNC|O_RDWR, 0600);
251 if (fd != 0) close(fd);
255 printf("%.1f usec/op (%s)\n", 1.0e6*end_timer()/count, name);
263 run_test("aio_open2", aio_open2);
265 run_test("noop", aio_noop);
267 run_test("aio_open", aio_open);
268 run_test("open", open);
269 run_test("aio_open2", aio_open2);
271 run_test("aio_open", aio_open);
272 run_test("open", open);
273 run_test("aio_open2", aio_open2);