1570af302Sopenharmony_ci#include <aio.h> 2570af302Sopenharmony_ci#include <pthread.h> 3570af302Sopenharmony_ci#include <semaphore.h> 4570af302Sopenharmony_ci#include <limits.h> 5570af302Sopenharmony_ci#include <errno.h> 6570af302Sopenharmony_ci#include <unistd.h> 7570af302Sopenharmony_ci#include <stdlib.h> 8570af302Sopenharmony_ci#include <sys/auxv.h> 9570af302Sopenharmony_ci#include "syscall.h" 10570af302Sopenharmony_ci#include "atomic.h" 11570af302Sopenharmony_ci#include "pthread_impl.h" 12570af302Sopenharmony_ci#include "aio_impl.h" 13570af302Sopenharmony_ci 14570af302Sopenharmony_ci#define malloc __libc_malloc 15570af302Sopenharmony_ci#define calloc __libc_calloc 16570af302Sopenharmony_ci#define realloc __libc_realloc 17570af302Sopenharmony_ci#define free __libc_free 18570af302Sopenharmony_ci 19570af302Sopenharmony_ci/* The following is a threads-based implementation of AIO with minimal 20570af302Sopenharmony_ci * dependence on implementation details. Most synchronization is 21570af302Sopenharmony_ci * performed with pthread primitives, but atomics and futex operations 22570af302Sopenharmony_ci * are used for notification in a couple places where the pthread 23570af302Sopenharmony_ci * primitives would be inefficient or impractical. 24570af302Sopenharmony_ci * 25570af302Sopenharmony_ci * For each fd with outstanding aio operations, an aio_queue structure 26570af302Sopenharmony_ci * is maintained. These are reference-counted and destroyed by the last 27570af302Sopenharmony_ci * aio worker thread to exit. Accessing any member of the aio_queue 28570af302Sopenharmony_ci * structure requires a lock on the aio_queue. Adding and removing aio 29570af302Sopenharmony_ci * queues themselves requires a write lock on the global map object, 30570af302Sopenharmony_ci * a 4-level table mapping file descriptor numbers to aio queues. A 31570af302Sopenharmony_ci * read lock on the map is used to obtain locks on existing queues by 32570af302Sopenharmony_ci * excluding destruction of the queue by a different thread while it is 33570af302Sopenharmony_ci * being locked. 34570af302Sopenharmony_ci * 35570af302Sopenharmony_ci * Each aio queue has a list of active threads/operations. Presently there 36570af302Sopenharmony_ci * is a one to one relationship between threads and operations. The only 37570af302Sopenharmony_ci * members of the aio_thread structure which are accessed by other threads 38570af302Sopenharmony_ci * are the linked list pointers, op (which is immutable), running (which 39570af302Sopenharmony_ci * is updated atomically), and err (which is synchronized via running), 40570af302Sopenharmony_ci * so no locking is necessary. Most of the other other members are used 41570af302Sopenharmony_ci * for sharing data between the main flow of execution and cancellation 42570af302Sopenharmony_ci * cleanup handler. 43570af302Sopenharmony_ci * 44570af302Sopenharmony_ci * Taking any aio locks requires having all signals blocked. This is 45570af302Sopenharmony_ci * necessary because aio_cancel is needed by close, and close is required 46570af302Sopenharmony_ci * to be async-signal safe. All aio worker threads run with all signals 47570af302Sopenharmony_ci * blocked permanently. 48570af302Sopenharmony_ci */ 49570af302Sopenharmony_ci 50570af302Sopenharmony_cistruct aio_thread { 51570af302Sopenharmony_ci pthread_t td; 52570af302Sopenharmony_ci struct aiocb *cb; 53570af302Sopenharmony_ci struct aio_thread *next, *prev; 54570af302Sopenharmony_ci struct aio_queue *q; 55570af302Sopenharmony_ci volatile int running; 56570af302Sopenharmony_ci int err, op; 57570af302Sopenharmony_ci ssize_t ret; 58570af302Sopenharmony_ci}; 59570af302Sopenharmony_ci 60570af302Sopenharmony_cistruct aio_queue { 61570af302Sopenharmony_ci int fd, seekable, append, ref, init; 62570af302Sopenharmony_ci pthread_mutex_t lock; 63570af302Sopenharmony_ci pthread_cond_t cond; 64570af302Sopenharmony_ci struct aio_thread *head; 65570af302Sopenharmony_ci}; 66570af302Sopenharmony_ci 67570af302Sopenharmony_cistruct aio_args { 68570af302Sopenharmony_ci struct aiocb *cb; 69570af302Sopenharmony_ci struct aio_queue *q; 70570af302Sopenharmony_ci int op; 71570af302Sopenharmony_ci sem_t sem; 72570af302Sopenharmony_ci}; 73570af302Sopenharmony_ci 74570af302Sopenharmony_cistatic pthread_rwlock_t maplock = PTHREAD_RWLOCK_INITIALIZER; 75570af302Sopenharmony_cistatic struct aio_queue *****map; 76570af302Sopenharmony_cistatic volatile int aio_fd_cnt; 77570af302Sopenharmony_civolatile int __aio_fut; 78570af302Sopenharmony_ci 79570af302Sopenharmony_cistatic size_t io_thread_stack_size; 80570af302Sopenharmony_ci 81570af302Sopenharmony_ci#define MAX(a,b) ((a)>(b) ? (a) : (b)) 82570af302Sopenharmony_ci 83570af302Sopenharmony_cistatic struct aio_queue *__aio_get_queue(int fd, int need) 84570af302Sopenharmony_ci{ 85570af302Sopenharmony_ci if (fd < 0) { 86570af302Sopenharmony_ci errno = EBADF; 87570af302Sopenharmony_ci return 0; 88570af302Sopenharmony_ci } 89570af302Sopenharmony_ci int a=fd>>24; 90570af302Sopenharmony_ci unsigned char b=fd>>16, c=fd>>8, d=fd; 91570af302Sopenharmony_ci struct aio_queue *q = 0; 92570af302Sopenharmony_ci pthread_rwlock_rdlock(&maplock); 93570af302Sopenharmony_ci if ((!map || !map[a] || !map[a][b] || !map[a][b][c] || !(q=map[a][b][c][d])) && need) { 94570af302Sopenharmony_ci pthread_rwlock_unlock(&maplock); 95570af302Sopenharmony_ci if (fcntl(fd, F_GETFD) < 0) return 0; 96570af302Sopenharmony_ci pthread_rwlock_wrlock(&maplock); 97570af302Sopenharmony_ci if (!io_thread_stack_size) { 98570af302Sopenharmony_ci unsigned long val = __getauxval(AT_MINSIGSTKSZ); 99570af302Sopenharmony_ci io_thread_stack_size = MAX(MINSIGSTKSZ+2048, val+512); 100570af302Sopenharmony_ci } 101570af302Sopenharmony_ci if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24); 102570af302Sopenharmony_ci if (!map) goto out; 103570af302Sopenharmony_ci if (!map[a]) map[a] = calloc(sizeof **map, 256); 104570af302Sopenharmony_ci if (!map[a]) goto out; 105570af302Sopenharmony_ci if (!map[a][b]) map[a][b] = calloc(sizeof ***map, 256); 106570af302Sopenharmony_ci if (!map[a][b]) goto out; 107570af302Sopenharmony_ci if (!map[a][b][c]) map[a][b][c] = calloc(sizeof ****map, 256); 108570af302Sopenharmony_ci if (!map[a][b][c]) goto out; 109570af302Sopenharmony_ci if (!(q = map[a][b][c][d])) { 110570af302Sopenharmony_ci map[a][b][c][d] = q = calloc(sizeof *****map, 1); 111570af302Sopenharmony_ci if (q) { 112570af302Sopenharmony_ci q->fd = fd; 113570af302Sopenharmony_ci pthread_mutex_init(&q->lock, 0); 114570af302Sopenharmony_ci pthread_cond_init(&q->cond, 0); 115570af302Sopenharmony_ci a_inc(&aio_fd_cnt); 116570af302Sopenharmony_ci } 117570af302Sopenharmony_ci } 118570af302Sopenharmony_ci } 119570af302Sopenharmony_ci if (q) pthread_mutex_lock(&q->lock); 120570af302Sopenharmony_ciout: 121570af302Sopenharmony_ci pthread_rwlock_unlock(&maplock); 122570af302Sopenharmony_ci return q; 123570af302Sopenharmony_ci} 124570af302Sopenharmony_ci 125570af302Sopenharmony_cistatic void __aio_unref_queue(struct aio_queue *q) 126570af302Sopenharmony_ci{ 127570af302Sopenharmony_ci if (q->ref > 1) { 128570af302Sopenharmony_ci q->ref--; 129570af302Sopenharmony_ci pthread_mutex_unlock(&q->lock); 130570af302Sopenharmony_ci return; 131570af302Sopenharmony_ci } 132570af302Sopenharmony_ci 133570af302Sopenharmony_ci /* This is potentially the last reference, but a new reference 134570af302Sopenharmony_ci * may arrive since we cannot free the queue object without first 135570af302Sopenharmony_ci * taking the maplock, which requires releasing the queue lock. */ 136570af302Sopenharmony_ci pthread_mutex_unlock(&q->lock); 137570af302Sopenharmony_ci pthread_rwlock_wrlock(&maplock); 138570af302Sopenharmony_ci pthread_mutex_lock(&q->lock); 139570af302Sopenharmony_ci if (q->ref == 1) { 140570af302Sopenharmony_ci int fd=q->fd; 141570af302Sopenharmony_ci int a=fd>>24; 142570af302Sopenharmony_ci unsigned char b=fd>>16, c=fd>>8, d=fd; 143570af302Sopenharmony_ci map[a][b][c][d] = 0; 144570af302Sopenharmony_ci a_dec(&aio_fd_cnt); 145570af302Sopenharmony_ci pthread_rwlock_unlock(&maplock); 146570af302Sopenharmony_ci pthread_mutex_unlock(&q->lock); 147570af302Sopenharmony_ci free(q); 148570af302Sopenharmony_ci } else { 149570af302Sopenharmony_ci q->ref--; 150570af302Sopenharmony_ci pthread_rwlock_unlock(&maplock); 151570af302Sopenharmony_ci pthread_mutex_unlock(&q->lock); 152570af302Sopenharmony_ci } 153570af302Sopenharmony_ci} 154570af302Sopenharmony_ci 155570af302Sopenharmony_cistatic void cleanup(void *ctx) 156570af302Sopenharmony_ci{ 157570af302Sopenharmony_ci struct aio_thread *at = ctx; 158570af302Sopenharmony_ci struct aio_queue *q = at->q; 159570af302Sopenharmony_ci struct aiocb *cb = at->cb; 160570af302Sopenharmony_ci struct sigevent sev = cb->aio_sigevent; 161570af302Sopenharmony_ci 162570af302Sopenharmony_ci /* There are four potential types of waiters we could need to wake: 163570af302Sopenharmony_ci * 1. Callers of aio_cancel/close. 164570af302Sopenharmony_ci * 2. Callers of aio_suspend with a single aiocb. 165570af302Sopenharmony_ci * 3. Callers of aio_suspend with a list. 166570af302Sopenharmony_ci * 4. AIO worker threads waiting for sequenced operations. 167570af302Sopenharmony_ci * Types 1-3 are notified via atomics/futexes, mainly for AS-safety 168570af302Sopenharmony_ci * considerations. Type 4 is notified later via a cond var. */ 169570af302Sopenharmony_ci 170570af302Sopenharmony_ci cb->__ret = at->ret; 171570af302Sopenharmony_ci if (a_swap(&at->running, 0) < 0) 172570af302Sopenharmony_ci __wake(&at->running, -1, 1); 173570af302Sopenharmony_ci if (a_swap(&cb->__err, at->err) != EINPROGRESS) 174570af302Sopenharmony_ci __wake(&cb->__err, -1, 1); 175570af302Sopenharmony_ci if (a_swap(&__aio_fut, 0)) 176570af302Sopenharmony_ci __wake(&__aio_fut, -1, 1); 177570af302Sopenharmony_ci 178570af302Sopenharmony_ci pthread_mutex_lock(&q->lock); 179570af302Sopenharmony_ci 180570af302Sopenharmony_ci if (at->next) at->next->prev = at->prev; 181570af302Sopenharmony_ci if (at->prev) at->prev->next = at->next; 182570af302Sopenharmony_ci else q->head = at->next; 183570af302Sopenharmony_ci 184570af302Sopenharmony_ci /* Signal aio worker threads waiting for sequenced operations. */ 185570af302Sopenharmony_ci pthread_cond_broadcast(&q->cond); 186570af302Sopenharmony_ci 187570af302Sopenharmony_ci __aio_unref_queue(q); 188570af302Sopenharmony_ci 189570af302Sopenharmony_ci if (sev.sigev_notify == SIGEV_SIGNAL) { 190570af302Sopenharmony_ci siginfo_t si = { 191570af302Sopenharmony_ci .si_signo = sev.sigev_signo, 192570af302Sopenharmony_ci .si_value = sev.sigev_value, 193570af302Sopenharmony_ci .si_code = SI_ASYNCIO, 194570af302Sopenharmony_ci .si_pid = getpid(), 195570af302Sopenharmony_ci .si_uid = getuid() 196570af302Sopenharmony_ci }; 197570af302Sopenharmony_ci __syscall(SYS_rt_sigqueueinfo, si.si_pid, si.si_signo, &si); 198570af302Sopenharmony_ci } 199570af302Sopenharmony_ci if (sev.sigev_notify == SIGEV_THREAD) { 200570af302Sopenharmony_ci#ifdef FEATURE_PTHREAD_CANCEL 201570af302Sopenharmony_ci a_store(&__pthread_self()->cancel, 0); 202570af302Sopenharmony_ci#endif 203570af302Sopenharmony_ci sev.sigev_notify_function(sev.sigev_value); 204570af302Sopenharmony_ci } 205570af302Sopenharmony_ci} 206570af302Sopenharmony_ci 207570af302Sopenharmony_cistatic void *io_thread_func(void *ctx) 208570af302Sopenharmony_ci{ 209570af302Sopenharmony_ci struct aio_thread at, *p; 210570af302Sopenharmony_ci 211570af302Sopenharmony_ci struct aio_args *args = ctx; 212570af302Sopenharmony_ci struct aiocb *cb = args->cb; 213570af302Sopenharmony_ci int fd = cb->aio_fildes; 214570af302Sopenharmony_ci int op = args->op; 215570af302Sopenharmony_ci void *buf = (void *)cb->aio_buf; 216570af302Sopenharmony_ci size_t len = cb->aio_nbytes; 217570af302Sopenharmony_ci off_t off = cb->aio_offset; 218570af302Sopenharmony_ci 219570af302Sopenharmony_ci struct aio_queue *q = args->q; 220570af302Sopenharmony_ci ssize_t ret; 221570af302Sopenharmony_ci 222570af302Sopenharmony_ci pthread_mutex_lock(&q->lock); 223570af302Sopenharmony_ci sem_post(&args->sem); 224570af302Sopenharmony_ci 225570af302Sopenharmony_ci at.op = op; 226570af302Sopenharmony_ci at.running = 1; 227570af302Sopenharmony_ci at.ret = -1; 228570af302Sopenharmony_ci at.err = ECANCELED; 229570af302Sopenharmony_ci at.q = q; 230570af302Sopenharmony_ci at.td = __pthread_self(); 231570af302Sopenharmony_ci at.cb = cb; 232570af302Sopenharmony_ci at.prev = 0; 233570af302Sopenharmony_ci if ((at.next = q->head)) at.next->prev = &at; 234570af302Sopenharmony_ci q->head = &at; 235570af302Sopenharmony_ci 236570af302Sopenharmony_ci if (!q->init) { 237570af302Sopenharmony_ci int seekable = lseek(fd, 0, SEEK_CUR) >= 0; 238570af302Sopenharmony_ci q->seekable = seekable; 239570af302Sopenharmony_ci q->append = !seekable || (fcntl(fd, F_GETFL) & O_APPEND); 240570af302Sopenharmony_ci q->init = 1; 241570af302Sopenharmony_ci } 242570af302Sopenharmony_ci 243570af302Sopenharmony_ci pthread_cleanup_push(cleanup, &at); 244570af302Sopenharmony_ci 245570af302Sopenharmony_ci /* Wait for sequenced operations. */ 246570af302Sopenharmony_ci if (op!=LIO_READ && (op!=LIO_WRITE || q->append)) { 247570af302Sopenharmony_ci for (;;) { 248570af302Sopenharmony_ci for (p=at.next; p && p->op!=LIO_WRITE; p=p->next); 249570af302Sopenharmony_ci if (!p) break; 250570af302Sopenharmony_ci pthread_cond_wait(&q->cond, &q->lock); 251570af302Sopenharmony_ci } 252570af302Sopenharmony_ci } 253570af302Sopenharmony_ci 254570af302Sopenharmony_ci pthread_mutex_unlock(&q->lock); 255570af302Sopenharmony_ci 256570af302Sopenharmony_ci switch (op) { 257570af302Sopenharmony_ci case LIO_WRITE: 258570af302Sopenharmony_ci ret = q->append ? write(fd, buf, len) : pwrite(fd, buf, len, off); 259570af302Sopenharmony_ci break; 260570af302Sopenharmony_ci case LIO_READ: 261570af302Sopenharmony_ci ret = !q->seekable ? read(fd, buf, len) : pread(fd, buf, len, off); 262570af302Sopenharmony_ci break; 263570af302Sopenharmony_ci case O_SYNC: 264570af302Sopenharmony_ci ret = fsync(fd); 265570af302Sopenharmony_ci break; 266570af302Sopenharmony_ci case O_DSYNC: 267570af302Sopenharmony_ci ret = fdatasync(fd); 268570af302Sopenharmony_ci break; 269570af302Sopenharmony_ci } 270570af302Sopenharmony_ci at.ret = ret; 271570af302Sopenharmony_ci at.err = ret<0 ? errno : 0; 272570af302Sopenharmony_ci 273570af302Sopenharmony_ci pthread_cleanup_pop(1); 274570af302Sopenharmony_ci 275570af302Sopenharmony_ci return 0; 276570af302Sopenharmony_ci} 277570af302Sopenharmony_ci 278570af302Sopenharmony_cistatic int submit(struct aiocb *cb, int op) 279570af302Sopenharmony_ci{ 280570af302Sopenharmony_ci int ret = 0; 281570af302Sopenharmony_ci pthread_attr_t a; 282570af302Sopenharmony_ci sigset_t allmask, origmask; 283570af302Sopenharmony_ci pthread_t td; 284570af302Sopenharmony_ci struct aio_queue *q = __aio_get_queue(cb->aio_fildes, 1); 285570af302Sopenharmony_ci struct aio_args args = { .cb = cb, .op = op, .q = q }; 286570af302Sopenharmony_ci sem_init(&args.sem, 0, 0); 287570af302Sopenharmony_ci 288570af302Sopenharmony_ci if (!q) { 289570af302Sopenharmony_ci if (errno != EBADF) errno = EAGAIN; 290570af302Sopenharmony_ci cb->__ret = -1; 291570af302Sopenharmony_ci cb->__err = errno; 292570af302Sopenharmony_ci return -1; 293570af302Sopenharmony_ci } 294570af302Sopenharmony_ci q->ref++; 295570af302Sopenharmony_ci pthread_mutex_unlock(&q->lock); 296570af302Sopenharmony_ci 297570af302Sopenharmony_ci if (cb->aio_sigevent.sigev_notify == SIGEV_THREAD) { 298570af302Sopenharmony_ci if (cb->aio_sigevent.sigev_notify_attributes) 299570af302Sopenharmony_ci a = *cb->aio_sigevent.sigev_notify_attributes; 300570af302Sopenharmony_ci else 301570af302Sopenharmony_ci pthread_attr_init(&a); 302570af302Sopenharmony_ci } else { 303570af302Sopenharmony_ci pthread_attr_init(&a); 304570af302Sopenharmony_ci pthread_attr_setstacksize(&a, io_thread_stack_size); 305570af302Sopenharmony_ci pthread_attr_setguardsize(&a, 0); 306570af302Sopenharmony_ci } 307570af302Sopenharmony_ci pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); 308570af302Sopenharmony_ci sigfillset(&allmask); 309570af302Sopenharmony_ci pthread_sigmask(SIG_BLOCK, &allmask, &origmask); 310570af302Sopenharmony_ci cb->__err = EINPROGRESS; 311570af302Sopenharmony_ci if (pthread_create(&td, &a, io_thread_func, &args)) { 312570af302Sopenharmony_ci pthread_mutex_lock(&q->lock); 313570af302Sopenharmony_ci __aio_unref_queue(q); 314570af302Sopenharmony_ci cb->__err = errno = EAGAIN; 315570af302Sopenharmony_ci cb->__ret = ret = -1; 316570af302Sopenharmony_ci } 317570af302Sopenharmony_ci pthread_sigmask(SIG_SETMASK, &origmask, 0); 318570af302Sopenharmony_ci 319570af302Sopenharmony_ci if (!ret) { 320570af302Sopenharmony_ci while (sem_wait(&args.sem)); 321570af302Sopenharmony_ci } 322570af302Sopenharmony_ci 323570af302Sopenharmony_ci return ret; 324570af302Sopenharmony_ci} 325570af302Sopenharmony_ci 326570af302Sopenharmony_ciint aio_read(struct aiocb *cb) 327570af302Sopenharmony_ci{ 328570af302Sopenharmony_ci return submit(cb, LIO_READ); 329570af302Sopenharmony_ci} 330570af302Sopenharmony_ci 331570af302Sopenharmony_ciint aio_write(struct aiocb *cb) 332570af302Sopenharmony_ci{ 333570af302Sopenharmony_ci return submit(cb, LIO_WRITE); 334570af302Sopenharmony_ci} 335570af302Sopenharmony_ci 336570af302Sopenharmony_ciint aio_fsync(int op, struct aiocb *cb) 337570af302Sopenharmony_ci{ 338570af302Sopenharmony_ci if (op != O_SYNC && op != O_DSYNC) { 339570af302Sopenharmony_ci errno = EINVAL; 340570af302Sopenharmony_ci return -1; 341570af302Sopenharmony_ci } 342570af302Sopenharmony_ci return submit(cb, op); 343570af302Sopenharmony_ci} 344570af302Sopenharmony_ci 345570af302Sopenharmony_cissize_t aio_return(struct aiocb *cb) 346570af302Sopenharmony_ci{ 347570af302Sopenharmony_ci return cb->__ret; 348570af302Sopenharmony_ci} 349570af302Sopenharmony_ci 350570af302Sopenharmony_ciint aio_error(const struct aiocb *cb) 351570af302Sopenharmony_ci{ 352570af302Sopenharmony_ci a_barrier(); 353570af302Sopenharmony_ci return cb->__err & 0x7fffffff; 354570af302Sopenharmony_ci} 355570af302Sopenharmony_ci 356570af302Sopenharmony_ciint aio_cancel(int fd, struct aiocb *cb) 357570af302Sopenharmony_ci{ 358570af302Sopenharmony_ci sigset_t allmask, origmask; 359570af302Sopenharmony_ci int ret = AIO_ALLDONE; 360570af302Sopenharmony_ci struct aio_thread *p; 361570af302Sopenharmony_ci struct aio_queue *q; 362570af302Sopenharmony_ci 363570af302Sopenharmony_ci /* Unspecified behavior case. Report an error. */ 364570af302Sopenharmony_ci if (cb && fd != cb->aio_fildes) { 365570af302Sopenharmony_ci errno = EINVAL; 366570af302Sopenharmony_ci return -1; 367570af302Sopenharmony_ci } 368570af302Sopenharmony_ci 369570af302Sopenharmony_ci sigfillset(&allmask); 370570af302Sopenharmony_ci pthread_sigmask(SIG_BLOCK, &allmask, &origmask); 371570af302Sopenharmony_ci 372570af302Sopenharmony_ci errno = ENOENT; 373570af302Sopenharmony_ci if (!(q = __aio_get_queue(fd, 0))) { 374570af302Sopenharmony_ci if (errno == EBADF) ret = -1; 375570af302Sopenharmony_ci goto done; 376570af302Sopenharmony_ci } 377570af302Sopenharmony_ci 378570af302Sopenharmony_ci for (p = q->head; p; p = p->next) { 379570af302Sopenharmony_ci if (cb && cb != p->cb) continue; 380570af302Sopenharmony_ci /* Transition target from running to running-with-waiters */ 381570af302Sopenharmony_ci if (a_cas(&p->running, 1, -1)) { 382570af302Sopenharmony_ci#ifdef FEATURE_PTHREAD_CANCEL 383570af302Sopenharmony_ci pthread_cancel(p->td); 384570af302Sopenharmony_ci#else 385570af302Sopenharmony_ci __syscall(SYS_tkill, p->td->tid, SIGCANCEL); 386570af302Sopenharmony_ci#endif 387570af302Sopenharmony_ci __wait(&p->running, 0, -1, 1); 388570af302Sopenharmony_ci if (p->err == ECANCELED) ret = AIO_CANCELED; 389570af302Sopenharmony_ci } 390570af302Sopenharmony_ci } 391570af302Sopenharmony_ci 392570af302Sopenharmony_ci pthread_mutex_unlock(&q->lock); 393570af302Sopenharmony_cidone: 394570af302Sopenharmony_ci pthread_sigmask(SIG_SETMASK, &origmask, 0); 395570af302Sopenharmony_ci return ret; 396570af302Sopenharmony_ci} 397570af302Sopenharmony_ci 398570af302Sopenharmony_ciint __aio_close(int fd) 399570af302Sopenharmony_ci{ 400570af302Sopenharmony_ci a_barrier(); 401570af302Sopenharmony_ci if (aio_fd_cnt) aio_cancel(fd, 0); 402570af302Sopenharmony_ci return fd; 403570af302Sopenharmony_ci} 404570af302Sopenharmony_ci 405570af302Sopenharmony_civoid __aio_atfork(int who) 406570af302Sopenharmony_ci{ 407570af302Sopenharmony_ci if (who<0) { 408570af302Sopenharmony_ci pthread_rwlock_rdlock(&maplock); 409570af302Sopenharmony_ci return; 410570af302Sopenharmony_ci } 411570af302Sopenharmony_ci if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++) 412570af302Sopenharmony_ci if (map[a]) for (int b=0; b<256; b++) 413570af302Sopenharmony_ci if (map[a][b]) for (int c=0; c<256; c++) 414570af302Sopenharmony_ci if (map[a][b][c]) for (int d=0; d<256; d++) 415570af302Sopenharmony_ci map[a][b][c][d] = 0; 416570af302Sopenharmony_ci pthread_rwlock_unlock(&maplock); 417570af302Sopenharmony_ci} 418570af302Sopenharmony_ci 419570af302Sopenharmony_ciweak_alias(aio_cancel, aio_cancel64); 420570af302Sopenharmony_ciweak_alias(aio_error, aio_error64); 421570af302Sopenharmony_ciweak_alias(aio_fsync, aio_fsync64); 422570af302Sopenharmony_ciweak_alias(aio_read, aio_read64); 423570af302Sopenharmony_ciweak_alias(aio_write, aio_write64); 424570af302Sopenharmony_ciweak_alias(aio_return, aio_return64); 425