summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/ChangeLog12
-rw-r--r--cpukit/Makefile.am3
-rw-r--r--cpukit/libcsupport/src/mknod.c3
-rw-r--r--cpukit/libcsupport/src/open.c4
-rw-r--r--cpukit/libcsupport/src/pipe.c10
-rw-r--r--cpukit/libfs/Makefile.am7
-rw-r--r--cpukit/libfs/preinstall.am2
-rw-r--r--cpukit/libfs/src/imfs/imfs.h17
-rw-r--r--cpukit/libfs/src/imfs/imfs_creat.c4
-rw-r--r--cpukit/libfs/src/imfs/imfs_debug.c5
-rw-r--r--cpukit/libfs/src/imfs/imfs_eval.c3
-rw-r--r--cpukit/libfs/src/imfs/imfs_fifo.c151
-rw-r--r--cpukit/libfs/src/imfs/imfs_initsupp.c11
-rw-r--r--cpukit/libfs/src/imfs/imfs_mknod.c5
-rw-r--r--cpukit/libfs/src/imfs/imfs_stat.c4
-rw-r--r--cpukit/libfs/src/imfs/memfile.c2
-rw-r--r--cpukit/libfs/src/pipe/fifo.c551
-rw-r--r--cpukit/libfs/src/pipe/pipe.c83
-rw-r--r--cpukit/libfs/src/pipe/pipe.h113
-rw-r--r--cpukit/preinstall.am4
20 files changed, 977 insertions, 17 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index df773a9660..6c7edb8e94 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,15 @@
+2008-10-14 Wei Shen <cquark@gmail.com>
+
+ * Makefile.am, preinstall.am, libcsupport/src/mknod.c,
+ libcsupport/src/open.c, libcsupport/src/pipe.c, libfs/Makefile.am,
+ libfs/preinstall.am, libfs/src/imfs/imfs.h,
+ libfs/src/imfs/imfs_creat.c, libfs/src/imfs/imfs_debug.c,
+ libfs/src/imfs/imfs_eval.c, libfs/src/imfs/imfs_initsupp.c,
+ libfs/src/imfs/imfs_mknod.c, libfs/src/imfs/imfs_stat.c,
+ libfs/src/imfs/memfile.c: Initial commit of POSIX pipe support.
+ * libfs/src/imfs/imfs_fifo.c, libfs/src/pipe/fifo.c,
+ libfs/src/pipe/pipe.c, libfs/src/pipe/pipe.h: New files.
+
2008-10-03 Joel Sherrill <joel.sherrill@oarcorp.com>
* libcsupport/src/printk.c: Addresses can be larger than integers
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index e9d916a0c6..9d4c81404a 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -79,6 +79,9 @@ include_rtems_HEADERS += include/rtems/irq-extension.h
## libfs
include_rtems_HEADERS += libfs/src/imfs/imfs.h
+## POSIX FIFO/pipe
+include_rtems_HEADERS += libfs/src/pipe/pipe.h
+
## devfs
include_rtems_HEADERS += libfs/src/devfs/devfs.h
diff --git a/cpukit/libcsupport/src/mknod.c b/cpukit/libcsupport/src/mknod.c
index c786c6d756..2d1db0fc3d 100644
--- a/cpukit/libcsupport/src/mknod.c
+++ b/cpukit/libcsupport/src/mknod.c
@@ -43,9 +43,6 @@ int mknod(
if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) )
rtems_set_errno_and_return_minus_one( EINVAL );
- if ( S_ISFIFO(mode) )
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-
rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
if ( !temp_loc.ops->evalformake_h ) {
diff --git a/cpukit/libcsupport/src/open.c b/cpukit/libcsupport/src/open.c
index e29427e568..1bc83ed7bc 100644
--- a/cpukit/libcsupport/src/open.c
+++ b/cpukit/libcsupport/src/open.c
@@ -164,8 +164,10 @@ int open(
}
rc = (*iop->handlers->open_h)( iop, pathname, flags, mode );
- if ( rc )
+ if ( rc ) {
+ rc = errno;
goto done;
+ }
/*
* Optionally truncate the file.
diff --git a/cpukit/libcsupport/src/pipe.c b/cpukit/libcsupport/src/pipe.c
index 57a682e55b..ef8c820483 100644
--- a/cpukit/libcsupport/src/pipe.c
+++ b/cpukit/libcsupport/src/pipe.c
@@ -16,11 +16,17 @@
#endif
#include <errno.h>
+#include <sys/types.h>
+
+extern int pipe_create(int filsdes[2]);
int pipe(
int filsdes[2]
)
{
- errno = ENOSYS;
- return -1;
+ if (filsdes == NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+ return pipe_create(filsdes);
}
diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am
index 1b907a46dd..a5a2537ff0 100644
--- a/cpukit/libfs/Makefile.am
+++ b/cpukit/libfs/Makefile.am
@@ -28,7 +28,7 @@ libimfs_a_SOURCES += src/imfs/imfs_chown.c src/imfs/imfs_config.c \
src/imfs/imfs_mknod.c src/imfs/imfs_mount.c src/imfs/imfs_fchmod.c \
src/imfs/imfs_unlink.c src/imfs/imfs_unmount.c src/imfs/imfs_utime.c \
src/imfs/imfs_ntype.c src/imfs/imfs_stat.c src/imfs/imfs_getchild.c \
- src/imfs/memfile.c src/imfs/deviceio.c \
+ src/imfs/memfile.c src/imfs/imfs_fifo.c src/imfs/deviceio.c \
src/imfs/imfs_handlers_device.c src/imfs/imfs_handlers_directory.c \
src/imfs/imfs_handlers_link.c src/imfs/imfs_handlers_memfile.c \
src/imfs/imfs_debug.c src/imfs/imfs_rmnod.c src/imfs/imfs_symlink.c \
@@ -43,6 +43,11 @@ libimfs_a_SOURCES += src/imfs/imfs_chown.c src/imfs/imfs_config.c \
src/devfs/devfs.h
endif
+# POSIX FIFO/pipe
+if ! UNIX
+libimfs_a_SOURCES += src/pipe/fifo.c src/pipe/pipe.c src/pipe/pipe.h
+endif
+
# dosfs
if LIBDOSFS
diff --git a/cpukit/libfs/preinstall.am b/cpukit/libfs/preinstall.am
index dba6cc4d81..7bccdb3872 100644
--- a/cpukit/libfs/preinstall.am
+++ b/cpukit/libfs/preinstall.am
@@ -5,3 +5,5 @@ $(srcdir)/preinstall.am: Makefile.am
$(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
endif
+if ! UNIX
+endif
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
index bd56bd57f4..b53a3cd8b4 100644
--- a/cpukit/libfs/src/imfs/imfs.h
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -25,6 +25,8 @@ extern "C" {
#include <limits.h>
#include <rtems/libio.h>
+#include <rtems/pipe.h>
+
/*
* File name macros
*/
@@ -59,6 +61,10 @@ typedef struct {
char *name;
} IMFS_sym_link_t;
+typedef struct {
+ pipe_control_t *pipe;
+} IMFS_fifo_t;
+
/*
* IMFS "memfile" information
*
@@ -84,7 +90,7 @@ typedef struct {
extern int imfs_rq_memfile_bytes_per_block;
extern int imfs_memfile_bytes_per_block;
-#define IMFS_MEMFILE_BYTES_PER_BLOCK imfs_memfile_bytes_per_block
+#define IMFS_MEMFILE_BYTES_PER_BLOCK imfs_memfile_bytes_per_block
#define IMFS_MEMFILE_BLOCK_SLOTS \
(IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
@@ -135,8 +141,9 @@ typedef struct {
#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
#define IMFS_LINEAR_FILE (IMFS_MEMORY_FILE + 1)
+#define IMFS_FIFO (IMFS_LINEAR_FILE + 1)
-#define IMFS_NUMBER_OF_TYPES (IMFS_LINEAR_FILE + 1)
+#define IMFS_NUMBER_OF_TYPES (IMFS_FIFO + 1)
typedef union {
IMFS_directory_t directory;
@@ -145,6 +152,7 @@ typedef union {
IMFS_sym_link_t sym_link;
IMFS_memfile_t file;
IMFS_linearfile_t linearfile;
+ IMFS_fifo_t fifo;
} IMFS_types_union;
/*
@@ -196,12 +204,12 @@ struct IMFS_jnode_tt {
_jnode->stat_ctime = (time_t) tv.tv_sec; \
} while (0)
-#define IMFS_atime_mtime_update( _jnode ) \
+#define IMFS_mtime_ctime_update( _jnode ) \
do { \
struct timeval tv; \
gettimeofday( &tv, 0 ); \
_jnode->stat_mtime = (time_t) tv.tv_sec; \
- _jnode->stat_atime = (time_t) tv.tv_sec; \
+ _jnode->stat_ctime = (time_t) tv.tv_sec; \
} while (0)
typedef struct {
@@ -230,6 +238,7 @@ extern const rtems_filesystem_file_handlers_r IMFS_directory_handlers;
extern const rtems_filesystem_file_handlers_r IMFS_device_handlers;
extern const rtems_filesystem_file_handlers_r IMFS_link_handlers;
extern const rtems_filesystem_file_handlers_r IMFS_memfile_handlers;
+extern const rtems_filesystem_file_handlers_r IMFS_fifo_handlers;
extern const rtems_filesystem_operations_table IMFS_ops;
extern const rtems_filesystem_operations_table miniIMFS_ops;
extern const rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c
index ccf88bdf64..946e71d729 100644
--- a/cpukit/libfs/src/imfs/imfs_creat.c
+++ b/cpukit/libfs/src/imfs/imfs_creat.c
@@ -112,6 +112,10 @@ IMFS_jnode_t *IMFS_create_node(
node->info.file.triply_indirect = 0;
break;
+ case IMFS_FIFO:
+ node->info.fifo.pipe = NULL;
+ break;
+
default:
assert(0);
break;
diff --git a/cpukit/libfs/src/imfs/imfs_debug.c b/cpukit/libfs/src/imfs/imfs_debug.c
index d766c5e8b1..eb7541bb6a 100644
--- a/cpukit/libfs/src/imfs/imfs_debug.c
+++ b/cpukit/libfs/src/imfs/imfs_debug.c
@@ -98,6 +98,11 @@ void IMFS_print_jnode(
assert(0);
break;
+ case IMFS_FIFO:
+ fprintf(stdout, " FIFO not printed\n" );
+ assert(0);
+ break;
+
default:
fprintf(stdout, " bad type %d\n", the_jnode->type );
assert(0);
diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c
index 9d8328d3a5..8c72fca049 100644
--- a/cpukit/libfs/src/imfs/imfs_eval.c
+++ b/cpukit/libfs/src/imfs/imfs_eval.c
@@ -57,6 +57,9 @@ int IMFS_Set_handlers(
case IMFS_MEMORY_FILE:
loc->handlers = fs_info->memfile_handlers;
break;
+ case IMFS_FIFO:
+ loc->handlers = &IMFS_fifo_handlers;
+ break;
}
return 0;
diff --git a/cpukit/libfs/src/imfs/imfs_fifo.c b/cpukit/libfs/src/imfs/imfs_fifo.c
new file mode 100644
index 0000000000..97fef98db6
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_fifo.c
@@ -0,0 +1,151 @@
+/*
+ * imfs_fifo.c: FIFO support for IMFS
+ *
+ * Author: Wei Shen <cquark@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#include "imfs.h"
+
+#define JNODE2PIPE(_jnode) ( (_jnode)->info.fifo.pipe )
+
+#define LIBIO2PIPE(_iop) ( JNODE2PIPE((IMFS_jnode_t *)(_iop)->file_info) )
+
+/* Set errno and return -1 if error, else return _err */
+#define IMFS_FIFO_RETURN(_err) \
+do { \
+ if (_err < 0) \
+ rtems_set_errno_and_return_minus_one(-_err); \
+ return _err; \
+} while (0)
+
+int IMFS_fifo_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ uint32_t flag,
+ uint32_t mode
+)
+{
+ IMFS_jnode_t *jnode = iop->file_info;
+
+ int err = fifo_open(&JNODE2PIPE(jnode), iop);
+ IMFS_FIFO_RETURN(err);
+}
+
+int IMFS_fifo_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *jnode = iop->file_info;
+
+ int err = pipe_release(&JNODE2PIPE(jnode), iop);
+
+ if (! err) {
+ iop->flags &= ~LIBIO_FLAGS_OPEN;
+ /* Free jnode if file is already unlinked and no one opens it */
+ if (! rtems_libio_is_file_open(jnode) && jnode->st_nlink < 1)
+ free(jnode);
+ }
+
+ IMFS_FIFO_RETURN(err);
+}
+
+ssize_t IMFS_fifo_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ size_t count
+)
+{
+ IMFS_jnode_t *jnode = iop->file_info;
+
+ int err = pipe_read(JNODE2PIPE(jnode), buffer, count, iop);
+ if (err > 0)
+ IMFS_update_atime(jnode);
+
+ IMFS_FIFO_RETURN(err);
+}
+
+ssize_t IMFS_fifo_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ size_t count
+)
+{
+ IMFS_jnode_t *jnode = iop->file_info;
+
+ int err = pipe_write(JNODE2PIPE(jnode), buffer, count, iop);
+ if (err > 0) {
+ IMFS_mtime_ctime_update(jnode);
+ }
+
+ IMFS_FIFO_RETURN(err);
+}
+
+int IMFS_fifo_ioctl(
+ rtems_libio_t *iop,
+ uint32_t command,
+ void *buffer
+)
+{
+ int err;
+
+ if (command == FIONBIO) {
+ if (buffer == NULL)
+ err = -EFAULT;
+ else {
+ if (*(int *)buffer)
+ iop->flags |= LIBIO_FLAGS_NO_DELAY;
+ else
+ iop->flags &= ~LIBIO_FLAGS_NO_DELAY;
+ return 0;
+ }
+ }
+ else
+ err = pipe_ioctl(LIBIO2PIPE(iop), command, buffer, iop);
+
+ IMFS_FIFO_RETURN(err);
+}
+
+int IMFS_fifo_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ int err = pipe_lseek(LIBIO2PIPE(iop), offset, whence, iop);
+ IMFS_FIFO_RETURN(err);
+}
+
+/*
+ * Handler table for IMFS FIFO nodes
+ */
+
+const rtems_filesystem_file_handlers_r IMFS_fifo_handlers = {
+ IMFS_fifo_open,
+ IMFS_fifo_close,
+ IMFS_fifo_read,
+ IMFS_fifo_write,
+ IMFS_fifo_ioctl,
+ IMFS_fifo_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ NULL, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ NULL, /* fdatasync */
+ IMFS_fcntl,
+ IMFS_rmnod,
+};
diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c
index 62d6b11c7a..648150257b 100644
--- a/cpukit/libfs/src/imfs/imfs_initsupp.c
+++ b/cpukit/libfs/src/imfs/imfs_initsupp.c
@@ -47,17 +47,17 @@ static int IMFS_determine_bytes_per_block(
* check, whether requested bytes per block is valid
*/
for (bit_mask = 16;
- !is_valid && (bit_mask <= 512);
+ !is_valid && (bit_mask <= 512);
bit_mask <<= 1) {
if (bit_mask == requested_bytes_per_block) {
is_valid = true;
}
}
- *dest_bytes_per_block = ((is_valid)
+ *dest_bytes_per_block = ((is_valid)
? requested_bytes_per_block
: default_bytes_per_block);
return 0;
-
+
}
@@ -81,7 +81,7 @@ int IMFS_initialize_support(
IMFS_determine_bytes_per_block(&imfs_memfile_bytes_per_block,
imfs_rq_memfile_bytes_per_block,
IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK);
-
+
/*
* Create the root node
*
@@ -121,5 +121,8 @@ int IMFS_initialize_support(
jnode = temp_mt_entry->mt_fs_root.node_access;
jnode->st_ino = fs_info->ino_count;
+ /* Initialize POSIX FIFO/pipe module */
+ rtems_pipe_initialize();
+
return 0;
}
diff --git a/cpukit/libfs/src/imfs/imfs_mknod.c b/cpukit/libfs/src/imfs/imfs_mknod.c
index abb9ab4052..9d35e61922 100644
--- a/cpukit/libfs/src/imfs/imfs_mknod.c
+++ b/cpukit/libfs/src/imfs/imfs_mknod.c
@@ -54,7 +54,10 @@ int IMFS_mknod(
else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
type = IMFS_DEVICE;
rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
- } else {
+ }
+ else if (S_ISFIFO(mode))
+ type = IMFS_FIFO;
+ else {
rtems_set_errno_and_return_minus_one( EINVAL );
}
diff --git a/cpukit/libfs/src/imfs/imfs_stat.c b/cpukit/libfs/src/imfs/imfs_stat.c
index 422e954ed1..76564811e9 100644
--- a/cpukit/libfs/src/imfs/imfs_stat.c
+++ b/cpukit/libfs/src/imfs/imfs_stat.c
@@ -49,6 +49,10 @@ int IMFS_stat(
buf->st_size = 0;
break;
+ case IMFS_FIFO:
+ buf->st_size = 0;
+ break;
+
default:
rtems_set_errno_and_return_minus_one( ENOTSUP );
break;
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
index 2391373acb..a0a89f64ec 100644
--- a/cpukit/libfs/src/imfs/memfile.c
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -844,7 +844,7 @@ fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
copied += to_copy;
}
- IMFS_atime_mtime_update( the_jnode );
+ IMFS_mtime_ctime_update( the_jnode );
return copied;
}
diff --git a/cpukit/libfs/src/pipe/fifo.c b/cpukit/libfs/src/pipe/fifo.c
new file mode 100644
index 0000000000..1c194c2030
--- /dev/null
+++ b/cpukit/libfs/src/pipe/fifo.c
@@ -0,0 +1,551 @@
+/*
+ * fifo.c: POSIX FIFO/pipe for RTEMS
+ *
+ * Author: Wei Shen <cquark@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include "pipe.h"
+
+
+#define MIN(a, b) ((a) < (b)? (a): (b))
+
+#define LIBIO_ACCMODE(_iop) ((_iop)->flags & LIBIO_FLAGS_READ_WRITE)
+#define LIBIO_NODELAY(_iop) ((_iop)->flags & LIBIO_FLAGS_NO_DELAY)
+
+extern uint16_t rtems_pipe_no;
+static rtems_id rtems_pipe_semaphore = 0;
+
+
+#define PIPE_EMPTY(_pipe) (_pipe->Length == 0)
+#define PIPE_FULL(_pipe) (_pipe->Length == _pipe->Size)
+#define PIPE_SPACE(_pipe) (_pipe->Size - _pipe->Length)
+#define PIPE_WSTART(_pipe) ((_pipe->Start + _pipe->Length) % _pipe->Size)
+
+#define PIPE_LOCK(_pipe) \
+ ( rtems_semaphore_obtain(_pipe->Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT) \
+ == RTEMS_SUCCESSFUL )
+
+#define PIPE_UNLOCK(_pipe) rtems_semaphore_release(_pipe->Semaphore)
+
+#define PIPE_READWAIT(_pipe) \
+ ( rtems_barrier_wait(_pipe->readBarrier, RTEMS_NO_TIMEOUT) \
+ == RTEMS_SUCCESSFUL)
+
+#define PIPE_WRITEWAIT(_pipe) \
+ ( rtems_barrier_wait(_pipe->writeBarrier, RTEMS_NO_TIMEOUT) \
+ == RTEMS_SUCCESSFUL)
+
+#define PIPE_WAKEUPREADERS(_pipe) \
+ do {uint32_t n; rtems_barrier_release(_pipe->readBarrier, &n); } while(0)
+
+#define PIPE_WAKEUPWRITERS(_pipe) \
+ do {uint32_t n; rtems_barrier_release(_pipe->writeBarrier, &n); } while(0)
+
+
+#ifdef RTEMS_POSIX_API
+
+#include <rtems/rtems/barrier.inl>
+#include <rtems/score/thread.inl>
+
+/* Set barriers to be interruptible by signals. */
+static void pipe_interruptible(pipe_control_t *pipe)
+{
+ Objects_Locations location;
+
+ _Barrier_Get(pipe->readBarrier, &location)->Barrier.Wait_queue.state
+ |= STATES_INTERRUPTIBLE_BY_SIGNAL;
+ _Thread_Enable_dispatch();
+ _Barrier_Get(pipe->writeBarrier, &location)->Barrier.Wait_queue.state
+ |= STATES_INTERRUPTIBLE_BY_SIGNAL;
+ _Thread_Enable_dispatch();
+}
+#endif
+
+/*
+ * Alloc pipe control structure, buffer, and resources.
+ * Called with rtems_pipe_semaphore held.
+ */
+static int pipe_alloc(
+ pipe_control_t **pipep
+)
+{
+ static char c = 'a';
+ pipe_control_t *pipe;
+ int err = -ENOMEM;
+
+ pipe = malloc(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);
+ if (! pipe->Buffer)
+ goto err_buf;
+
+ err = -EINTR;
+ if (rtems_barrier_create(
+ rtems_build_name ('P', 'I', 'r', c),
+ RTEMS_BARRIER_MANUAL_RELEASE, 0,
+ &pipe->readBarrier) != RTEMS_SUCCESSFUL)
+ goto err_rbar;
+ if (rtems_barrier_create(
+ rtems_build_name ('P', 'I', 'w', c),
+ RTEMS_BARRIER_MANUAL_RELEASE, 0,
+ &pipe->writeBarrier) != RTEMS_SUCCESSFUL)
+ goto err_wbar;
+ if (rtems_semaphore_create(
+ rtems_build_name ('P', 'I', 's', c), 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_FIFO,
+ RTEMS_NO_PRIORITY, &pipe->Semaphore) != RTEMS_SUCCESSFUL)
+ goto err_sem;
+
+#ifdef RTEMS_POSIX_API
+ pipe_interruptible(pipe);
+#endif
+
+ *pipep = pipe;
+ if (c ++ == 'z')
+ c = 'a';
+ return 0;
+
+err_sem:
+ rtems_barrier_delete(pipe->writeBarrier);
+err_wbar:
+ rtems_barrier_delete(pipe->readBarrier);
+err_rbar:
+ free(pipe->Buffer);
+err_buf:
+ free(pipe);
+ return err;
+}
+
+/* Called with rtems_pipe_semaphore held. */
+static inline void pipe_free(
+ pipe_control_t *pipe
+)
+{
+ rtems_barrier_delete(pipe->readBarrier);
+ rtems_barrier_delete(pipe->writeBarrier);
+ rtems_semaphore_delete(pipe->Semaphore);
+ free(pipe->Buffer);
+ free(pipe);
+}
+
+/*
+ * If called with *pipep = NULL, pipe_new will call pipe_alloc to allocate a
+ * pipe control structure and set *pipep to its address.
+ * pipe is locked, when pipe_new returns with no error.
+ */
+static int pipe_new(
+ pipe_control_t **pipep
+)
+{
+ pipe_control_t *pipe;
+ int err = 0;
+
+ if (rtems_semaphore_obtain(rtems_pipe_semaphore,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL)
+ return -EINTR;
+
+ pipe = *pipep;
+ if (pipe == NULL) {
+ err = pipe_alloc(&pipe);
+ if (err)
+ goto out;
+ }
+
+ if (! PIPE_LOCK(pipe))
+ err = -EINTR;
+
+ if (*pipep == NULL) {
+ if (err)
+ pipe_free(pipe);
+ else
+ *pipep = pipe;
+ }
+
+out:
+ rtems_semaphore_release(rtems_pipe_semaphore);
+ return err;
+}
+
+/*
+ * Interface to file system close.
+ *
+ * *pipep points to pipe control structure. When the last user releases pipe,
+ * it will be set to NULL.
+ */
+int pipe_release(
+ pipe_control_t **pipep,
+ rtems_libio_t *iop
+)
+{
+ pipe_control_t *pipe = *pipep;
+ uint32_t mode;
+
+ rtems_status_code sc;
+ sc = rtems_semaphore_obtain(pipe->Semaphore,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ /* WARN pipe not released! */
+ if(sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(sc);
+
+ mode = LIBIO_ACCMODE(iop);
+ if (mode & LIBIO_FLAGS_READ)
+ pipe->Readers --;
+ if (mode & LIBIO_FLAGS_WRITE)
+ pipe->Writers --;
+
+ sc = rtems_semaphore_obtain(rtems_pipe_semaphore,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ /* WARN pipe not freed and pipep not set to NULL! */
+ if(sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(sc);
+
+ PIPE_UNLOCK(pipe);
+
+ if (pipe->Readers == 0 && pipe->Writers == 0) {
+#if 0
+ /* To delete an anonymous pipe file when all users closed it */
+ if (pipe->Anonymous)
+ delfile = TRUE;
+#endif
+ pipe_free(pipe);
+ *pipep = NULL;
+ }
+ else if (pipe->Readers == 0 && mode != LIBIO_FLAGS_WRITE)
+ /* Notify waiting Writers that all their partners left */
+ PIPE_WAKEUPWRITERS(pipe);
+ else if (pipe->Writers == 0 && mode != LIBIO_FLAGS_READ)
+ PIPE_WAKEUPREADERS(pipe);
+
+ rtems_semaphore_release(rtems_pipe_semaphore);
+
+#if 0
+ if (! delfile)
+ return 0;
+ if (iop->pathinfo.ops->unlink_h == NULL)
+ return 0;
+
+ /* This is safe for IMFS, but how about other FSes? */
+ iop->flags &= ~LIBIO_FLAGS_OPEN;
+ if(iop->pathinfo.ops->unlink_h(&iop->pathinfo))
+ return -errno;
+#endif
+
+ return 0;
+}
+
+/*
+ * Interface to file system open.
+ *
+ * *pipep points to pipe control structure. If called with *pipep = NULL,
+ * fifo_open will try allocating and initializing a control structure. If the
+ * call succeeds, *pipep will be set to address of new control structure.
+ */
+int fifo_open(
+ pipe_control_t **pipep,
+ rtems_libio_t *iop
+)
+{
+ pipe_control_t *pipe;
+ uint prevCounter;
+ int err;
+
+ err = pipe_new(pipep);
+ if (err)
+ return err;
+ pipe = *pipep;
+
+ switch (LIBIO_ACCMODE(iop)) {
+ case LIBIO_FLAGS_READ:
+ pipe->readerCounter ++;
+ if (pipe->Readers ++ == 0)
+ PIPE_WAKEUPWRITERS(pipe);
+
+ if (pipe->Writers == 0) {
+ /* Not an error */
+ if (LIBIO_NODELAY(iop))
+ break;
+
+ prevCounter = pipe->writerCounter;
+ err = -EINTR;
+ /* Wait until a writer opens the pipe */
+ do {
+ PIPE_UNLOCK(pipe);
+ if (! PIPE_READWAIT(pipe))
+ goto out_error;
+ if (! PIPE_LOCK(pipe))
+ goto out_error;
+ } while (prevCounter == pipe->writerCounter);
+ }
+ break;
+
+ case LIBIO_FLAGS_WRITE:
+ if (pipe->Readers == 0 && LIBIO_NODELAY(iop)) {
+ err = -ENXIO;
+ goto out_error;
+ }
+
+ pipe->writerCounter ++;
+ if (pipe->Writers ++ == 0)
+ PIPE_WAKEUPREADERS(pipe);
+
+ if (pipe->Readers == 0) {
+ prevCounter = pipe->readerCounter;
+ err = -EINTR;
+ do {
+ PIPE_UNLOCK(pipe);
+ if (! PIPE_WRITEWAIT(pipe))
+ goto out_error;
+ if (! PIPE_LOCK(pipe))
+ goto out_error;
+ } while (prevCounter == pipe->readerCounter);
+ }
+ break;
+
+ case LIBIO_FLAGS_READ_WRITE:
+ pipe->readerCounter ++;
+ if (pipe->Readers ++ == 0)
+ PIPE_WAKEUPWRITERS(pipe);
+ pipe->writerCounter ++;
+ if (pipe->Writers ++ == 0)
+ PIPE_WAKEUPREADERS(pipe);
+ break;
+ }
+
+ PIPE_UNLOCK(pipe);
+ return 0;
+
+out_error:
+ pipe_release(pipep, iop);
+ return err;
+}
+
+/*
+ * Interface to file system read.
+ */
+ssize_t pipe_read(
+ pipe_control_t *pipe,
+ void *buffer,
+ size_t count,
+ rtems_libio_t *iop
+)
+{
+ int chunk, chunk1, read = 0, ret = 0;
+
+ if (! PIPE_LOCK(pipe))
+ return -EINTR;
+
+ while (read < count) {
+ while (PIPE_EMPTY(pipe)) {
+ /* Not an error */
+ if (pipe->Writers == 0)
+ goto out_locked;
+
+ if (LIBIO_NODELAY(iop)) {
+ ret = -EAGAIN;
+ goto out_locked;
+ }
+
+ /* Wait until pipe is no more empty or no writer exists */
+ pipe->waitingReaders ++;
+ PIPE_UNLOCK(pipe);
+ if (! PIPE_READWAIT(pipe))
+ ret = -EINTR;
+ if (! PIPE_LOCK(pipe)) {
+ /* WARN waitingReaders not restored! */
+ ret = -EINTR;
+ goto out_nolock;
+ }
+ pipe->waitingReaders --;
+ if (ret != 0)
+ goto out_locked;
+ }
+
+ /* Read chunk bytes */
+ chunk = MIN(count - read, pipe->Length);
+ chunk1 = pipe->Size - pipe->Start;
+ if (chunk > chunk1) {
+ memcpy(buffer + read, pipe->Buffer + pipe->Start, chunk1);
+ memcpy(buffer + read + chunk1, pipe->Buffer, chunk - chunk1);
+ }
+ else
+ memcpy(buffer + read, pipe->Buffer + pipe->Start, chunk);
+
+ pipe->Start += chunk;
+ pipe->Start %= pipe->Size;
+ pipe->Length -= chunk;
+ /* For buffering optimization */
+ if (PIPE_EMPTY(pipe))
+ pipe->Start = 0;
+
+ if (pipe->waitingWriters > 0)
+ PIPE_WAKEUPWRITERS(pipe);
+ read += chunk;
+ }
+
+out_locked:
+ PIPE_UNLOCK(pipe);
+
+out_nolock:
+ if (read > 0)
+ return read;
+ return ret;
+}
+
+/*
+ * Interface to file system write.
+ */
+ssize_t pipe_write(
+ pipe_control_t *pipe,
+ const void *buffer,
+ size_t count,
+ rtems_libio_t *iop
+)
+{
+ int chunk, chunk1, written = 0, ret = 0;
+
+ /* Write nothing */
+ if (count == 0)
+ return 0;
+
+ if (! PIPE_LOCK(pipe))
+ return -EINTR;
+
+ if (pipe->Readers == 0) {
+ ret = -EPIPE;
+ goto out_locked;
+ }
+
+ /* Write of PIPE_BUF bytes or less shall not be interleaved */
+ chunk = count <= pipe->Size ? count : 1;
+
+ while (written < count) {
+ while (PIPE_SPACE(pipe) < chunk) {
+ if (LIBIO_NODELAY(iop)) {
+ ret = -EAGAIN;
+ goto out_locked;
+ }
+
+ /* Wait until there is chunk bytes space or no reader exists */
+ pipe->waitingWriters ++;
+ PIPE_UNLOCK(pipe);
+ if (! PIPE_WRITEWAIT(pipe))
+ ret = -EINTR;
+ if (! PIPE_LOCK(pipe)) {
+ /* WARN waitingWriters not restored! */
+ ret = -EINTR;
+ goto out_nolock;
+ }
+ pipe->waitingWriters --;
+ if (ret != 0)
+ goto out_locked;
+
+ if (pipe->Readers == 0) {
+ ret = -EPIPE;
+ goto out_locked;
+ }
+ }
+
+ chunk = MIN(count - written, PIPE_SPACE(pipe));
+ chunk1 = pipe->Size - PIPE_WSTART(pipe);
+ if (chunk > chunk1) {
+ memcpy(pipe->Buffer + PIPE_WSTART(pipe), buffer + written, chunk1);
+ memcpy(pipe->Buffer, buffer + written + chunk1, chunk - chunk1);
+ }
+ else
+ memcpy(pipe->Buffer + PIPE_WSTART(pipe), buffer + written, chunk);
+
+ pipe->Length += chunk;
+ if (pipe->waitingReaders > 0)
+ PIPE_WAKEUPREADERS(pipe);
+ written += chunk;
+ /* Write of more than PIPE_BUF bytes can be interleaved */
+ chunk = 1;
+ }
+
+out_locked:
+ PIPE_UNLOCK(pipe);
+
+out_nolock:
+#ifdef RTEMS_POSIX_API
+ /* Signal SIGPIPE */
+ if (ret == -EPIPE)
+ kill(getpid(), SIGPIPE);
+#endif
+
+ if (written > 0)
+ return written;
+ return ret;
+}
+
+/*
+ * Interface to file system ioctl.
+ */
+int pipe_ioctl(
+ pipe_control_t *pipe,
+ uint32_t cmd,
+ void *buffer,
+ rtems_libio_t *iop
+)
+{
+ if (cmd == FIONREAD) {
+ if (buffer == NULL)
+ return -EFAULT;
+
+ if (! PIPE_LOCK(pipe))
+ return -EINTR;
+
+ /* Return length of pipe */
+ *(uint *)buffer = pipe->Length;
+ PIPE_UNLOCK(pipe);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * Interface to file system lseek.
+ */
+int pipe_lseek(
+ pipe_control_t *pipe,
+ off_t offset,
+ int whence,
+ rtems_libio_t *iop
+)
+{
+ /* Seek on pipe is not supported */
+ return -ESPIPE;
+}
+
+/*
+ * Initialization of FIFO/pipe module.
+ */
+void rtems_pipe_initialize (void)
+{
+ if (rtems_pipe_semaphore)
+ return;
+
+ rtems_status_code sc;
+ sc = rtems_semaphore_create(
+ rtems_build_name ('P', 'I', 'P', 'E'), 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY, &rtems_pipe_semaphore);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+
+ rtems_interval now;
+ rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ rtems_pipe_no = now;
+}
diff --git a/cpukit/libfs/src/pipe/pipe.c b/cpukit/libfs/src/pipe/pipe.c
new file mode 100644
index 0000000000..339aa42f4e
--- /dev/null
+++ b/cpukit/libfs/src/pipe/pipe.c
@@ -0,0 +1,83 @@
+/*
+ * pipe.c: anonymous pipe
+ *
+ * Author: Wei Shen <cquark@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/* Incremental number added to names of anonymous pipe files */
+uint16_t rtems_pipe_no = 0;
+
+/*
+ * Called by pipe() to create an anonymous pipe.
+ */
+int pipe_create(
+ int filsdes[2]
+)
+{
+ rtems_filesystem_location_info_t loc;
+ rtems_libio_t *iop;
+ int err = 0;
+
+ /* Create /tmp if not exists */
+ if (rtems_filesystem_evaluate_path("/tmp", RTEMS_LIBIO_PERMS_RWX, &loc, TRUE)
+ != 0) {
+ if (errno != ENOENT)
+ return -1;
+ if (mkdir("/tmp", S_IRWXU|S_IRWXG|S_IRWXO|S_ISVTX) != 0)
+ return -1;
+ }
+ else
+ rtems_filesystem_freenode(&loc);
+
+ /* /tmp/.fifoXXXX */
+ char fifopath[15];
+ memcpy(fifopath, "/tmp/.fifo", 10);
+ sprintf(fifopath + 10, "%04x", rtems_pipe_no ++);
+
+ /* Try creating FIFO file until find an available file name */
+ while (mkfifo(fifopath, S_IRUSR|S_IWUSR) != 0) {
+ if (errno != EEXIST)
+ return -1;
+ /* Just try once... */
+ return -1;
+ sprintf(fifopath + 10, "%04x", rtems_pipe_no ++);
+ }
+
+ /* Non-blocking open to avoid waiting for writers */
+ filsdes[0] = open(fifopath, O_RDONLY | O_NONBLOCK);
+ if (filsdes[0] < 0) {
+ err = errno;
+ goto out;
+ }
+
+ /* Reset open file to blocking mode */
+ iop = rtems_libio_iop(filsdes[0]);
+ iop->flags &= ~LIBIO_FLAGS_NO_DELAY;
+
+ filsdes[1] = open(fifopath, O_WRONLY);
+
+ if (filsdes[1] < 0) {
+ err = errno;
+ close(filsdes[0]);
+ }
+
+out:
+ /* Delete file at errors, or else if pipe is successfully created
+ the file node will be deleted after it is closed by all. */
+ unlink(fifopath);
+
+ if (! err)
+ return 0;
+ rtems_set_errno_and_return_minus_one(err);
+}
diff --git a/cpukit/libfs/src/pipe/pipe.h b/cpukit/libfs/src/pipe/pipe.h
new file mode 100644
index 0000000000..54f7525524
--- /dev/null
+++ b/cpukit/libfs/src/pipe/pipe.h
@@ -0,0 +1,113 @@
+/*
+ * pipe.h: header of POSIX FIFO/pipe
+ *
+ * Author: Wei Shen <cquark@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_PIPE_H
+#define _RTEMS_PIPE_H
+
+#include <rtems/libio.h>
+
+/* Control block to manage each pipe */
+typedef struct pipe_control {
+ char *Buffer;
+ uint Size;
+ uint Start;
+ uint Length;
+ uint Readers;
+ uint Writers;
+ uint waitingReaders;
+ uint waitingWriters;
+ uint readerCounter; /* incremental counters */
+ uint writerCounter; /* for differentiation of successive opens */
+ rtems_id Semaphore;
+ rtems_id readBarrier; /* wait queues */
+ rtems_id writeBarrier;
+#if 0
+ boolean Anonymous; /* anonymous pipe or FIFO */
+#endif
+} pipe_control_t;
+
+/*
+ * Called by pipe() to create an anonymous pipe.
+ */
+int pipe_create(
+ int filsdes[2]
+);
+
+/*
+ * Interface to file system close.
+ *
+ * *pipep points to pipe control structure. When the last user releases pipe,
+ * it will be set to NULL.
+ */
+int pipe_release(
+ pipe_control_t **pipep,
+ rtems_libio_t *iop
+);
+
+/*
+ * Interface to file system open.
+ *
+ * *pipep points to pipe control structure. If called with *pipep = NULL,
+ * fifo_open will try allocating and initializing a control structure. If the
+ * call succeeds, *pipep will be set to address of new control structure.
+ */
+int fifo_open(
+ pipe_control_t **pipep,
+ rtems_libio_t *iop
+);
+
+/*
+ * Interface to file system read.
+ */
+ssize_t pipe_read(
+ pipe_control_t *pipe,
+ void *buffer,
+ size_t count,
+ rtems_libio_t *iop
+);
+
+/*
+ * Interface to file system write.
+ */
+ssize_t pipe_write(
+ pipe_control_t *pipe,
+ const void *buffer,
+ size_t count,
+ rtems_libio_t *iop
+);
+
+/*
+ * Interface to file system ioctl.
+ */
+int pipe_ioctl(
+ pipe_control_t *pipe,
+ uint32_t cmd,
+ void *buffer,
+ rtems_libio_t *iop
+);
+
+/*
+ * Interface to file system lseek.
+ */
+int pipe_lseek(
+ pipe_control_t *pipe,
+ off_t offset,
+ int whence,
+ rtems_libio_t *iop
+);
+
+/*
+ * Initialization of FIFO/pipe module.
+ */
+void rtems_pipe_initialize (void);
+
+#endif /* #define _RTEMS_PIPE_H */
diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am
index 3977050929..34b82f58f8 100644
--- a/cpukit/preinstall.am
+++ b/cpukit/preinstall.am
@@ -146,6 +146,10 @@ $(PROJECT_INCLUDE)/rtems/imfs.h: libfs/src/imfs/imfs.h $(PROJECT_INCLUDE)/rtems/
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/imfs.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/imfs.h
+$(PROJECT_INCLUDE)/rtems/pipe.h: libfs/src/pipe/pipe.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/pipe.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/pipe.h
+
$(PROJECT_INCLUDE)/rtems/devfs.h: libfs/src/devfs/devfs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/devfs.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/devfs.h