summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-10-04 14:44:57 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-10-04 14:44:57 -0600
commit92dcff84fe6500c09b5a822727abec1c8affe7b5 (patch)
tree61b25595d954d7a074c0409305757f201a9e8889
parent77334062690149a06cf7303ef9cc8b990f2bce14 (diff)
downloadnuttx-92dcff84fe6500c09b5a822727abec1c8affe7b5.tar.gz
nuttx-92dcff84fe6500c09b5a822727abec1c8affe7b5.tar.bz2
nuttx-92dcff84fe6500c09b5a822727abec1c8affe7b5.zip
Fleshes out aio_read implementation
-rw-r--r--nuttx/include/aio.h4
-rw-r--r--nuttx/libc/aio/aio_read.c51
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;
}