static void aio_read_worker(FAR void *arg) { FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg; FAR struct aiocb *aiocbp; pid_t pid; #ifdef CONFIG_PRIORITY_INHERITANCE uint8_t prio; #endif ssize_t nread = 0; /* Get the information from the container, decant the AIO control block, * and free the container before starting any I/O. That will minimize * the delays by any other threads waiting for a pre-allocated container. */ DEBUGASSERT(aioc && aioc->aioc_aiocbp); pid = aioc->aioc_pid; #ifdef CONFIG_PRIORITY_INHERITANCE prio = aioc->aioc_prio; #endif aiocbp = aioc_decant(aioc); #ifdef AIO_HAVE_FILEP { /* Perform the file read using: * * u.aioc_filep - File structure pointer * aio_buf - Location of buffer * aio_nbytes - Length of transfer * aio_offset - File offset */ nread = file_pread(aioc->u.aioc_filep, (FAR void *)aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset); } #endif /* Set the result of the read */ if (nread < 0) { int errcode = get_errno(); fdbg("ERROR: pread failed: %d\n", errcode); DEBUGASSERT(errcode > 0); aiocbp->aio_result = -errcode; } else { aiocbp->aio_result = nread; } /* Signal the client */ (void)aio_signal(pid, aiocbp); #ifdef CONFIG_PRIORITY_INHERITANCE /* Restore the low priority worker thread default priority */ lpwork_restorepriority(prio); #endif }
static void aio_fsync_worker(FAR void *arg) { FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg; FAR struct aiocb *aiocbp; pid_t pid; #ifdef CONFIG_PRIORITY_INHERITANCE uint8_t prio; #endif int ret; /* Get the information from the container, decant the AIO control block, * and free the container before starting any I/O. That will minimize * the delays by any other threads waiting for a pre-allocated container. */ DEBUGASSERT(aioc && aioc->aioc_aiocbp); pid = aioc->aioc_pid; #ifdef CONFIG_PRIORITY_INHERITANCE prio = aioc->aioc_prio; #endif aiocbp = aioc_decant(aioc); /* Perform the fsync using u.aioc_filep */ ret = file_fsync(aioc->u.aioc_filep); if (ret < 0) { int errcode = get_errno(); ferr("ERROR: fsync failed: %d\n", errcode); DEBUGASSERT(errcode > 0); aiocbp->aio_result = -errcode; } else { aiocbp->aio_result = OK; } /* Signal the client */ (void)aio_signal(pid, aiocbp); #ifdef CONFIG_PRIORITY_INHERITANCE /* Restore the low priority worker thread default priority */ lpwork_restorepriority(prio); #endif }
int aio_cancel(int fildes, FAR struct aiocb *aiocbp) { FAR struct aio_container_s *aioc; FAR struct aio_container_s *next; int status; int ret; /* Check if a non-NULL aiocbp was provided */ /* Lock the scheduler so that no I/O events can complete on the worker * thread until we set complete this operation. */ ret = AIO_ALLDONE; sched_lock(); aio_lock(); if (aiocbp) { /* Check if the I/O has completed */ if (aiocbp->aio_result == -EINPROGRESS) { /* No.. Find the container for this AIO control block */ for (aioc = (FAR struct aio_container_s *)g_aio_pending.head; aioc && aioc->aioc_aiocbp != aiocbp; aioc = (FAR struct aio_container_s *)aioc->aioc_link.flink) ; /* Did we find a container for this fildes? We should; the aio_result says * that the transfer is pending. If not we return AIO_ALLDONE. */ if (aioc) { /* Yes... attempt to cancel the I/O. There are two * possibilities:* (1) the work has already been started and * is no longer queued, or (2) the work has not been started * and is still in the work queue. Only the second case can * be cancelled. work_cancel() will return -ENOENT in the * first case. */ status = work_cancel(LPWORK, &aioc->aioc_work); if (status >= 0) { aiocbp->aio_result = -ECANCELED; ret = AIO_CANCELED; } else { ret = AIO_NOTCANCELED; } /* Remove the container from the list of pending transfers */ (void)aioc_decant(aioc); } } } else { /* No aiocbp.. cancel all outstanding I/O for the fildes */ next = (FAR struct aio_container_s *)g_aio_pending.head; do { /* Find the next container with this AIO control block */ for (aioc = next; aioc && aioc->aioc_aiocbp->aio_fildes != fildes; aioc = (FAR struct aio_container_s *)aioc->aioc_link.flink) ; /* Did we find the container? We should; the aio_result says * that the transfer is pending. If not we return AIO_ALLDONE. */ if (aioc) { /* Yes... attempt to cancel the I/O. There are two * possibilities:* (1) the work has already been started and * is no longer queued, or (2) the work has not been started * and is still in the work queue. Only the second case can * be cancelled. work_cancel() will return -ENOENT in the * first case. */ status = work_cancel(LPWORK, &aioc->aioc_work); /* Remove the container from the list of pending transfers */ next = (FAR struct aio_container_s *)aioc->aioc_link.flink; aiocbp = aioc_decant(aioc); DEBUGASSERT(aiocbp); if (status >= 0) { aiocbp->aio_result = -ECANCELED; if (ret != AIO_NOTCANCELED) { ret = AIO_CANCELED; } } else { ret = AIO_NOTCANCELED; } } } while (aioc); } aio_unlock(); sched_unlock(); return ret; }
static void aio_write_worker(FAR void *arg) { FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg; FAR struct aiocb *aiocbp; pid_t pid; #ifdef CONFIG_PRIORITY_INHERITANCE uint8_t prio; #endif ssize_t nwritten = 0; #ifdef AIO_HAVE_FILEP int oflags; #endif /* Get the information from the container, decant the AIO control block, * and free the container before starting any I/O. That will minimize * the delays by any other threads waiting for a pre-allocated container. */ DEBUGASSERT(aioc && aioc->aioc_aiocbp); pid = aioc->aioc_pid; #ifdef CONFIG_PRIORITY_INHERITANCE prio = aioc->aioc_prio; #endif aiocbp = aioc_decant(aioc); #if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK) if (aiocbp->aio_fildes < CONFIG_NFILE_DESCRIPTORS) #endif #ifdef AIO_HAVE_FILEP { /* Call fcntl(F_GETFL) to get the file open mode. */ oflags = file_fcntl(aioc->u.aioc_filep, F_GETFL); if (oflags < 0) { int errcode = get_errno(); fdbg("ERROR: fcntl failed: %d\n", errcode); aiocbp->aio_result = -errcode; goto errout; } /* Perform the write using: * * u.aioc_filep - File structure pointer * aio_buf - Location of buffer * aio_nbytes - Length of transfer * aio_offset - File offset */ /* Check if O_APPEND is set in the file open flags */ if ((oflags & O_APPEND) != 0) { /* Append to the current file position */ nwritten = file_write(aioc->u.aioc_filep, (FAR const void *)aiocbp->aio_buf, aiocbp->aio_nbytes); } else { nwritten = file_pwrite(aioc->u.aioc_filep, (FAR const void *)aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset); } } #endif #if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK) else #endif #ifdef AIO_HAVE_PSOCK { /* Perform the send using: * * u.aioc_psock - Socket structure pointer * aio_buf - Location of buffer * aio_nbytes - Length of transfer */ nwritten = psock_send(aioc->u.aioc_psock, (FAR const void *)aiocbp->aio_buf, aiocbp->aio_nbytes, 0); } #endif /* Check the result of the write */ if (nwritten < 0) { int errcode = get_errno(); fdbg("ERROR: write/pwrite failed: %d\n", errcode); DEBUGASSERT(errcode > 0); aiocbp->aio_result = -errcode; } else { aiocbp->aio_result = nwritten; } #ifdef AIO_HAVE_FILEP errout: #endif /* Signal the client */ (void)aio_signal(pid, aiocbp); #ifdef CONFIG_PRIORITY_INHERITANCE /* Restore the low priority worker thread default priority */ lpwork_restorepriority(prio); #endif }