int main() { char tmpfname[256]; #define BUF_SIZE 111 char buf[BUF_SIZE]; int fd; struct aiocb aiocb_write; struct aiocb aiocb_fsync; #if _POSIX_ASYNCHRONOUS_IO != 200112L exit(PTS_UNSUPPORTED); #endif snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_4_2_%d", getpid()); unlink(tmpfname); fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); if (fd == -1) { printf(TNAME " Error at open(): %s\n", strerror(errno)); exit(PTS_UNRESOLVED); } unlink(tmpfname); memset(&aiocb_write, 0, sizeof(aiocb_write)); aiocb_write.aio_fildes = fd; aiocb_write.aio_buf = buf; aiocb_write.aio_nbytes = BUF_SIZE; if (aio_write(&aiocb_write) == -1) { printf(TNAME " Error at aio_write(): %s\n", strerror(errno)); exit(PTS_FAIL); } memset(&aiocb_fsync, 0, sizeof(aiocb_fsync)); aiocb_fsync.aio_fildes = fd; if (aio_fsync(O_SYNC, &aiocb_fsync) != 0) { printf(TNAME " Error at aio_fsync()\n"); exit(PTS_FAIL); } errno = 0; aio_return(&aiocb_fsync); if (errno != 0) { printf(TNAME " Error at aio_return() : %s\n", strerror(errno)); exit(PTS_FAIL); } close(fd); printf ("Test PASSED\n"); return PTS_PASS; }
int main() { char tmpfname[256]; #define BUF_SIZE 111 char buf[BUF_SIZE]; int fd; int ret; struct aiocb aiocb_write; struct aiocb aiocb_fsync; if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L) return PTS_UNSUPPORTED; snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_8_2_%d", getpid()); unlink(tmpfname); fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); if (fd == -1) { printf(TNAME " Error at open(): %s\n", strerror(errno)); exit(PTS_UNRESOLVED); } unlink(tmpfname); memset(&aiocb_write, 0, sizeof(aiocb_write)); aiocb_write.aio_fildes = fd; aiocb_write.aio_buf = buf; aiocb_write.aio_nbytes = BUF_SIZE; if (aio_write(&aiocb_write) == -1) { printf(TNAME " Error at aio_write(): %s\n", strerror(errno)); exit(PTS_FAIL); } do { usleep(10000); ret = aio_error(&aiocb_write); } while (ret == EINPROGRESS); if (ret < 0) { printf(TNAME " Error at aio_error() : %s\n", strerror(ret)); exit(PTS_FAIL); } memset(&aiocb_fsync, 0, sizeof(aiocb_fsync)); aiocb_fsync.aio_fildes = fd; aiocb_fsync.aio_buf = NULL; if (aio_fsync(O_SYNC, &aiocb_fsync) != 0) { printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno)); exit(PTS_FAIL); } close(fd); printf("Test PASSED\n"); return PTS_PASS; }
IoObject *IoAsyncRequest_sync(IoAsyncRequest *self, IoObject *locals, IoMessage *m) { /*doc AsyncRequest sync Waits for the request to complete. Returns nil on error or self otherwise. */ int r = aio_fsync(O_SYNC, IOCB(self)); return r == 0 ? self : IONIL(self); }
static VALUE rb_aio_sync(int op, aiocb_t *cb) { int ret; TRAP_BEG; ret = aio_fsync( op, cb ); TRAP_END; if (ret != 0) rb_aio_sync_error(); return INT2FIX(ret); }
int main (void) { char tmpfname[256]; char buf[BUF_SIZE]; int fd; struct aiocb aiocb_write; struct aiocb aiocb_fsync; if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L) return PTS_UNSUPPORTED; snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_2_1_%d", getpid()); unlink(tmpfname); fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); if (fd == -1) { printf(TNAME " Error at open(): %s\n", strerror(errno)); exit(PTS_UNRESOLVED); } unlink(tmpfname); memset(&aiocb_write, 0, sizeof(aiocb_write)); aiocb_write.aio_fildes = fd; aiocb_write.aio_buf = buf; aiocb_write.aio_nbytes = BUF_SIZE; if (aio_write(&aiocb_write) == -1) { printf(TNAME " Error at aio_write(): %s\n", strerror(errno)); exit(PTS_FAIL); } memset(&aiocb_fsync, 0, sizeof(aiocb_fsync)); aiocb_fsync.aio_fildes = fd; if (aio_fsync(O_DSYNC, &aiocb_fsync) != 0) { printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno)); exit(PTS_FAIL); } close(fd); /* we didn't check if the operation is really performed */ return PTS_UNTESTED; }
void aio_check_functions(struct aiocb *ai) { (void)aio_cancel(0, ai); (void)aio_error(ai); #if _POSIX_FSYNC > 0 || _POSIX_SYNCHRONIZED_IO > 0 (void)aio_fsync(0, ai); #endif (void)aio_read(ai); (void)aio_return(ai); (void)aio_suspend((const struct aiocb * const *)1234, 0, (struct timespec *)0); (void)aio_write(ai); (void)lio_listio(0, (struct aiocb * const *)1234, 0, (struct sigevent *)0); }
static struct tevent_req *aio_posix_fsync_send( struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct files_struct *fsp) { struct tevent_req *req; struct aio_posix_state *state; struct aiocb *a; int ret; req = tevent_req_create(mem_ctx, &state, struct aio_posix_state); if (req == NULL) { return NULL; } a = &state->acb; a->aio_fildes = fsp->fh->fd; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; a->aio_sigevent.sigev_value.sival_ptr = req; ret = aio_fsync(O_SYNC, a); if (ret == 0) { talloc_set_destructor(state, aio_posix_state_destructor); return req; } if (errno == EAGAIN) { /* * aio overloaded, do the sync fallback */ state->ret = fsync(fsp->fh->fd); if (state->ret == -1) { state->err = errno; } tevent_req_done(req); return tevent_req_post(req, ev); } tevent_req_error(req, errno); return tevent_req_post(req, ev); }
void * POSIX_Init (void *argument) { int result, fd; struct aiocb *aiocbp; int status; rtems_aio_init (); status = mkdir ("/tmp", S_IRWXU); rtems_test_assert (!status); fd = open ("/tmp/aio_fildes", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); rtems_test_assert ( fd != -1); TEST_BEGIN(); puts (" Init: EBADF TESTS "); aiocbp = create_aiocb (WRONG_FD); status = aio_write (aiocbp); rtems_test_assert (status == -1); /* Bad file descriptor */ puts ("Init: aio_write() - EBADF "); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EBADF); status = aio_read (aiocbp); rtems_test_assert (status == -1); /* Bad file descriptor */ puts ("Init: aio_read() - EBADF "); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EBADF); status = aio_cancel (WRONG_FD, NULL); rtems_test_assert (status == -1); /* Bad file descriptor */ puts ("Init: aio_cancel() - EBADF "); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EBADF); status = aio_fsync (O_SYNC, aiocbp); rtems_test_assert (status == -1); /* Bad file descriptor */ puts ("Init: aio_fsync() - EBADF "); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EBADF); free_aiocb (aiocbp); /* Invalid offset */ puts ("Init: aio_write() - EINVAL [aio_offset]"); aiocbp = create_aiocb (fd); aiocbp->aio_offset = -1; status = aio_write (aiocbp); rtems_test_assert (status == -1); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EINVAL); /* Invalid offset */ puts ("Init: aio_read() - EINVAL [aio_offset]"); status = aio_read (aiocbp); rtems_test_assert (status == -1); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EINVAL); free_aiocb (aiocbp); /* Invalid request priority */ puts ("Init: aio_write() - EINVAL [aio_reqprio]"); aiocbp = create_aiocb (fd); aiocbp->aio_reqprio = AIO_PRIO_DELTA_MAX + 1; status = aio_write (aiocbp); rtems_test_assert (status == -1); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EINVAL); /* Invalid request priority */ puts ("Init: aio_read() - EINVAL [aio_reqprio]"); status = aio_read (aiocbp); rtems_test_assert (status == -1); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EINVAL); /* Invalid request aio_cancel */ puts ("Init: aio_cancel() - EINVAL "); status = aio_cancel (WRONG_FD, aiocbp); rtems_test_assert (status == -1); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EINVAL); /* Invalid operation to aio_fsync */ puts ("Init: aio_fsync() - EINVAL "); status = aio_fsync (-1, aiocbp); rtems_test_assert (status == -1); result = aio_return (aiocbp); rtems_test_assert (result == -1); status = aio_error (aiocbp); rtems_test_assert (status == EINVAL); free_aiocb (aiocbp); TEST_END(); close (fd); rtems_test_exit (0); return NULL; }
int main(int argc, char *argv[]) { int ifd, ofd, i, j, n, err, numop; struct stat sbuf; const struct aiocb *aiolist[NBUF]; off_t off = 0; if (argc != 3) err_quit("usage: rot13 infile outfile"); if ((ifd = open(argv[1], O_RDONLY)) < 0) err_sys("can't open %s", argv[1]); if ((ofd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) < 0) err_sys("can't create %s", argv[2]); if (fstat(ifd, &sbuf) < 0) err_sys("fstat error"); /* initialize the buffers */ for (i = 0; i < NBUF; i++) { bufs[i].op = UNUSED; bufs[i].aiocb.aio_buf = bufs[i].data; bufs[i].aiocb.aio_sigevent.sigev_notify = SIGEV_NONE; aiolist[i] = NULL; } numop = 0; for (;;) { for (i = 0; i < NBUF; i++) { switch (bufs[i].op) { case UNUSED: /* * Read from the input file if more data * remains unread */ if (off < sbuf.st_size) { bufs[i].op = READ_PENDING; bufs[i].aiocb.aio_fildes = ifd; bufs[i].aiocb.aio_offset = off; off += BSZ; if (off >= sbuf.st_size) bufs[i].last = 1; bufs[i].aiocb.aio_nbytes = BSZ; if (aio_read(&bufs[i].aiocb) < 0) err_sys("aio_read failed"); aiolist[i] = &bufs[i].aiocb; numop++; } break; case READ_PENDING: if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS) continue; if (err != 0) { if (err == 1) err_sys("aio_error failed"); else err_exit(err, "read failed"); } /* * A read is complete; tranlate the buffer * and write it */ if ((n = aio_return(&bufs[i].aiocb)) < 0) err_sys("aio_return failed"); if (n != BSZ && !bufs[i].last) err_quit("short read (%d/%d)", n, BSZ); for (j = 0; j < n; j++) bufs[i].data[j] = tranlate(bufs[i].data[j]); bufs[i].op = WRITE_PENDING; bufs[i].aiocb.aio_fildes = ofd; bufs[i].aiocb.aio_nbytes = n; if (aio_write(&bufs[i].aiocb) < 0) err_sys("aio_write failed"); /* retain(保持) our spot(地点) in aiolis */ break; case WRITE_PENDING: if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS) continue; if (err != 0) { if (err == -1) err_sys("aio_error failed"); else err_exit(err, "write failed"); } /* * A write is complete; mark the buffer as unused */ if ((n = aio_return(&bufs[i].aiocb)) < 0) err_sys("aio_return failed"); if (n != bufs[i].aiocb.aio_nbytes) err_quit("short write (%d/%d)", n, BSZ); aiolist[i] = NULL; bufs[i].op = UNUSED; numop--; break; } } if (numop == 0) { if (off >= sbuf.st_size) break; } else { if (aio_suspend(aiolist, NBUF, NULL) < 0) err_sys("aio_suspend failed"); } } bufs[0].aiocb.aio_fildes = ofd; if (aio_fsync(O_SYNC, &bufs[0].aiocb) < 0) err_sys("aio_fsync failed"); exit(0); }
int do_test (int argc, char *argv[]) { struct aiocb cbs[10]; struct aiocb cbs_fsync; struct aiocb *cbp[10]; struct aiocb *cbp_fsync[1]; char *buf; size_t cnt; int result = 0; buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); tmpbuf = buf + 10 * blksz; if (buf == MAP_FAILED) { error (0, errno, "mmap failed"); return 1; } /* Preparation. */ for (cnt = 0; cnt < 10; ++cnt) { cbs[cnt].aio_fildes = fd; cbs[cnt].aio_reqprio = 0; cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz); cbs[cnt].aio_nbytes = blksz; cbs[cnt].aio_offset = cnt * blksz; cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; cbp[cnt] = &cbs[cnt]; } /* First a simple test. */ for (cnt = 10; cnt > 0; ) if (aio_write (cbp[--cnt]) < 0 && errno == ENOSYS) { error (0, 0, "no aio support in this configuration"); return 0; } /* Wait 'til the results are there. */ result |= do_wait (cbp, 10, 0); /* Test this. */ result |= test_file (buf, 10 * blksz, fd, "aio_write"); /* Read now as we've written it. */ memset (buf, '\0', 10 * blksz); /* Issue the commands. */ for (cnt = 10; cnt > 0; ) { --cnt; cbp[cnt] = &cbs[cnt]; aio_read (cbp[cnt]); } /* Wait 'til the results are there. */ result |= do_wait (cbp, 10, 0); /* Test this. */ for (cnt = 0; cnt < 10 * blksz; ++cnt) if (buf[cnt] != '0' + (cnt / blksz)) { result = 1; error (0, 0, "comparison failed for aio_read test"); break; } if (cnt == 10 * blksz) puts ("aio_read test ok"); /* Remove the test file contents. */ if (ftruncate (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Test lio_listio. */ for (cnt = 0; cnt < 10; ++cnt) { cbs[cnt].aio_lio_opcode = LIO_WRITE; cbp[cnt] = &cbs[cnt]; } /* Issue the command. */ lio_listio (LIO_WAIT, cbp, 10, NULL); /* ...and immediately test it since we started it in wait mode. */ result |= test_file (buf, 10 * blksz, fd, "lio_listio (write)"); /* Test aio_fsync. */ cbs_fsync.aio_fildes = fd; cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE; cbp_fsync[0] = &cbs_fsync; /* Remove the test file contents first. */ if (ftruncate (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Write again. */ for (cnt = 10; cnt > 0; ) aio_write (cbp[--cnt]); if (aio_fsync (O_SYNC, &cbs_fsync) < 0) { error (0, errno, "aio_fsync failed\n"); result = 1; } result |= do_wait (cbp_fsync, 1, 0); /* ...and test since all data should be on disk now. */ result |= test_file (buf, 10 * blksz, fd, "aio_fsync (aio_write)"); /* Test aio_cancel. */ /* Remove the test file contents first. */ if (ftruncate (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Write again. */ for (cnt = 10; cnt > 0; ) aio_write (cbp[--cnt]); /* Cancel all requests. */ if (aio_cancel (fd, NULL) == -1) printf ("aio_cancel (fd, NULL) cannot cancel anything\n"); result |= do_wait (cbp, 10, ECANCELED); /* Another test for aio_cancel. */ /* Remove the test file contents first. */ if (ftruncate (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Write again. */ for (cnt = 10; cnt > 0; ) { --cnt; cbp[cnt] = &cbs[cnt]; aio_write (cbp[cnt]); } puts ("finished3"); /* Cancel all requests. */ for (cnt = 10; cnt > 0; ) if (aio_cancel (fd, cbp[--cnt]) == -1) /* This is not an error. The request can simply be finished. */ printf ("aio_cancel (fd, cbp[%Zd]) cannot be canceled\n", cnt); puts ("finished2"); result |= do_wait (cbp, 10, ECANCELED); puts ("finished"); return result; }
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) { int rc = VINF_SUCCESS; PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; /* Parameter checks */ AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE); AssertReturn(cReqs != 0, VERR_INVALID_POINTER); AssertPtrReturn(pahReqs, VERR_INVALID_PARAMETER); rtFileAioCtxDump(pCtxInt); /* Check that we don't exceed the limit */ if (ASMAtomicUoReadS32(&pCtxInt->cRequests) + cReqs > pCtxInt->cMaxRequests) return VERR_FILE_AIO_LIMIT_EXCEEDED; PRTFILEAIOREQINTERNAL pHead = NULL; do { int rcPosix = 0; size_t cReqsSubmit = 0; size_t i = 0; PRTFILEAIOREQINTERNAL pReqInt; while ( (i < cReqs) && (i < AIO_LISTIO_MAX)) { pReqInt = pahReqs[i]; if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) { /* Undo everything and stop submitting. */ for (size_t iUndo = 0; iUndo < i; iUndo++) { pReqInt = pahReqs[iUndo]; RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); pReqInt->pCtxInt = NULL; /* Unlink from the list again. */ PRTFILEAIOREQINTERNAL pNext, pPrev; pNext = pReqInt->pNext; pPrev = pReqInt->pPrev; if (pNext) pNext->pPrev = pPrev; if (pPrev) pPrev->pNext = pNext; else pHead = pNext; } rc = VERR_INVALID_HANDLE; break; } pReqInt->pCtxInt = pCtxInt; if (pReqInt->fFlush) break; /* Link them together. */ pReqInt->pNext = pHead; if (pHead) pHead->pPrev = pReqInt; pReqInt->pPrev = NULL; pHead = pReqInt; RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); cReqsSubmit++; i++; } if (cReqsSubmit) { rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL); if (RT_UNLIKELY(rcPosix < 0)) { size_t cReqsSubmitted = cReqsSubmit; if (errno == EAGAIN) rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; else rc = RTErrConvertFromErrno(errno); /* Check which ones were not submitted. */ for (i = 0; i < cReqsSubmit; i++) { pReqInt = pahReqs[i]; rcPosix = aio_error(&pReqInt->AioCB); if ((rcPosix != EINPROGRESS) && (rcPosix != 0)) { cReqsSubmitted--; #if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) if (errno == EINVAL) #else if (rcPosix == EINVAL) #endif { /* Was not submitted. */ RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); } else { /* An error occurred. */ RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); /* * Looks like Apple and glibc interpret the standard in different ways. * glibc returns the error code which would be in errno but Apple returns * -1 and sets errno to the appropriate value */ #if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) Assert(rcPosix == -1); pReqInt->Rc = RTErrConvertFromErrno(errno); #elif defined(RT_OS_LINUX) pReqInt->Rc = RTErrConvertFromErrno(rcPosix); #endif pReqInt->cbTransfered = 0; } /* Unlink from the list. */ PRTFILEAIOREQINTERNAL pNext, pPrev; pNext = pReqInt->pNext; pPrev = pReqInt->pPrev; if (pNext) pNext->pPrev = pPrev; if (pPrev) pPrev->pNext = pNext; else pHead = pNext; pReqInt->pNext = NULL; pReqInt->pPrev = NULL; } } ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted); AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n")); break; } ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n")); cReqs -= cReqsSubmit; pahReqs += cReqsSubmit; } /* * Check if we have a flush request now. * If not we hit the AIO_LISTIO_MAX limit * and will continue submitting requests * above. */ if (cReqs && RT_SUCCESS_NP(rc)) { pReqInt = pahReqs[0]; if (pReqInt->fFlush) { /* * lio_listio does not work with flush requests so * we have to use aio_fsync directly. */ rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB); if (RT_UNLIKELY(rcPosix < 0)) { if (errno == EAGAIN) { rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); } else { rc = RTErrConvertFromErrno(errno); RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); pReqInt->Rc = rc; } pReqInt->cbTransfered = 0; break; } /* Link them together. */ pReqInt->pNext = pHead; if (pHead) pHead->pPrev = pReqInt; pReqInt->pPrev = NULL; pHead = pReqInt; RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); ASMAtomicIncS32(&pCtxInt->cRequests); AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n")); cReqs--; pahReqs++; } } } while ( cReqs && RT_SUCCESS_NP(rc)); if (pHead) { /* * Forward successfully submitted requests to the thread waiting for requests. * We search for a free slot first and if we don't find one * we will grab the first one and append our list to the existing entries. */ unsigned iSlot = 0; while ( (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead)) && !ASMAtomicCmpXchgPtr(&pCtxInt->apReqsNewHead[iSlot], pHead, NULL)) iSlot++; if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead)) { /* Nothing found. */ PRTFILEAIOREQINTERNAL pOldHead = ASMAtomicXchgPtrT(&pCtxInt->apReqsNewHead[0], NULL, PRTFILEAIOREQINTERNAL); /* Find the end of the current head and link the old list to the current. */ PRTFILEAIOREQINTERNAL pTail = pHead; while (pTail->pNext) pTail = pTail->pNext; pTail->pNext = pOldHead; ASMAtomicWritePtr(&pCtxInt->apReqsNewHead[0], pHead); } /* Set the internal wakeup flag and wakeup the thread if possible. */ bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true); if (!fWokenUp) rtFileAioCtxWakeup(pCtxInt); } rtFileAioCtxDump(pCtxInt); return rc; }
int main() { char tmpfname[256]; char buf[BUF_SIZE]; int fd; struct aiocb aiocb_write; struct aiocb aiocb_fsync; int ret; #if _POSIX_ASYNCHRONOUS_IO != 200112L exit(PTS_UNSUPPORTED); #endif snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_5_1_%d", getpid()); unlink(tmpfname); fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); if (fd == -1) { printf(TNAME " Error at open(): %s\n", strerror(errno)); exit(PTS_UNRESOLVED); } unlink(tmpfname); memset(&aiocb_write, 0, sizeof(aiocb_write)); aiocb_write.aio_fildes = fd; aiocb_write.aio_buf = buf; aiocb_write.aio_nbytes = BUF_SIZE; if (aio_write(&aiocb_write) == -1) { printf(TNAME " Error at aio_write(): %s\n", strerror(errno)); exit(PTS_FAIL); } memset(&aiocb_fsync, 0, sizeof(aiocb_fsync)); aiocb_fsync.aio_fildes = fd; if (aio_fsync(O_SYNC, &aiocb_fsync) != 0) { printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno)); exit(PTS_FAIL); } ret = PTS_UNTESTED; if (aio_error(&aiocb_fsync) == EINPROGRESS) ret = PTS_PASS; /* allow to check if aio_error() move from EINPROGRESS to * something else * otherwise test hangs */ while (aio_error(&aiocb_fsync) == EINPROGRESS); close(fd); /* we didn't check if the operation is really performed */ return ret; }
int main(int argc, const char *argv[]) { int ifd, ofd, i, j, n, err, numop; struct stat sbuf; const struct aiocb *aiolist[NBUF]; off_t off = 0; if (argc != 3) err_quit("usage: rot13 infile outfile"); if ((ifd = open(argv[1], O_RDONLY)) < 0) err_sys("can`t open %s", argv[1]); if ((ofd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) < 0) err_sys("cna`t create %s", argv[2]); if (fstat(ifd, &sbuf) < 0) err_sys("fstat failed"); for (i = 0; i < NBUF; i ++) { bufs[i].op = UNUSED; bufs[i].aiocb.aio_buf = bufs[i].data; bufs[i].aiocb.aio_sigevent.sigev_notify = SIGEV_NONE; aiolist[i] = NULL; } numop = 0; while (1) { for (i = 0; i < NBUF; i ++) { switch (bufs[i].op) { case UNUSED: if (off < sbuf.st_size) { bufs[i].op = READ_PENDING; bufs[i].aiocb.aio_fildes = ifd; bufs[i].aiocb.aio_offset = off; off += BSZ; if (off >= sbuf.st_size) bufs[i].last = 1; bufs[i].aiocb.aio_nbytes = BSZ; if (aio_read(&bufs[i].aiocb) < 0) err_sys("aio_read failed"); aiolist[i] = &bufs[i].aiocb; numop ++; } break; case READ_PENDING: if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS) continue; if (err != 0) { if (err == -1) err_sys("aio_error failed"); else err_exit(err, "read failed"); } if ((n = aio_return(&bufs[i].aiocb)) < 0) err_sys("aio_return failed"); if (n != BSZ && !bufs[i].last) err_quit("short read (%d/%d)", n, BSZ); for (j = 0; j < n; j ++) bufs[i].data[j] = translate(bufs[i].data[j]); bufs[i].op = WRITE_PENDING; bufs[i].aiocb.aio_fildes = ofd; bufs[i].aiocb.aio_nbytes = n; if (aio_write(&bufs[i].aiocb) < 0) err_sys("aio_write failed"); break; case WRITE_PENDING: if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS) continue; if (err != 0) { if (err == -1) err_sys("aio_error failed"); else err_exit(err, "write failed"); } if ((n = aio_return(&bufs[i].aiocb)) < 0) err_sys("aio_return failed"); if (n != bufs[i].aiocb.aio_nbytes) err_quit("short write (%d/%d)", n, BSZ); aiolist[i] = NULL; bufs[i].op = UNUSED; numop --; break; } } if (numop == 0) { if (off >= sbuf.st_size) break; } else { if (aio_suspend(aiolist, NBUF, NULL) < 0) err_sys("aio_suspend failed"); } } bufs[0].aiocb.aio_fildes = ofd; if (aio_fsync(O_SYNC, &bufs[0].aiocb) < 0) err_sys("aio_fsync failed"); exit(0); }
static STATUS DI_force( DI_IO *f, DI_OP *diop, CL_ERR_DESC *err_code) { STATUS big_status = OK, small_status = OK, intern_status = OK; register DI_SLAVE_CB *disl; do { if (Di_slave) { disl = diop->di_evcb; disl->file_op = DI_SL_SYNC; /* Send file properties to slave */ FPROP_COPY(f->io_fprop,disl->io_fprop); DI_slave_send( disl->dest_slave_no, diop, &big_status, &small_status, &intern_status); if (big_status != OK ) break; if ( small_status == OK ) { if ((small_status = disl->status) != OK ) { STRUCT_ASSIGN_MACRO(disl->errcode, *err_code); } } } else { /* ** put code in here for fsync issues */ #ifdef xCL_ASYNC_IO if( Di_async_io) { DI_AIOCB *aio; aio=DI_get_aiocb(); #ifdef dr6_us5 aio->aio.aio_filedes=diop->di_fd; #else aio->aio.aio_fildes=diop->di_fd; #endif /* dr6_us5 */ #ifdef LARGEFILE64 if(aio_fsync64( O_SYNC, &aio->aio)) #elif defined(any_aix) if(fsync( aio->aio.aio_fildes )) #else if(aio_fsync( O_SYNC, &aio->aio)) #endif /* LARGEFILE64 */ { SETCLERR(err_code, 0, ER_fsync); small_status = FAIL; break; } else { if( (small_status=CSsuspend( CS_DIOW_MASK, 0, 0) ) != OK) { DIlru_set_di_error( &small_status, err_code, DI_LRU_CSSUSPEND_ERR, DI_GENERAL_ERR); break; } #if defined(axp_osf) if ( (aio_error(&aio->aio)) != 0 ) #else #ifdef LARGEFILE64 if ( (aio_error64(&aio->aio)) != 0 ) #else /* LARGEFILE64 */ if ( (aio_error(&aio->aio)) != 0 ) #endif /* LARGEFILE64 */ #endif { SETCLERR(err_code, 0, ER_fsync); small_status = FAIL; break; } } } else #endif /* xCL_ASYNC_IO */ if (FSYNC(diop->di_fd) < 0) { #ifdef xCL_092_NO_RAW_FSYNC /* AIX returns EINVAL on character special files */ if (errno != EINVAL) #endif /* xCL_092_NO_RAW_FSYNC */ { SETCLERR(err_code, 0, ER_fsync); small_status = FAIL; } } } } while (FALSE); if ( big_status != OK ) small_status = big_status; if ( small_status != OK ) DIlru_set_di_error( &small_status, err_code, intern_status, DI_GENERAL_ERR); return( small_status ); }
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) { /* * Parameter validation. */ int rc = VINF_SUCCESS; PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; RTFILEAIOCTX_VALID_RETURN(pCtxInt); AssertReturn(cReqs > 0, VERR_INVALID_PARAMETER); AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); size_t i = cReqs; do { int rcSol = 0; size_t cReqsSubmit = 0; PRTFILEAIOREQINTERNAL pReqInt; while(i-- > 0) { pReqInt = pahReqs[i]; if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) { /* Undo everything and stop submitting. */ for (size_t iUndo = 0; iUndo < i; iUndo++) { pReqInt = pahReqs[iUndo]; RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); pReqInt->pCtxInt = NULL; } rc = VERR_INVALID_HANDLE; break; } pReqInt->PortNotifier.portnfy_port = pCtxInt->iPort; pReqInt->pCtxInt = pCtxInt; RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); if (pReqInt->fFlush) break; cReqsSubmit++; } if (cReqsSubmit) { rcSol = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL); if (RT_UNLIKELY(rcSol < 0)) { if (rcSol == EAGAIN) rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; else rc = RTErrConvertFromErrno(errno); /* Check which requests got actually submitted and which not. */ for (i = 0; i < cReqs; i++) { pReqInt = pahReqs[i]; rcSol = aio_error(&pReqInt->AioCB); if (rcSol == EINVAL) { /* Was not submitted. */ RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); pReqInt->pCtxInt = NULL; } else if (rcSol != EINPROGRESS) { /* The request encountered an error. */ RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); } } break; } ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); cReqs -= cReqsSubmit; pahReqs += cReqsSubmit; } if (cReqs) { pReqInt = pahReqs[0]; RTFILEAIOREQ_VALID_RETURN(pReqInt); /* * If there are still requests left we have a flush request. * lio_listio does not work with this requests so * we have to use aio_fsync directly. */ rcSol = aio_fsync(O_SYNC, &pReqInt->AioCB); if (RT_UNLIKELY(rcSol < 0)) { RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); rc = RTErrConvertFromErrno(errno); break; } ASMAtomicIncS32(&pCtxInt->cRequests); cReqs--; pahReqs++; } } while (cReqs); return rc; }
int main(void) { char tmpfname[256]; char buf[BUF_SIZE]; int fd, ret; struct aiocb aiocb_write; struct aiocb aiocb_fsync; if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L) return PTS_UNSUPPORTED; snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_2_1_%d", getpid()); unlink(tmpfname); fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); if (fd == -1) { printf(TNAME " Error at open(): %s\n", strerror(errno)); exit(PTS_UNRESOLVED); } unlink(tmpfname); memset(&aiocb_write, 0, sizeof(aiocb_write)); aiocb_write.aio_fildes = fd; aiocb_write.aio_buf = buf; aiocb_write.aio_nbytes = BUF_SIZE; if (aio_write(&aiocb_write) == -1) { printf(TNAME " Error at aio_write(): %s\n", strerror(errno)); exit(PTS_FAIL); } memset(&aiocb_fsync, 0, sizeof(aiocb_fsync)); aiocb_fsync.aio_fildes = fd; if (aio_fsync(O_DSYNC, &aiocb_fsync) != 0) { printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno)); exit(PTS_FAIL); } /* wait for aio_fsync */ do { usleep(10000); ret = aio_error(&aiocb_fsync); } while (ret == EINPROGRESS); ret = aio_return(&aiocb_fsync); if (ret) { printf(TNAME " Error at aio_return(): %d (%s)\n", ret, strerror(errno)); close(fd); return PTS_FAIL; } /* check that aio_write is completed at this point */ ret = aio_error(&aiocb_write); if (ret == EINPROGRESS) { printf(TNAME " aiocb_write still in progress\n"); close(fd); return PTS_FAIL; } close(fd); return PTS_PASS; }
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) { /* * Parameter validation. */ int rc = VINF_SUCCESS; PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; RTFILEAIOCTX_VALID_RETURN(pCtxInt); AssertReturn(cReqs > 0, VERR_INVALID_PARAMETER); AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); do { int rcBSD = 0; size_t cReqsSubmit = 0; size_t i = 0; PRTFILEAIOREQINTERNAL pReqInt; while ( (i < cReqs) && (i < AIO_LISTIO_MAX)) { pReqInt = pahReqs[i]; if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) { /* Undo everything and stop submitting. */ for (size_t iUndo = 0; iUndo < i; iUndo++) { pReqInt = pahReqs[iUndo]; RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); pReqInt->pCtxInt = NULL; pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = 0; } rc = VERR_INVALID_HANDLE; break; } pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = pCtxInt->iKQueue; pReqInt->pCtxInt = pCtxInt; RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); if (pReqInt->fFlush) break; cReqsSubmit++; i++; } if (cReqsSubmit) { rcBSD = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL); if (RT_UNLIKELY(rcBSD < 0)) { if (errno == EAGAIN) rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; else rc = RTErrConvertFromErrno(errno); /* Check which requests got actually submitted and which not. */ for (i = 0; i < cReqs; i++) { pReqInt = pahReqs[i]; rcBSD = aio_error(&pReqInt->AioCB); if ( rcBSD == -1 && errno == EINVAL) { /* Was not submitted. */ RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); pReqInt->pCtxInt = NULL; } else if (rcBSD != EINPROGRESS) { /* The request encountered an error. */ RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); pReqInt->Rc = RTErrConvertFromErrno(rcBSD); pReqInt->pCtxInt = NULL; pReqInt->cbTransfered = 0; } } break; } ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); cReqs -= cReqsSubmit; pahReqs += cReqsSubmit; } /* Check if we have a flush request now. */ if (cReqs && RT_SUCCESS_NP(rc)) { pReqInt = pahReqs[0]; RTFILEAIOREQ_VALID_RETURN(pReqInt); if (pReqInt->fFlush) { /* * lio_listio does not work with flush requests so * we have to use aio_fsync directly. */ rcBSD = aio_fsync(O_SYNC, &pReqInt->AioCB); if (RT_UNLIKELY(rcBSD < 0)) { if (rcBSD == EAGAIN) { /* Was not submitted. */ RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); pReqInt->pCtxInt = NULL; return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; } else { RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); pReqInt->Rc = RTErrConvertFromErrno(errno); pReqInt->cbTransfered = 0; return pReqInt->Rc; } } ASMAtomicIncS32(&pCtxInt->cRequests); cReqs--; pahReqs++; } } } while (cReqs); return rc; }
int main(void) { aio_fsync(1, &iocb); return 0; }
int main(int argc, char *argv[]) { int ifd, ofd, i, j, n, err, numop; struct stat sbuf; struct aiocb *aiolist[NBUF]; off_t off=0; printf("SIGEV_NODE:%d\n", SIGEV_NONE); if (argc != 3) { printf("usage: rot13 infile outfile"); return -1; } if ((ifd = open(argv[1], O_RDONLY)) < 0) { printf("cant't open %s", argv[1]); return -1; } if ((ofd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) { printf("Cant't create %s", argv[2]); return -1; } if (fstat(ifd, &sbuf) < 0) { printf("fstat failed"); return -1; } /* initialize the buffers */ for (i = 0; i < NBUF; i++) { bufs[i].op = UNUSED; bufs[i].aiocb.aio_buf = bufs[i].data; bufs[i].aiocb.aio_sigevent.sigev_notify = SIGEV_NONE; aiolist[i] = NULL; } numop = 0; printf("sbuf.st_size:%d\n", sbuf.st_size); for (;;) { for (i = 0; i < 1; i++) { switch (bufs[i].op) { case UNUSED: /* * Read from the input file if more data * remains unread */ if (off < sbuf.st_size) { bufs[i].op = 1; bufs[i].aiocb.aio_fildes = ifd; bufs[i].aiocb.aio_offset = off; off += BSZ; if (off >= sbuf.st_size) bufs[i].last = 1; bufs[i].aiocb.aio_nbytes = BSZ; if (aio_read(&bufs[i].aiocb) < 0) printf("aio_read failed"); printf("Start aio\n"); aiolist[i] = &bufs[i].aiocb; numop++; } break; case READ_PENDING: if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS) { printf("Pending\n"); continue; } if (err != 0) { if (err == -1) printf("aio_error failed"); else printf("read failed"); } if ((n = aio_return(&bufs[i].aiocb)) < 0) /* A read is complete; translate the buffer and write it */ printf("aio_return failed"); if (n != BSZ && !bufs[i].last) printf("short read (%d/%d)", n, BSZ); for (j = 0; j < n; j++) bufs[i].data[j] = bufs[i].data[j]; bufs[i].op = WRITE_PENDING; bufs[i].aiocb.aio_fildes = ofd; bufs[i].aiocb.aio_nbytes = n; if (aio_write(&bufs[i].aiocb) < 0) printf("aio_write failed"); /* retain out spot in aiolist */ break; case WRITE_PENDING: if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS) continue; if (err != 0) { if (err == -1) printf("aio_error failed"); else printf("write failed"); } /* * A write is complete; mark the buffer as unused. */ if ((n = aio_return(&bufs[i].aiocb)) < 0) printf("aio_return failed"); if (n != bufs[i].aiocb.aio_nbytes) printf("short write (%d/%d)", n, BSZ); aiolist[i] = NULL; bufs[i].op = UNUSED; numop--; break; printf("switch ..\n"); } //switch } // small for if (numop == 0) { if (off >= sbuf.st_size) break; } else { if (aio_suspend(aiolist, NBUF, NULL) < 0) printf("aio_suspend failed"); } } // big for bufs[0].aiocb.aio_fildes = ofd; if (aio_fsync(O_SYNC, &bufs[0].aiocb) <0) printf("aio_fsync failed"); exit(0); return 0; }
void * POSIX_Init (void *argument) { int fd[MAX]; struct aiocb *aiocbp[MAX+1]; int status, i, policy = SCHED_FIFO; char filename[BUFSIZE]; struct sched_param param; status = rtems_aio_init (); rtems_test_assert (status == 0); param.sched_priority = 30; status = pthread_setschedparam (pthread_self(), policy, ¶m); rtems_test_assert (status == 0); status = mkdir ("/tmp", S_IRWXU); rtems_test_assert (!status); puts ("\n\n*** POSIX AIO TEST 02 ***"); puts ("Init: Open files"); for (i=0; i<MAX; i++) { sprintf (filename, "/tmp/aio_fildes%d",i); fd[i] = open (filename, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); rtems_test_assert ( fd[i] != -1); } puts ("Init: [WQ] aio_write on 1st file"); aiocbp[0] = create_aiocb (fd[0]); status = aio_write (aiocbp[0]); rtems_test_assert (status != -1); puts ("Init: [WQ] aio_write on 2nd file"); aiocbp[1] = create_aiocb (fd[1]); status = aio_write (aiocbp[1]); rtems_test_assert (status != -1); puts ("Init: [WQ] aio_read on 2nd file add by priority"); aiocbp[2] = create_aiocb (fd[1]); status = aio_read (aiocbp[2]); rtems_test_assert (status != -1); puts ("Init: [WQ] aio_write on 3rd file"); aiocbp[3] = create_aiocb (fd[2]); status = aio_write (aiocbp[3]); rtems_test_assert (status != -1); puts ("Init: [WQ] aio_write on 4th file"); aiocbp[4] = create_aiocb (fd[3]); status = aio_write (aiocbp[4]); rtems_test_assert (status != -1); puts ("Init: [WQ] aio_write on 5th file -- [WQ] full"); aiocbp[5] = create_aiocb (fd[4]); status = aio_write (aiocbp[5]); rtems_test_assert (status != -1); puts ("Init: [IQ] aio_write on 6th file"); aiocbp[6] = create_aiocb (fd[5]); status = aio_write (aiocbp[6]); rtems_test_assert (status != -1); puts ("Init: [IQ] aio_write on 7th file"); aiocbp[7] = create_aiocb (fd[6]); status = aio_write (aiocbp[7]); rtems_test_assert (status != -1); puts ("Init: [IQ] aio_read on 7th file add by priority"); aiocbp[8] = create_aiocb (fd[6]); status = aio_read (aiocbp[8]); rtems_test_assert (status != -1); puts ("Init: [WQ] aio_sync on 1st file add by priority"); aiocbp[9] = create_aiocb (fd[0]); status = aio_fsync (O_SYNC, aiocbp[9]); rtems_test_assert (status != -1); puts ("Init: [NONE] aio_cancel aiocbp=NULL and invalid fildes"); status = aio_cancel (WRONG_FD, NULL); rtems_test_assert (status == -1); puts ("Init: [NONE] aio_cancel aiocbp=NULL valid fildes not in queue"); status = aio_cancel (fd[7], NULL); rtems_test_assert (status == AIO_ALLDONE); puts ("Init: [WQ] aio_cancel aiocbp=NULL fildes=fd[1]"); status = aio_cancel (fd[1], NULL); rtems_test_assert (status == AIO_CANCELED); puts ("Init: [IQ] aio_cancel aiocbp=NULL fildes=fd[6]"); status = aio_cancel (fd[6], NULL); rtems_test_assert (status == AIO_CANCELED); puts ("Init: [NONE] aio_cancel aiocbp->aio_fildes != fildes"); status = aio_cancel (fd[4],aiocbp[4]); rtems_test_assert (status == -1 ); puts ("Init: [NONE] aio_cancel FD on [IQ], aiocb not on chain"); aiocbp[10] = create_aiocb (fd[9]); status = aio_cancel (fd[9], aiocbp[10]); rtems_test_assert (status == -1); puts ("Init: [IQ] aio_cancel 6th file only one request"); status = aio_cancel (fd[5], aiocbp[6]); rtems_test_assert (status == AIO_CANCELED); puts ("Init: [WQ] aio_cancel 1st file only one request"); status = aio_cancel (fd[0], aiocbp[9]); rtems_test_assert (status == AIO_CANCELED); puts ("Init: [NONE] aio_cancel empty [IQ]"); status = aio_cancel (fd[5], aiocbp[6]); rtems_test_assert (status == AIO_ALLDONE); puts ("*** END OF POSIX AIO TEST 02 ***"); for (i = 0; i < MAX; i++) { close (fd[i]); free_aiocb (aiocbp[i]); } free_aiocb (aiocbp[i]); rtems_test_exit (0); return NULL; }
static int do_test (void) { int result = 0; int piped[2]; /* Make a pipe that we will never write to, so we can block reading it. */ if (pipe (piped) < 0) { perror ("pipe"); return 1; } /* Test for aio_cancel() detecting invalid file descriptor. */ { struct aiocb cb; int fd = -1; cb.aio_fildes = fd; cb.aio_offset = 0; cb.aio_buf = NULL; cb.aio_nbytes = 0; cb.aio_reqprio = 0; cb.aio_sigevent.sigev_notify = SIGEV_NONE; errno = 0; /* Case one: invalid fds that match. */ if (aio_cancel (fd, &cb) != -1 || errno != EBADF) { if (errno == ENOSYS) { puts ("no aio support in this configuration"); return 0; } puts ("aio_cancel( -1, {-1..} ) did not return -1 or errno != EBADF"); ++result; } cb.aio_fildes = -2; errno = 0; /* Case two: invalid fds that do not match; just print warning. */ if (aio_cancel (fd, &cb) != -1 || errno != EBADF) puts ("aio_cancel( -1, {-2..} ) did not return -1 or errno != EBADF"); } /* Test for aio_fsync() detecting bad fd. */ { struct aiocb cb; int fd = -1; cb.aio_fildes = fd; cb.aio_offset = 0; cb.aio_buf = NULL; cb.aio_nbytes = 0; cb.aio_reqprio = 0; cb.aio_sigevent.sigev_notify = SIGEV_NONE; errno = 0; /* Case one: invalid fd. */ if (aio_fsync (O_SYNC, &cb) != -1 || errno != EBADF) { puts ("aio_fsync( op, {-1..} ) did not return -1 or errno != EBADF"); ++result; } } /* Test for aio_suspend() suspending even if completed elements in list. */ { #define BYTES 8 const int ELEMS = 2; int i, r, fd; static char buff[BYTES]; char name[] = "/tmp/aio7.XXXXXX"; struct timespec timeout; static struct aiocb cb0, cb1; struct aiocb *list[ELEMS]; fd = mkstemp (name); if (fd < 0) error (1, errno, "creating temp file"); if (unlink (name)) error (1, errno, "unlinking temp file"); if (write (fd, "01234567", BYTES) != BYTES) error (1, errno, "writing to temp file"); cb0.aio_fildes = fd; cb0.aio_offset = 0; cb0.aio_buf = buff; cb0.aio_nbytes = BYTES; cb0.aio_reqprio = 0; cb0.aio_sigevent.sigev_notify = SIGEV_NONE; r = aio_read (&cb0); if (r != 0) error (1, errno, "reading from file"); while (aio_error (&(cb0)) == EINPROGRESS) usleep (10); for (i = 0; i < BYTES; i++) printf ("%c ", buff[i]); printf ("\n"); /* At this point, the first read is completed, so start another one on the read half of a pipe on which nothing will be written. */ cb1.aio_fildes = piped[0]; cb1.aio_offset = 0; cb1.aio_buf = buff; cb1.aio_nbytes = BYTES; cb1.aio_reqprio = 0; cb1.aio_sigevent.sigev_notify = SIGEV_NONE; r = aio_read (&cb1); if (r != 0) error (1, errno, "reading from file"); /* Now call aio_suspend() with the two reads. It should return * immediately according to the POSIX spec. */ list[0] = &cb0; list[1] = &cb1; timeout.tv_sec = 3; timeout.tv_nsec = 0; r = aio_suspend ((const struct aiocb * const *) list, ELEMS, &timeout); if (r == -1 && errno == EAGAIN) { puts ("aio_suspend([done,blocked],2,3) suspended thread"); ++result; } /* Note that CB1 is still pending, and so cannot be an auto variable. Thus we also test that exiting with an outstanding request works. */ } return result; }