void loop_aio(int fd, void *buf) { int res; unsigned int elapsed; /* i/o context initialization */ io_context_t myctx; memset(&myctx, 0, sizeof(myctx)); if ((res = io_queue_init(maxinflight, &myctx))) io_error("io_queue_init", res); copied = 0; inflight = 0; if (opt_verbose) printf("[run %d] start\n", runid); while (copied < mycount) { struct iocb *ioq[maxsubmit]; int tosubmit = 0; unsigned long long int index; struct iocb *iocb; struct timeval tv1, tv2; /* filling a context with io queries */ while (copied + inflight + tosubmit < mycount && inflight + tosubmit < maxinflight && tosubmit < maxsubmit) { /* Simultaneous asynchronous operations using the same iocb produce undefined results. */ iocb = calloc(1, sizeof(struct iocb)); if (mode_rnd) index = (mydevsize / myiosize) * random() / RAND_MAX; else index = copied + inflight + tosubmit; if (mode_write) io_prep_pwrite(iocb, fd, buf, myiosize, index * myiosize); else io_prep_pread(iocb, fd, buf, myiosize, index * myiosize); io_set_callback(iocb, io_done); ioq[tosubmit] = iocb; tosubmit += 1; } /* if there are available slots for submitting queries, do it */ if (tosubmit) { /* submit io and check elapsed time */ gettimeofday(&tv1, NULL); if ((res = io_submit(myctx, tosubmit, ioq)) != tosubmit) { printf("only %d io submitted\n", res); io_error("io_submit write", res); } gettimeofday(&tv2, NULL); elapsed = (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000; if (elapsed > 200) printf("warning: io_submit() took %d ms, this is suspicious, maybe nr_request is too low.\n", elapsed); /* inflight io += newly submitted io */ inflight += tosubmit; } /* handle completed io events */ if ((res = io_queue_run(myctx)) < 0) io_error("io_queue_run", res); if (inflight == maxinflight || (inflight && copied + inflight == mycount)) { struct io_event event; if ((res = io_getevents(myctx, 1, 1, &event, NULL)) < 0) io_error("io_getevents", res); if (res != 1) errx(1, "no events?"); ((io_callback_t)event.obj->data)(myctx, event.obj, event.res, event.res2); } } io_queue_release(myctx); }
int main(int argc, char *const *argv) { int srcfd; struct stat st; off_t length = 0, offset = 0; io_context_t myctx; if (argc != 2 || argv[1][0] == '-') { fprintf(stderr, "Usage: aioread SOURCE"); exit(1); } if ((srcfd = open(srcname = argv[1], O_RDONLY)) < 0) { perror(srcname); exit(1); } if (fstat(srcfd, &st) < 0) { perror("fstat"); exit(1); } length = st.st_size; /* initialize state machine */ memset(&myctx, 0, sizeof(myctx)); io_queue_init(AIO_MAXIO, &myctx); tocopy = howmany(length, AIO_BLKSIZE); printf("tocopy: %ld times\n", tocopy); int i, j; for (i = 0; i < AIO_MAXIO; i ++) memset(&aiobuf[i], '\0', sizeof(struct mybuf)); int ps = getpagesize(); while (tocopy > 0) { rc; /* Submit as many reads as once as possible upto AIO_MAXIO */ int n = MIN(MIN(AIO_MAXIO - busy, AIO_MAXIO / 2), \ howmany(length - offset, AIO_BLKSIZE)); if (n > 0) { struct iocb *ioq[n]; for (i = 0; i < n; i++) { struct iocb *io = (struct iocb *) malloc(sizeof(struct iocb)); int iosize = MIN(length - offset, AIO_BLKSIZE); for (j = 0; j < AIO_MAXIO; j ++) { } char *buf; posix_memalign(&buf, ps, iosize); if (NULL == buf || NULL == io) { fprintf(stderr, "out of memory\n"); exit(1); } io_prep_pread(io, srcfd, buf, iosize, offset); io_set_callback(io, rd_done); ioq[i] = io; offset += iosize; } rc = io_submit(myctx, n, ioq); if (rc < 0) io_error("io_submit", rc); busy += n; } // Handle IO’s that have completed rc = io_queue_run(myctx); if (rc < 0) io_error("io_queue_run", rc); // if we have maximum number of i/o’s in flight // then wait for one to complete if (busy == AIO_MAXIO) { rc = io_queue_wait(myctx, NULL); if (rc < 0) io_error("io_queue_wait", rc); } } close(srcfd); exit(0); }