-
Notifications
You must be signed in to change notification settings - Fork 0
/
async.c
62 lines (56 loc) · 1.73 KB
/
async.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* CS 533 Project
* Asynchronous I/O
* Naomi Dickerson
*/
#include <aio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include "scheduler.h"
ssize_t read_wrap(int fd, void * buf, size_t count) {
struct aiocb io_ctl;
// man page recommends we 0 out the aiocb buffer
memset(&io_ctl, 0, sizeof(struct aiocb));
// if file is seekable, set offset value
off_t offset;
offset = lseek(fd, 0, SEEK_CUR);
// if there is an error seeking, set offset to 0. Don't
// bother returning this error, as it's perfectly acceptable
// to read from stdin or a pipe, which doesn't allow seeking
if (offset == -1) {
offset = 0;
errno = 0;
}
// initialize the fields of the aiocb
io_ctl.aio_fildes = fd;
io_ctl.aio_buf = buf;
io_ctl.aio_nbytes = count;
io_ctl.aio_offset = offset;
io_ctl.aio_reqprio = 0;
io_ctl.aio_sigevent.sigev_notify = SIGEV_NONE;
// now perform read
int ret;
ret = aio_read(&io_ctl);
if (ret == -1) {
// Leaving it up to the program to handle a read failure
return ret;
}
// Poll until read is complete, yielding if still in progress
int status;
while ((status = aio_error(&io_ctl)) == EINPROGRESS) {
yield();
}
// At this point the read has either completed successfully or
// has an error to return
ret = aio_return(&io_ctl);
// Update the offset in the file descriptor if the read
// terminated successfully
if (ret >= 0) {
lseek(fd, ret, SEEK_CUR);
// If we reach this point, there was no error from the read
// or return, but lseek might have caused an error we don't
// care about
errno = 0;
}
return ret;
}