[rtems commit] Filesystem: Add select() support for pipes
Sebastian Huber
sebh at rtems.org
Mon Jul 9 08:39:11 UTC 2012
Module: rtems
Branch: master
Commit: 1f16a9f801016b6a636e92bef4813f238e4b4f98
Changeset: http://git.rtems.org/rtems/commit/?id=1f16a9f801016b6a636e92bef4813f238e4b4f98
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Thu Apr 12 17:15:53 2012 +0200
Filesystem: Add select() support for pipes
---
cpukit/libfs/src/pipe/fifo.c | 96 ++++++++++++++++++++++++++++++++++++-----
cpukit/libfs/src/pipe/pipe.h | 2 +
2 files changed, 86 insertions(+), 12 deletions(-)
diff --git a/cpukit/libfs/src/pipe/fifo.c b/cpukit/libfs/src/pipe/fifo.c
index d80a51f..31ccfc8 100644
--- a/cpukit/libfs/src/pipe/fifo.c
+++ b/cpukit/libfs/src/pipe/fifo.c
@@ -68,6 +68,21 @@ static rtems_id pipe_semaphore = RTEMS_ID_NONE;
#include <rtems/rtems/barrier.h>
#include <rtems/score/thread.h>
+static void pipe_select_wakeup(rtems_id *id_ptr)
+{
+ rtems_id id = *id_ptr;
+
+ *id_ptr = 0;
+
+ if (id != 0) {
+ rtems_status_code sc = rtems_event_send(id, RTEMS_IOCTL_SELECT_EVENT);
+
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(sc);
+ }
+ }
+}
+
/* Set barriers to be interruptible by signals. */
static void pipe_interruptible(pipe_control_t *pipe)
{
@@ -94,10 +109,9 @@ static int pipe_alloc(
pipe_control_t *pipe;
int err = -ENOMEM;
- pipe = malloc(sizeof(pipe_control_t));
+ pipe = calloc(1, sizeof(pipe_control_t));
if (pipe == NULL)
return err;
- memset(pipe, 0, sizeof(pipe_control_t));
pipe->Size = PIPE_BUF;
pipe->Buffer = malloc(pipe->Size);
@@ -447,6 +461,7 @@ ssize_t pipe_read(
if (PIPE_EMPTY(pipe))
pipe->Start = 0;
+ pipe_select_wakeup(&pipe->select_write_task_id);
if (pipe->waitingWriters > 0)
PIPE_WAKEUPWRITERS(pipe);
read += chunk;
@@ -525,6 +540,7 @@ ssize_t pipe_write(
memcpy(pipe->Buffer + PIPE_WSTART(pipe), buffer + written, chunk);
pipe->Length += chunk;
+ pipe_select_wakeup(&pipe->select_read_task_id);
if (pipe->waitingReaders > 0)
PIPE_WAKEUPREADERS(pipe);
written += chunk;
@@ -547,6 +563,53 @@ out_nolock:
return ret;
}
+static int pipe_register_select_wakeup(
+ rtems_id *id_ptr,
+ const rtems_ioctl_select_request *request
+)
+{
+ int rv = 0;
+ rtems_id current_id = *id_ptr;
+ rtems_id request_id = request->request_task_id;
+
+ if (current_id == 0 || current_id == request_id) {
+ *id_ptr = request_id;
+ } else {
+ rv = -EINVAL;
+ }
+
+ return rv;
+}
+
+static int pipe_select(
+ pipe_control_t *pipe,
+ const rtems_ioctl_select_request *request
+)
+{
+ int rv = 0;
+
+ switch (request->kind) {
+ case RTEMS_IOCTL_SELECT_READ:
+ if (!PIPE_EMPTY(pipe)) {
+ rv = 1;
+ } else {
+ rv = pipe_register_select_wakeup(&pipe->select_read_task_id, request);
+ }
+ break;
+ case RTEMS_IOCTL_SELECT_WRITE:
+ if (PIPE_SPACE(pipe) > 0) {
+ rv = 1;
+ } else {
+ rv = pipe_register_select_wakeup(&pipe->select_write_task_id, request);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rv;
+}
+
/*
* Interface to file system ioctl.
*/
@@ -557,20 +620,29 @@ int pipe_ioctl(
rtems_libio_t *iop
)
{
- if (cmd == FIONREAD) {
- if (buffer == NULL)
- return -EFAULT;
+ int rv = 0;
- if (! PIPE_LOCK(pipe))
- return -EINTR;
+ if (buffer != NULL) {
+ if (PIPE_LOCK(pipe)) {
+ switch (cmd) {
+ case RTEMS_IOCTL_SELECT:
+ rv = pipe_select(pipe, buffer);
+ break;
+ case FIONREAD:
+ /* Return length of pipe */
+ *(unsigned int *) buffer = pipe->Length;
+ break;
+ }
- /* Return length of pipe */
- *(unsigned int *)buffer = pipe->Length;
- PIPE_UNLOCK(pipe);
- return 0;
+ PIPE_UNLOCK(pipe);
+ } else {
+ rv = -EINTR;
+ }
+ } else {
+ rv = -EFAULT;
}
- return -EINVAL;
+ return rv;
}
/*
diff --git a/cpukit/libfs/src/pipe/pipe.h b/cpukit/libfs/src/pipe/pipe.h
index 52d0a85..97358eb 100644
--- a/cpukit/libfs/src/pipe/pipe.h
+++ b/cpukit/libfs/src/pipe/pipe.h
@@ -39,6 +39,8 @@ typedef struct pipe_control {
rtems_id Semaphore;
rtems_id readBarrier; /* wait queues */
rtems_id writeBarrier;
+ rtems_id select_read_task_id;
+ rtems_id select_write_task_id;
#if 0
boolean Anonymous; /* anonymous pipe or FIFO */
#endif
More information about the vc
mailing list