kernel: scheduling fix for ARM
[minix.git] / lib / libasyn / asyn_read.c
blobb5f02a086d747738d06aa3316e921fa591241dd2
1 /* asyn_read() Author: Kees J. Bot
2 * 7 Jul 1997
3 */
4 #include "asyn.h"
5 #include <signal.h>
7 ssize_t asyn_read(asynchio_t *asyn, int fd, void *buf, size_t len)
8 /* Asynchronous read(). Try if a read can be done, if not then set a flag
9 * indicating that select(2) should look out for it. Returns like a normal
10 * read or returns -1 with errno set to EAGAIN.
13 asynfd_t *afd;
15 /* Asyn_wait() may block if this counter equals zero indicating that
16 * all of the asyn_* functions are "in progress".
18 asyn->asyn_more++;
20 if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
21 afd= &asyn->asyn_afd[fd];
23 /* If this is the first async call on this filedescriptor then
24 * remember its file flags.
26 if (!afd->afd_seen) {
27 if ((afd->afd_flags= fcntl(fd, F_GETFL)) < 0) return -1;
28 afd->afd_seen= 1;
31 /* Try to read if I/O is pending. */
32 if (afd->afd_state[SEL_READ] == PENDING) {
33 sigset_t mask;
34 ssize_t result;
35 int err;
37 sigemptyset(&mask);
38 if (sigprocmask(SIG_SETMASK, &mask, &mask) < 0) return -1;
39 (void) fcntl(fd, F_SETFL, afd->afd_flags | O_NONBLOCK);
41 /* Try the actual read. */
42 result= read(fd, buf, len);
43 err= errno;
45 (void) fcntl(fd, F_SETFL, afd->afd_flags);
46 (void) sigprocmask(SIG_SETMASK, &mask, nil);
48 errno= err;
49 if (result != -1 || errno != EAGAIN) {
50 afd->afd_state[SEL_READ]= IDLE;
51 return result;
55 /* Record this read as "waiting". */
56 afd->afd_state[SEL_READ]= WAITING;
57 FD_SET(fd, &asyn->asyn_fdset[SEL_READ]);
58 errno= EAGAIN;
59 asyn->asyn_more--;
60 return -1;