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