]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - tools/regression/aio/kqueue/aio_kqueue.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / tools / regression / aio / kqueue / aio_kqueue.c
1 /*-
2  * Copyright (C) 2005 IronPort Systems, Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27
28 /* 
29  * Note: it is a good idea to run this against a physical drive to 
30  * exercise the physio fast path (ie. aio_kqueue /dev/<something safe>)
31  */
32
33 #include <aio.h>
34 #include <fcntl.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <sys/event.h>
40 #include <sys/time.h>
41 #include <unistd.h>
42
43 #define PATH_TEMPLATE   "/tmp/aio.XXXXXXXXXX"
44
45 #define MAX 128
46 #define MAX_RUNS 300
47 /* #define DEBUG */
48
49 main(int argc, char *argv[]){
50         int fd;
51         struct aiocb *iocb[MAX], *kq_iocb;
52         int i, result, run, error, j;
53         char buffer[32768];
54         int kq = kqueue();
55         struct kevent ke, kq_returned;
56         struct timespec ts;
57         int cancel, pending, tmp_file = 0, failed = 0;
58         char *file, pathname[sizeof(PATH_TEMPLATE)-1];
59
60         if (kq < 0) {
61                 perror("No kqeueue\n");
62                 exit(1);
63         }
64
65         if (argc == 1) { 
66                 strcpy(pathname, PATH_TEMPLATE);
67                 fd = mkstemp(pathname);
68                 file = pathname;
69                 tmp_file = 1;
70         } else {
71                 file = argv[1];
72                 fd = open(file, O_RDWR|O_CREAT, 0666);
73         }
74         if (fd < 0){
75                 fprintf(stderr, "Can't open %s\n", file);
76                 perror("");
77                 exit(1);
78         }
79
80         for (run = 0; run < MAX_RUNS; run++){
81 #ifdef DEBUG
82                 printf("Run %d\n", run);
83 #endif
84                 for(i = 0; i < MAX; i++) {
85                         iocb[i] = (struct aiocb *)malloc(sizeof(struct aiocb));
86                         bzero(iocb[i], sizeof(struct aiocb));
87                 }
88                 
89                 pending = 0;    
90                 for(i = 0; i < MAX; i++) {
91                         pending++;
92                         iocb[i]->aio_nbytes = sizeof(buffer);
93                         iocb[i]->aio_buf = buffer;
94                         iocb[i]->aio_fildes = fd;
95                         iocb[i]->aio_offset = iocb[i]->aio_nbytes * i * run;
96                         
97                         iocb[i]->aio_sigevent.sigev_notify_kqueue = kq;
98                         iocb[i]->aio_sigevent.sigev_value.sival_ptr = iocb[i];
99                         iocb[i]->aio_sigevent.sigev_notify = SIGEV_KEVENT;
100                         
101                         result = aio_write(iocb[i]);
102                         if (result != 0) {
103                                 perror("aio_write");
104                                 printf("Result %d iteration %d\n",result, i);
105                                 exit(1);
106                         }
107 #ifdef DEBUG
108                         printf("WRITE %d is at %p\n", i, iocb[i]);
109 #endif
110                         result = rand();
111                         if (result < RAND_MAX/32) {
112                                 if (result > RAND_MAX/64) {
113                                         result = aio_cancel(fd, iocb[i]);
114 #ifdef DEBUG
115                                         printf("Cancel %d %p result %d\n", i, iocb[i], result);
116 #endif
117                                         if (result == AIO_CANCELED) {
118                                                 aio_return(iocb[i]);
119                                                 iocb[i]=NULL;
120                                                 pending--;
121                                         }
122                                 }
123                         }
124                 }
125                 cancel = MAX - pending;
126                 
127                 i = 0;
128                 while(pending) {
129                         for(;;) {
130                                 bzero(&ke, sizeof(ke));
131                                 bzero(&kq_returned, sizeof(ke));
132                                 ts.tv_sec = 0;
133                                 ts.tv_nsec = 1;
134                                 result = kevent(kq, NULL, 0, 
135                                                 &kq_returned, 1, &ts);
136                                 error = errno;
137                                 if (result < 0) {
138                                         perror("kevent error: ");
139                                 }
140                                 kq_iocb = kq_returned.udata;
141 #ifdef DEBUG
142                                 printf("kevent %d %d errno %d return.ident %p "
143                                        "return.data %p return.udata %p %p\n", 
144                                        i, result, error, 
145                                        kq_returned.ident, kq_returned.data, 
146                                        kq_returned.udata, 
147                                        kq_iocb);
148 #endif
149                                 
150                                 if(kq_iocb)
151                                         break;
152 #ifdef DEBUG
153                                 printf("Try again left %d out of %d %d\n",pending, MAX, cancel);
154 #endif
155                         }                       
156                         
157                         for(j = 0; j < MAX; j++) {
158                                 if (iocb[j] == kq_iocb) {
159                                         break;
160                                 }
161                         }
162 #ifdef DEBUG
163                         printf("kq_iocb %p\n", kq_iocb);
164                         
165                         printf("Error Result for %d is %d pending %d\n", j, result, pending);
166 #endif
167                         result = aio_return(kq_iocb);
168 #ifdef DEBUG
169                         printf("Return Result for %d is %d\n", j, result);
170                         printf("\n");
171 #endif
172                         if (result != sizeof(buffer)) {
173                                 printf("FAIL: run %d, operation %d, result %d (errno=%d) should be %d\n", run, pending, result, errno, sizeof(buffer));
174                                 failed = 1;
175                         } else {
176                                 printf("PASS: run %d, left %d\n", run, pending - 1);
177                         }
178
179                         free(kq_iocb);
180                         iocb[j] = NULL;
181                         pending--;
182                         i++;
183                 }       
184         }
185
186         if (tmp_file) {
187                 unlink(pathname);
188         }
189
190         if (failed) {
191                 printf("FAIL: Atleast one\n");
192                 exit(1);
193         } else {
194                 printf("PASS: All\n");
195                 exit(0);
196         }
197 }