summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-10-04 17:30:24 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-10-04 17:30:24 -0600
commit2604a25c90a8b02ce323dbd491bdbb8bac3a25c3 (patch)
tree5518238513a29b6378acb0fa832a720d86ce074c
parentb9a8ce78e2f71190fe1b02ff34a2a57a2e8f3f8a (diff)
downloadnuttx-2604a25c90a8b02ce323dbd491bdbb8bac3a25c3.tar.gz
nuttx-2604a25c90a8b02ce323dbd491bdbb8bac3a25c3.tar.bz2
nuttx-2604a25c90a8b02ce323dbd491bdbb8bac3a25c3.zip
Initial implementation of aio_write()
-rw-r--r--nuttx/include/aio.h2
-rw-r--r--nuttx/include/fcntl.h2
-rw-r--r--nuttx/libc/Kconfig2
-rw-r--r--nuttx/libc/aio/Make.defs2
-rw-r--r--nuttx/libc/aio/aio_read.c4
-rw-r--r--nuttx/libc/aio/aio_write.c299
-rw-r--r--nuttx/libc/aio/lio_listio.c2
7 files changed, 306 insertions, 7 deletions
diff --git a/nuttx/include/aio.h b/nuttx/include/aio.h
index 32e9d1b29..449ce7959 100644
--- a/nuttx/include/aio.h
+++ b/nuttx/include/aio.h
@@ -135,7 +135,7 @@ struct aiocb
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() */
+ volatile ssize_t aio_result; /* Support for aio_error() and aio_return() */
};
/****************************************************************************
diff --git a/nuttx/include/fcntl.h b/nuttx/include/fcntl.h
index 7671c0aca..6bec04f0a 100644
--- a/nuttx/include/fcntl.h
+++ b/nuttx/include/fcntl.h
@@ -69,7 +69,7 @@
/* Unsupported, but required open flags */
#define O_RSYNC 0 /* Synchronize input on read */
-#define O_ACCMODE 0 /* Required by POSIX */
+#define O_ACCMODE O_RDWR /* Mask for access mode */
#define O_NOCTTY 0 /* Required by POSIX */
#define O_TEXT 0 /* Open the file in text (translated) mode. */
diff --git a/nuttx/libc/Kconfig b/nuttx/libc/Kconfig
index e425a48d5..32eb7464c 100644
--- a/nuttx/libc/Kconfig
+++ b/nuttx/libc/Kconfig
@@ -460,7 +460,7 @@ if SCHED_LPWORK
config SCHED_LPWORKPRIORITY
int "Low priority worker thread priority"
- default 50
+ default 100
---help---
The execution priority of the lopwer priority worker thread. Default: 192
diff --git a/nuttx/libc/aio/Make.defs b/nuttx/libc/aio/Make.defs
index 0ad5bbb47..ee7e35916 100644
--- a/nuttx/libc/aio/Make.defs
+++ b/nuttx/libc/aio/Make.defs
@@ -37,7 +37,7 @@ ifeq ($(CONFIG_LIBC_AIO),y)
# Add the asynchronous I/O C files to the build
-CSRCS += aio_read.c
+CSRCS += aio_read.c aio_write.c
ifneq ($(CONFIG_PTHREAD_DISABLE),y)
CSRCS += lio_listio.c
diff --git a/nuttx/libc/aio/aio_read.c b/nuttx/libc/aio/aio_read.c
index 5ae81ff8f..49d5823bf 100644
--- a/nuttx/libc/aio/aio_read.c
+++ b/nuttx/libc/aio/aio_read.c
@@ -159,7 +159,7 @@ static void aio_read_worker(FAR void *arg)
* operation, the value of the file offset for the file is unspecified.
*
* The aiocbp->aio_lio_opcode field will be ignored by aio_read().
- *
+ *
* The aiocbp argument points to an aiocb structure. If the buffer pointed
* to by aiocbp->aio_buf or the control block pointed to by aiocbp becomes
* an illegal address prior to asynchronous I/O completion, then the
@@ -168,7 +168,7 @@ static void aio_read_worker(FAR void *arg)
* Simultaneous asynchronous operations using the same aiocbp produce
* undefined results.
*
- * For any system action that changes the process memory space while an
+ * For any system action that changes the process memory space while an
* synchronous I/O is outstanding to the address range being changed, the
* result of that action is undefined.
*
diff --git a/nuttx/libc/aio/aio_write.c b/nuttx/libc/aio/aio_write.c
new file mode 100644
index 000000000..b8826afb9
--- /dev/null
+++ b/nuttx/libc/aio/aio_write.c
@@ -0,0 +1,299 @@
+/****************************************************************************
+ * libc/aio/aio_write.c
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <unistd.h>
+#include <signal.h>
+#include <aio.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "lib_internal.h"
+#include "aio/aio.h"
+
+#ifndef CONFIG_LIBC_AIO
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: aio_write_worker
+ *
+ * Description:
+ * This function executes on the worker thread and performs the
+ * asynchronous I/O operation.
+ *
+ * Input Parameters:
+ * arg - Worker argument. In this case, a pointer to an instance of
+ * struct aiocb cast to void *.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void aio_write_worker(FAR void *arg)
+{
+ FAR struct aiocb *aiocbp = (FAR struct aiocb *)arg;
+ DEBASSERT(arg);
+ ssize_t nwritten;
+ int oflags;
+
+ /* Call fcntl(F_GETFL) to get the file open mode.
+ *
+ * REVISIT: Consider moving aio_write into the kernel. Notice that in a
+ * system using system calls, up to three system calls may be required:
+ * (1) fcntl, (2) write or pwrite, and possibly (3) sigueue(). If aio_write
+ * were a system call, then only one would be required.
+ */
+
+ oflags = fcntl((aiocbp->aio_fildes, F_GETFL, ...)
+ if (oflags < 0)
+ {
+ int errcode = get_errno();
+ fdbg("ERROR: fcntl failed: %d\n", errode);
+ aicbp->result = -errcode;
+ }
+ else
+ {
+ /* Perform the write using:
+ *
+ * aio_fildes - File descriptor
+ * 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 = write(aiocbp->aio_fildes, aiocbp->aio_buf,
+ aiocbp->aio_nbytes);
+ }
+ else
+ {
+ nwritten = pwrite(aiocbp->aio_fildes, aiocbp->aio_buf,
+ aiocbp->aio_nbytes, aiocbp->aio_offset);
+ }
+
+ /* Set the result of the write */
+
+ if (nwritten < 0)
+ {
+ int errcode = get_errno();
+ fdbg("ERROR: write/pwrite failed: %d\n", errode);
+ DEBUGASSERT(errcode > 0);
+ aicbp->result = -errcode;
+ }
+ else
+ {
+ aicbp->result = nwritten;
+ }
+ }
+
+ /* 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
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: aio_write
+ *
+ * Description:
+ * The aio_write() function writes aiocbp->aio_nbytes to the file
+ * associated with aiocbp->aio_fildes from the buffer pointed to by
+ * aiocbp->aio_buf. The function call will return when the write request
+ * has been initiated or queued to the file or device (even when the data
+ * cannot be delivered immediately).
+ *
+ * The aiocbp value may be used as an argument to aio_error() and
+ * aio_return() in order to determine the error status and return status,
+ * respectively, of the asynchronous operation while it is proceeding.
+ *
+ * The aiocbp argument points to an aiocb structure. If the buffer pointed
+ * to by aiocbp->aio_buf or the control block pointed to by aiocbp becomes
+ * an illegal address prior to asynchronous I/O completion, then the
+ * behavior is undefined.
+ *
+ * If O_APPEND is not set for the file descriptor aio_fildes, then the
+ * requested operation will take place at the absolute position in the file
+ * as given by aio_offset, as if lseek() were called immediately prior to the
+ * operation with an offset equal to aio_offset and a whence equal to SEEK_SET.
+ * If O_APPEND is set for the file descriptor, write operations append to the
+ * file in the same order as the calls were made. After a successful call to
+ * enqueue an asynchronous I/O operation, the value of the file offset for the
+ * file is unspecified.
+ *
+ * The aiocbp->aio_lio_opcode field will be ignored by aio_write().
+ *
+ * Simultaneous asynchronous operations using the same aiocbp produce
+ * undefined results.
+ *
+ * For any system action that changes the process memory space while an
+ * synchronous I/O is outstanding to the address range being changed, the
+ * result of that action is undefined.
+ *
+ * Input Parameters:
+ * aiocbp - A pointer to an instance of struct aiocb
+ *
+ * Returned Value:
+ *
+ * The aio_write() function will return the value zero if the I/O operation
+ * is successfully queued; otherwise, the function will return the value
+ * -1 and set errno to indicate the error. The aio_write() function will
+ * ail if:
+ *
+ * EAGAIN - The requested asynchronous I/O operation was not queued due to
+ * system resource limitations.
+ *
+ * Each of the following conditions may be detected synchronously at the
+ * time of the call to aio_write(), or asynchronously. If any of the
+ * conditions below are detected synchronously, the aio_write() function
+ * will return -1 and set errno to the corresponding value. If any of the
+ * conditions below are detected asynchronously, the return status of the
+ * asynchronous operation is set to -1, and the error status of the
+ * asynchronous operation is set to the corresponding value.
+ *
+ * EBADF - The aiocbp->aio_fildes argument is not a valid file descriptor
+ * open for writing.
+ * EINVAL - The file offset value implied by aiocbp->aio_offset would be
+ * invalid, aiocbp->aio_reqprio is not a valid value, or
+ * aiocbp->aio_nbytes is an invalid value.
+ *
+ * In the case that the aio_write() successfully queues the I/O operation
+ * but the operation is subsequently cancelled or encounters an error, the
+ * return status of the asynchronous operation is one of the values
+ * normally returned by the write() function call. In addition, the error
+ * status of the asynchronous operation is set to one of the error
+ * statuses normally set by the write() function call, or one of the
+ * following values:
+ *
+ * EBADF - The aiocbp->aio_fildes argument is not a valid file descriptor
+ * open for writing.
+ * EINVAL - The file offset value implied by aiocbp->aio_offset would be
+ * invalid.
+ * ECANCELED - The requested I/O was cancelled before the I/O completed
+ * due to an explicit aio_cancel() request.
+ *
+ * The following condition may be detected synchronously or asynchronously:
+ *
+ * EFBIG - The file is a regular file, aiobcp->aio_nbytes is greater
+ * than 0, and the starting offset in aiobcp->aio_offset is at or
+ * beyond the offset maximum in the open file description associated
+ * with aiocbp->aio_fildes.
+ *
+ * POSIX Compliance:
+ * - The standard requires that if prioritized I/O is supported for this
+ * file, then the asynchronous operation will be submitted at a priority
+ * equal to a base scheduling priority minus aiocbp->aio_reqprio. If
+ * Thwrite Execution Scheduling is not supported, then the base scheduling
+ * priority is that of the calling thread.
+ *
+ * This implementation uses the NuttX work queues that run at a fixed,
+ * configured priority.
+ *
+ * - Most errors required in the standard are not detected at this point.
+ * There are no pre-queuing checks for the validity of the operation.
+ *
+ ****************************************************************************/
+
+int aio_write(FAR struct aiocb *aiocbp);
+{
+ int ret;
+
+ 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_write_worker, aiocbp, 0);
+ if (ret < 0)
+ {
+ aio->aio_result = ret;
+ set_errno(ret);
+ return ERROR;
+ }
+
+ return OK;
+}
+
+#endif /* CONFIG_LIBC_AIO */
diff --git a/nuttx/libc/aio/lio_listio.c b/nuttx/libc/aio/lio_listio.c
index 2a817c8aa..c5f6e424c 100644
--- a/nuttx/libc/aio/lio_listio.c
+++ b/nuttx/libc/aio/lio_listio.c
@@ -164,7 +164,7 @@ static pthread_addr_t lio_thread(pthread_addr_t arg)
*
* If the buffer pointed to by 'list' or the aiocb structures pointed to
* by the elements of the array 'list' become illegal addresses before all
- * asynchronous I/O completed and, if necessary, the notification is
+ * asynchronous I/O completed and, if necessary, the notification is
* sent, then the behavior is undefined. If the buffers pointed to by the
* aio_buf member of the aiocb structure pointed to by the elements of
* the array 'list' become illegal addresses prior to the asynchronous