/* * Copyright 1999, Silicon Graphics, Inc. * * Written October 1999 by Rajagopal Ananthanarayanan (ananth) * at Silicon Graphics, Inc. */ #define AIO_LARGEFILE64 #include #include #include #include #include #include #include #include #include #include _syscall5(int, aio, int, cmd, unsigned long, arg1, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4); int child(void *arg) { /* child */ aio(AIOCMD_SLAVE, 0, 0, 0, 0); return -1; } int aio_init(int nslaves) { int i; char *cstack; int aio_cpid[AIO_MAX_THREADS]; if (nslaves == 0) { char *p; /* get it from the environment */ if ((p = getenv(AIO_THREAD_ENVIRON))) nslaves = strtol(p, 0, 0); else nslaves = AIO_DEFAULT_THREADS; } if (nslaves <= 0 || nslaves > AIO_MAX_THREADS) { nslaves = AIO_DEFAULT_THREADS; } for (i = 0; i < nslaves; i++) { cstack = (char *) malloc(64 * 1024); cstack += (32 * 1024); cstack = (char *)((unsigned long)cstack & 0xfffff000); aio_cpid[i] = clone(child, cstack, SIGCHLD|CLONE_VM|CLONE_FS|CLONE_FILES, 0); if (aio_cpid[i] < 0) { return -1; } } return 0; } int aio_read64(aiocb64_t *aiocb) { int ret; ret = aio(AIOCMD_READ, (unsigned long)aiocb, 0, 0, 0); if (ret < 0 && errno == ENOTCONN) { aio_init(0); ret = aio(AIOCMD_READ, (unsigned long)aiocb, 0, 0, 0); } return ret; } int aio_write64(aiocb64_t *aiocb) { int ret; ret = aio(AIOCMD_WRITE, (unsigned long)aiocb, 0, 0, 0); if (ret < 0 && errno == ENOTCONN) { aio_init(0); ret = aio(AIOCMD_WRITE, (unsigned long)aiocb, 0, 0, 0); } return ret; } int aio_cancel64(int fildes, aiocb64_t *aiocb) { int ret; ret = aio(AIOCMD_CANCEL, (unsigned long)fildes, (unsigned long)aiocb, 0, 0); if (ret < 0 && errno == ENOTCONN) { aio_init(0); ret = aio(AIOCMD_CANCEL, (unsigned long)fildes, (unsigned long)aiocb, 0, 0); } return ret; } int aio_suspend64(const aiocb64_t *const list[], int nent, const struct timespec *timeout) { int ret; ret = aio(AIOCMD_SUSPEND, (unsigned long)list, (unsigned long)nent, (unsigned long)timeout, 0); if (ret < 0 && errno == ENOTCONN) { aio_init(0); ret = aio(AIOCMD_SUSPEND, (unsigned long)list, (unsigned long)nent, (unsigned long)timeout, 0); } return ret; } ssize_t aio_return64(aiocb64_t *aiocb) { return(aiocb->aio_reserved[3]); } int lio_listio64(int mode, aiocb64_t *const list[], int nent, sigevent_t *sig) { int ret; ret = aio(AIOCMD_LIST_IO, (unsigned long)mode, (unsigned long)list, (unsigned long)nent, (unsigned long)sig); if (ret < 0 && errno == ENOTCONN) { aio_init(0); ret = aio(AIOCMD_LIST_IO, (unsigned long)mode, (unsigned long)list, (unsigned long)nent, (unsigned long)sig); } return ret; } #ifndef __USE_FILE_OFFSET64 #define PAD_AIOCB(aiocb) *(unsigned int *)&((aiocb)->__aio_pad) = 0; #else #define PAD_AIOCB(aiocb) #endif int aio_read(aiocb_t *aiocb) { PAD_AIOCB(aiocb); return(aio_read64((aiocb64_t *)aiocb)); } int aio_write(aiocb_t *aiocb) { PAD_AIOCB(aiocb); return(aio_write64((aiocb64_t *)aiocb)); } int aio_cancel(int fildes, aiocb_t *aiocb) { if (aiocb) PAD_AIOCB(aiocb); return(aio_cancel64(fildes, (aiocb64_t *)aiocb)); } typedef const aiocb64_t * const *CLISTC; typedef aiocb64_t * const *LISTC; int aio_suspend(const aiocb_t *const list[], int nent, const struct timespec *timeout) { #ifndef __USE_FILE_OFFSET64 int i; for (i = 0; i < nent; i++) if (list[i]) PAD_AIOCB(list[i]); #endif return(aio_suspend64((CLISTC)list, nent, timeout)); } ssize_t aio_return(aiocb_t *aiocb) { return aio_return64((aiocb64_t *)aiocb); } int lio_listio(int mode, aiocb_t *const list[], int nent, sigevent_t *sig) { #ifndef __USE_FILE_OFFSET64 int i; for (i = 0; i < nent; i++) if (list[i]) PAD_AIOCB(list[i]); #endif return(lio_listio64(mode, (LISTC)list, nent, sig)); } int aio_pcinvalidate(int fd) { if (aio(AIOCMD_PCINVALIDATE, fd, 0, 0, 0)) { if (errno == ENOTCONN) { aio_init(0); if (aio(AIOCMD_PCINVALIDATE, fd, 0, 0, 0) == 0) return; } return -1; } }