| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 #include <aio.h> | 
|  | 2 #include <errno.h> | 
|  | 3 #include <unistd.h> | 
|  | 4 #include <string.h> | 
|  | 5 #include "pthread_impl.h" | 
|  | 6 #include "libc.h" | 
|  | 7 | 
|  | 8 struct lio_state { | 
|  | 9         struct sigevent *sev; | 
|  | 10         int cnt; | 
|  | 11         struct aiocb *cbs[]; | 
|  | 12 }; | 
|  | 13 | 
|  | 14 static int lio_wait(struct lio_state *st) | 
|  | 15 { | 
|  | 16         int i, err, got_err = 0; | 
|  | 17         int cnt = st->cnt; | 
|  | 18         struct aiocb **cbs = st->cbs; | 
|  | 19 | 
|  | 20         for (;;) { | 
|  | 21                 for (i=0; i<cnt; i++) { | 
|  | 22                         if (!cbs[i]) continue; | 
|  | 23                         err = aio_error(cbs[i]); | 
|  | 24                         if (err==EINPROGRESS) | 
|  | 25                                 break; | 
|  | 26                         if (err) got_err=1; | 
|  | 27                         cbs[i] = 0; | 
|  | 28                 } | 
|  | 29                 if (i==cnt) { | 
|  | 30                         if (got_err) { | 
|  | 31                                 errno = EIO; | 
|  | 32                                 return -1; | 
|  | 33                         } | 
|  | 34                         return 0; | 
|  | 35                 } | 
|  | 36                 if (aio_suspend((void *)cbs, cnt, 0)) | 
|  | 37                         return -1; | 
|  | 38         } | 
|  | 39 } | 
|  | 40 | 
|  | 41 static void notify_signal(struct sigevent *sev) | 
|  | 42 { | 
|  | 43         siginfo_t si = { | 
|  | 44                 .si_signo = sev->sigev_signo, | 
|  | 45                 .si_value = sev->sigev_value, | 
|  | 46                 .si_code = SI_ASYNCIO, | 
|  | 47                 .si_pid = getpid(), | 
|  | 48                 .si_uid = getuid() | 
|  | 49         }; | 
|  | 50         __syscall(SYS_rt_sigqueueinfo, si.si_pid, si.si_signo, &si); | 
|  | 51 } | 
|  | 52 | 
|  | 53 static void *wait_thread(void *p) | 
|  | 54 { | 
|  | 55         struct lio_state *st = p; | 
|  | 56         struct sigevent *sev = st->sev; | 
|  | 57         lio_wait(st); | 
|  | 58         free(st); | 
|  | 59         switch (sev->sigev_notify) { | 
|  | 60         case SIGEV_SIGNAL: | 
|  | 61                 notify_signal(sev); | 
|  | 62                 break; | 
|  | 63         case SIGEV_THREAD: | 
|  | 64                 sev->sigev_notify_function(sev->sigev_value); | 
|  | 65                 break; | 
|  | 66         } | 
|  | 67         return 0; | 
|  | 68 } | 
|  | 69 | 
|  | 70 int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, st
     ruct sigevent *restrict sev) | 
|  | 71 { | 
|  | 72         int i, ret; | 
|  | 73         struct lio_state *st=0; | 
|  | 74 | 
|  | 75         if (cnt < 0) { | 
|  | 76                 errno = EINVAL; | 
|  | 77                 return -1; | 
|  | 78         } | 
|  | 79 | 
|  | 80         if (mode == LIO_WAIT || (sev && sev->sigev_notify != SIGEV_NONE)) { | 
|  | 81                 if (!(st = malloc(sizeof *st + cnt*sizeof *cbs))) { | 
|  | 82                         errno = EAGAIN; | 
|  | 83                         return -1; | 
|  | 84                 } | 
|  | 85                 st->cnt = cnt; | 
|  | 86                 st->sev = sev; | 
|  | 87                 memcpy(st->cbs, (void*) cbs, cnt*sizeof *cbs); | 
|  | 88         } | 
|  | 89 | 
|  | 90         for (i=0; i<cnt; i++) { | 
|  | 91                 if (!cbs[i]) continue; | 
|  | 92                 switch (cbs[i]->aio_lio_opcode) { | 
|  | 93                 case LIO_READ: | 
|  | 94                         ret = aio_read(cbs[i]); | 
|  | 95                         break; | 
|  | 96                 case LIO_WRITE: | 
|  | 97                         ret = aio_write(cbs[i]); | 
|  | 98                         break; | 
|  | 99                 default: | 
|  | 100                         continue; | 
|  | 101                 } | 
|  | 102                 if (ret) { | 
|  | 103                         free(st); | 
|  | 104                         errno = EAGAIN; | 
|  | 105                         return -1; | 
|  | 106                 } | 
|  | 107         } | 
|  | 108 | 
|  | 109         if (mode == LIO_WAIT) { | 
|  | 110                 ret = lio_wait(st); | 
|  | 111                 free(st); | 
|  | 112                 return ret; | 
|  | 113         } | 
|  | 114 | 
|  | 115         if (st) { | 
|  | 116                 pthread_attr_t a; | 
|  | 117                 sigset_t set; | 
|  | 118                 pthread_t td; | 
|  | 119 | 
|  | 120                 if (sev->sigev_notify == SIGEV_THREAD) { | 
|  | 121                         if (sev->sigev_notify_attributes) | 
|  | 122                                 a = *sev->sigev_notify_attributes; | 
|  | 123                         else | 
|  | 124                                 pthread_attr_init(&a); | 
|  | 125                 } else { | 
|  | 126                         pthread_attr_init(&a); | 
|  | 127                         pthread_attr_setstacksize(&a, PAGE_SIZE); | 
|  | 128                         pthread_attr_setguardsize(&a, 0); | 
|  | 129                 } | 
|  | 130                 pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); | 
|  | 131                 sigfillset(&set); | 
|  | 132                 pthread_sigmask(SIG_BLOCK, &set, &set); | 
|  | 133                 if (pthread_create(&td, &a, wait_thread, st)) { | 
|  | 134                         free(st); | 
|  | 135                         errno = EAGAIN; | 
|  | 136                         return -1; | 
|  | 137                 } | 
|  | 138                 pthread_sigmask(SIG_SETMASK, &set, 0); | 
|  | 139         } | 
|  | 140 | 
|  | 141         return 0; | 
|  | 142 } | 
|  | 143 | 
|  | 144 LFS64(lio_listio); | 
| OLD | NEW | 
|---|