diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-10-04 14:44:57 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-10-04 14:44:57 -0600 |
commit | 92dcff84fe6500c09b5a822727abec1c8affe7b5 (patch) | |
tree | 61b25595d954d7a074c0409305757f201a9e8889 | |
parent | 77334062690149a06cf7303ef9cc8b990f2bce14 (diff) | |
download | nuttx-92dcff84fe6500c09b5a822727abec1c8affe7b5.tar.gz nuttx-92dcff84fe6500c09b5a822727abec1c8affe7b5.tar.bz2 nuttx-92dcff84fe6500c09b5a822727abec1c8affe7b5.zip |
Fleshes out aio_read implementation
-rw-r--r-- | nuttx/include/aio.h | 4 | ||||
-rw-r--r-- | nuttx/libc/aio/aio_read.c | 51 |
2 files changed, 53 insertions, 2 deletions
diff --git a/nuttx/include/aio.h b/nuttx/include/aio.h index b130f522a..32e9d1b29 100644 --- a/nuttx/include/aio.h +++ b/nuttx/include/aio.h @@ -133,7 +133,9 @@ struct aiocb /* Non-standard, implementation-dependent data */ - struct work_s aio_work; /* Use to defer I/O to the work thread */ + struct work_s aio_work; /* Used to defer I/O to the work thread */ + pid_t aio_pid; /* ID of client to be notify at completion */ + ssize_t aio_result; /* Support aio_error() and aio_return() */ }; /**************************************************************************** diff --git a/nuttx/libc/aio/aio_read.c b/nuttx/libc/aio/aio_read.c index 7e19fb0ed..5ae81ff8f 100644 --- a/nuttx/libc/aio/aio_read.c +++ b/nuttx/libc/aio/aio_read.c @@ -39,6 +39,7 @@ #include <nuttx/config.h> +#include <unistd.h> #include <signal.h> #include <aio.h> #include <assert.h> @@ -90,7 +91,46 @@ static void aio_read_worker(FAR void *arg) { FAR struct aiocb *aiocbp = (FAR struct aiocb *)arg; DEBASSERT(arg); -#warning Missing logic + ssize_t nread; + + /* Perform the read using: + * + * aio_fildes - File descriptor + * aio_buf - Location of buffer + * aio_nbytes - Length of transfer + * aio_offset - File offset + */ + + nread = pread(aiocbp->aio_fildes, aiocbp->aio_buf, aiocbp->aio_nbytes, + aiocbp->aio_offset); + + /* Set the result of the read */ + + if (nread < 0) + { + int errcode = get_errno(); + fdbg("ERROR: pread failed: %d\n", errode); + DEBUGASSERT(errcode > 0); + aicbp->result = -errcode; + } + else + { + aicbp->result = nread; + } + + /* Signal the client */ + + if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) + { + int ret; +#ifdef CONFIG_CAN_PASS_STRUCTS + ret = sigqueue(aiocbp->aio_pid, aiocbp->aio_sigevent.sigev_signo, + aiocbp->aio_sigevent.sigev_value); +#else + ret = sigqueue(aiocbp->aio_pid, aiocbp->aio_sigevent.sigev_sign, + aiocbp->aio_sigevent.sigev_value.sival_ptr); +#endif + } } /**************************************************************************** @@ -202,11 +242,20 @@ int aio_read(FAR struct aiocb *aiocbp); DEBUGASSERT(aiocbp); + /* The result -EBUSY means that the transfer has not yet completed */ + + aiocbp->aio_result = -EBUSY; + + /* Save the ID of the calling, client thread */ + + aiocbp->aio_pid = getpid(); + /* Defer the work to the worker thread */ ret = work_queue(AIO_QUEUE, &aiocbp->aio_work, aio_read_worker, aiocbp, 0); if (ret < 0) { + aio->aio_result = ret; set_errno(ret); return ERROR; } |