Module: xenomai-forge
Branch: master
Commit: cacb53091dd395a015212154a951b03a268676c9
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=cacb53091dd395a015212154a951b03a268676c9

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sat Nov 12 19:25:14 2011 +0100

alchemy: introduce message pipes (Cobalt only)

---

 include/alchemy/Makefile.am |    1 +
 include/alchemy/Makefile.in |    1 +
 include/alchemy/pipe.h      |   78 ++++++++++++
 lib/alchemy/Makefile.am     |    6 +
 lib/alchemy/Makefile.in     |   51 ++++----
 lib/alchemy/pipe.c          |  291 +++++++++++++++++++++++++++++++++++++++++++
 lib/alchemy/pipe.h          |   37 ++++++
 7 files changed, 437 insertions(+), 28 deletions(-)

diff --git a/include/alchemy/Makefile.am b/include/alchemy/Makefile.am
index 6264677..1216fc4 100644
--- a/include/alchemy/Makefile.am
+++ b/include/alchemy/Makefile.am
@@ -5,6 +5,7 @@ includesub_HEADERS =    \
        buffer.h        \
        cond.h          \
        mutex.h         \
+       pipe.h          \
        queue.h         \
        sem.h           \
        task.h          \
diff --git a/include/alchemy/Makefile.in b/include/alchemy/Makefile.in
index 68d5063..553c483 100644
--- a/include/alchemy/Makefile.in
+++ b/include/alchemy/Makefile.in
@@ -244,6 +244,7 @@ includesub_HEADERS = \
        buffer.h        \
        cond.h          \
        mutex.h         \
+       pipe.h          \
        queue.h         \
        sem.h           \
        task.h          \
diff --git a/include/alchemy/pipe.h b/include/alchemy/pipe.h
new file mode 100644
index 0000000..2e5ced7
--- /dev/null
+++ b/include/alchemy/pipe.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 Philippe Gerum <r...@xenomai.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+
+#ifndef _XENOMAI_ALCHEMY_PIPE_H
+#define _XENOMAI_ALCHEMY_PIPE_H
+
+#include <stdint.h>
+#include <alchemy/timer.h>
+
+/* Creation flags. */
+#define P_MINOR_AUTO   XNPIPE_MINOR_AUTO
+
+/* Operation flags. */
+#define P_URGENT  0x1
+#define P_NORMAL  0x0
+
+struct RT_PIPE {
+       uintptr_t handle;
+};
+
+typedef struct RT_PIPE RT_PIPE;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int rt_pipe_create(RT_PIPE *pipe,
+                  const char *name,
+                  int minor,
+                  size_t poolsize);
+
+int rt_pipe_delete(RT_PIPE *pipe);
+
+ssize_t rt_pipe_read(RT_PIPE *pipe,
+                    void *buf,
+                    size_t size,
+                    RTIME timeout);
+
+ssize_t rt_pipe_read_until(RT_PIPE *pipe,
+                          void *buf,
+                          size_t size,
+                          RTIME timeout);
+
+ssize_t rt_pipe_write(RT_PIPE *pipe,
+                     const void *buf,
+                     size_t size,
+                     int mode);
+
+ssize_t rt_pipe_stream(RT_PIPE *pipe,
+                      const void *buf,
+                      size_t size);
+
+int rt_pipe_bind(RT_PIPE *pipe,
+                const char *name,
+                RTIME timeout);
+
+int rt_pipe_unbind(RT_PIPE *pipe);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _XENOMAI_ALCHEMY_PIPE_H */
diff --git a/lib/alchemy/Makefile.am b/lib/alchemy/Makefile.am
index 4632394..2f6a4ea 100644
--- a/lib/alchemy/Makefile.am
+++ b/lib/alchemy/Makefile.am
@@ -28,6 +28,12 @@ libalchemy_la_SOURCES =      \
        timer.c         \
        timer.h
 
+if XENO_COBALT
+libalchemy_la_SOURCES +=       \
+       pipe.c                  \
+       pipe.h
+endif
+
 libalchemy_la_CPPFLAGS = \
        @XENO_USER_CFLAGS@ \
        -I$(top_srcdir)/include \
diff --git a/lib/alchemy/Makefile.in b/lib/alchemy/Makefile.in
index 43be5b4..c46ebc5 100644
--- a/lib/alchemy/Makefile.in
+++ b/lib/alchemy/Makefile.in
@@ -35,6 +35,10 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
+@XENO_COBALT_TRUE@am__append_1 = \
+@XENO_COBALT_TRUE@     pipe.c                  \
+@XENO_COBALT_TRUE@     pipe.h
+
 subdir = lib/alchemy
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in COPYING
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -76,13 +80,18 @@ am__base_list = \
 am__installdirs = "$(DESTDIR)$(libdir)"
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libalchemy_la_LIBADD =
+am__libalchemy_la_SOURCES_DIST = init.c internal.c internal.h \
+       reference.h alarm.c alarm.h buffer.c buffer.h cond.c cond.h \
+       event.c event.h heap.c heap.h mutex.c mutex.h queue.c queue.h \
+       task.c task.h sem.c sem.h timer.c timer.h pipe.c pipe.h
+@XENO_COBALT_TRUE@am__objects_1 = libalchemy_la-pipe.lo
 am_libalchemy_la_OBJECTS = libalchemy_la-init.lo \
        libalchemy_la-internal.lo libalchemy_la-alarm.lo \
        libalchemy_la-buffer.lo libalchemy_la-cond.lo \
        libalchemy_la-event.lo libalchemy_la-heap.lo \
        libalchemy_la-mutex.lo libalchemy_la-queue.lo \
        libalchemy_la-task.lo libalchemy_la-sem.lo \
-       libalchemy_la-timer.lo
+       libalchemy_la-timer.lo $(am__objects_1)
 libalchemy_la_OBJECTS = $(am_libalchemy_la_OBJECTS)
 libalchemy_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -101,7 +110,7 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) 
$(LIBTOOLFLAGS) \
        --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
        $(LDFLAGS) -o $@
 SOURCES = $(libalchemy_la_SOURCES)
-DIST_SOURCES = $(libalchemy_la_SOURCES)
+DIST_SOURCES = $(am__libalchemy_la_SOURCES_DIST)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -264,32 +273,10 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 lib_LTLIBRARIES = libalchemy.la
 libalchemy_la_LDFLAGS = -version-info 0:0:0 -lpthread
-libalchemy_la_SOURCES = \
-       init.c          \
-       internal.c      \
-       internal.h      \
-       reference.h     \
-       alarm.c         \
-       alarm.h         \
-       buffer.c        \
-       buffer.h        \
-       cond.c          \
-       cond.h          \
-       event.c         \
-       event.h         \
-       heap.c          \
-       heap.h          \
-       mutex.c         \
-       mutex.h         \
-       queue.c         \
-       queue.h         \
-       task.c          \
-       task.h          \
-       sem.c           \
-       sem.h           \
-       timer.c         \
-       timer.h
-
+libalchemy_la_SOURCES = init.c internal.c internal.h reference.h \
+       alarm.c alarm.h buffer.c buffer.h cond.c cond.h event.c \
+       event.h heap.c heap.h mutex.c mutex.h queue.c queue.h task.c \
+       task.h sem.c sem.h timer.c timer.h $(am__append_1)
 libalchemy_la_CPPFLAGS = \
        @XENO_USER_CFLAGS@ \
        -I$(top_srcdir)/include \
@@ -379,6 +366,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libalchemy_la-init.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libalchemy_la-internal.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libalchemy_la-mutex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libalchemy_la-pipe.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libalchemy_la-queue.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libalchemy_la-sem.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libalchemy_la-task.Plo@am__quote@
@@ -489,6 +477,13 @@ libalchemy_la-timer.lo: timer.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) 
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(libalchemy_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
libalchemy_la-timer.lo `test -f 'timer.c' || echo '$(srcdir)/'`timer.c
 
+libalchemy_la-pipe.lo: pipe.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) 
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(libalchemy_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
libalchemy_la-pipe.lo -MD -MP -MF $(DEPDIR)/libalchemy_la-pipe.Tpo -c -o 
libalchemy_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libalchemy_la-pipe.Tpo 
$(DEPDIR)/libalchemy_la-pipe.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='pipe.c' 
object='libalchemy_la-pipe.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) 
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(libalchemy_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
libalchemy_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c
+
 mostlyclean-libtool:
        -rm -f *.lo
 
diff --git a/lib/alchemy/pipe.c b/lib/alchemy/pipe.c
new file mode 100644
index 0000000..604c103
--- /dev/null
+++ b/lib/alchemy/pipe.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2011 Philippe Gerum <r...@xenomai.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include "rtdm/rtipc.h"
+#include "copperplate/threadobj.h"
+#include "copperplate/heapobj.h"
+#include "copperplate/cluster.h"
+#include "reference.h"
+#include "internal.h"
+#include "pipe.h"
+#include "timer.h"
+
+struct syncluster alchemy_pipe_table;
+
+static struct alchemy_namegen pipe_namegen = {
+       .prefix = "pipe",
+       .length = sizeof ((struct alchemy_pipe *)0)->name,
+};
+
+static struct alchemy_pipe *find_alchemy_pipe(RT_PIPE *pipe, int *err_r)
+{
+       struct alchemy_pipe *pcb;
+
+       if (pipe == NULL || ((intptr_t)pipe & (sizeof(intptr_t)-1)) != 0)
+               goto bad_handle;
+
+       pcb = mainheap_deref(pipe->handle, struct alchemy_pipe);
+       if (pcb == NULL || ((intptr_t)pcb & (sizeof(intptr_t)-1)) != 0)
+               goto bad_handle;
+
+       if (pcb->magic == ~pipe_magic)
+               goto dead_handle;
+
+       if (pcb->magic == pipe_magic)
+               return pcb;
+bad_handle:
+       *err_r = -EINVAL;
+       return NULL;
+
+dead_handle:
+       /* Removed under our feet. */
+       *err_r = -EIDRM;
+       return NULL;
+}
+
+int rt_pipe_create(RT_PIPE *pipe,
+                  const char *name, int minor, size_t poolsize)
+{
+       struct rtipc_port_label plabel;
+       struct sockaddr_ipc saddr;
+       struct alchemy_pipe *pcb;
+       struct service svc;
+       size_t streambufsz;
+       int ret = 0, sock;
+
+       if (threadobj_irq_p())
+               return -EPERM;
+
+       COPPERPLATE_PROTECT(svc);
+
+       pcb = xnmalloc(sizeof(*pcb));
+       if (pcb == NULL) {
+               COPPERPLATE_UNPROTECT(svc);
+               return -ENOMEM;
+       }
+
+       alchemy_build_name(pcb->name, name, &pipe_namegen);
+
+       if (syncluster_addobj(&alchemy_pipe_table, pcb->name, &pcb->cobj)) {
+               xnfree(pcb);
+               COPPERPLATE_UNPROTECT(svc);
+               return -EEXIST;
+       }
+
+       sock = __RT(socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_XDDP));
+       if (sock < 0) {
+               ret = -errno;
+               xnfree(pcb);
+               goto out;
+       }
+
+       if (name && *name) {
+               strncpy(plabel.label, name, sizeof(plabel.label)-1);
+               plabel.label[sizeof(plabel.label)-1] = '\0';
+               ret = __RT(setsockopt(sock, SOL_XDDP, XDDP_LABEL,
+                                     &plabel, sizeof(plabel)));
+               if (ret)
+                       goto fail;
+       }
+
+       if (poolsize > 0) {
+               ret = setsockopt(pcb->sock, SOL_XDDP, XDDP_POOLSZ,
+                                &poolsize, sizeof(poolsize));
+               if (ret)
+                       goto fail;
+       }
+
+       streambufsz = ALCHEMY_PIPE_STREAMSZ;
+       ret = __RT(setsockopt(pcb->sock, SOL_XDDP, XDDP_BUFSZ,
+                             &streambufsz, streambufsz));
+       if (ret)
+               goto fail;
+
+       memset(&saddr, 0, sizeof(saddr));
+       saddr.sipc_family = AF_RTIPC;
+       saddr.sipc_port = minor;
+       ret = bind(sock, (struct sockaddr *)&saddr, sizeof(saddr));
+       if (ret)
+               goto fail;
+
+       pcb->sock = sock;
+       pcb->magic = pipe_magic;
+       pipe->handle = mainheap_ref(pcb, uintptr_t);
+out:
+       COPPERPLATE_UNPROTECT(svc);
+
+       return 0;
+fail:
+       ret = -errno;
+       __RT(close(sock));
+       syncluster_delobj(&alchemy_pipe_table, &pcb->cobj);
+       xnfree(pcb);
+
+       COPPERPLATE_UNPROTECT(svc);
+
+       return ret;     
+}
+
+int rt_pipe_delete(RT_PIPE *pipe)
+{
+       struct alchemy_pipe *pcb;
+       struct service svc;
+       int ret = 0;
+
+       if (threadobj_irq_p())
+               return -EPERM;
+
+       COPPERPLATE_PROTECT(svc);
+
+       pcb = find_alchemy_pipe(pipe, &ret);
+       if (pcb == NULL)
+               goto out;
+
+       ret = __RT(close(pcb->sock));
+       if (ret) {
+               ret = -errno;
+               if (ret == -EBADF)
+                       ret = -EIDRM;
+               goto out;
+       }
+
+       syncluster_delobj(&alchemy_pipe_table, &pcb->cobj);
+       pcb->magic = ~pipe_magic;
+out:
+       COPPERPLATE_UNPROTECT(svc);
+
+       return ret;
+}
+
+ssize_t rt_pipe_read_until(RT_PIPE *pipe,
+                          void *buf, size_t size, RTIME timeout)
+{
+       struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
+       struct timespec ts, *timespec;
+       struct alchemy_pipe *pcb;
+       struct service svc;
+       int err, flags;
+       ssize_t ret;
+
+       if (!threadobj_current_p())
+               return -EPERM;
+
+       COPPERPLATE_PROTECT(svc);
+
+       pcb = find_alchemy_pipe(pipe, &err);
+       if (pcb == NULL) {
+               ret = err;
+               goto out;
+       }
+
+       switch (timeout) {
+       default:
+               timespec = alchemy_get_timespec(timeout, &ts);
+               tv.tv_sec = ts.tv_sec;
+               tv.tv_usec = ts.tv_nsec / 1000;
+               /* Falldown wanted. */
+       case TM_INFINITE:
+               __RT(setsockopt(pcb->sock, SOL_SOCKET,
+                               SO_RCVTIMEO, &tv, sizeof(tv)));
+               flags = 0;
+               break;
+       case TM_NONBLOCK:
+               flags = MSG_DONTWAIT;
+               break;
+       }
+
+       ret = __RT(recvfrom(pcb->sock, buf, size, flags, NULL, 0));
+       if (ret < 0)
+               ret = -errno;
+out:
+       COPPERPLATE_UNPROTECT(svc);
+
+       return ret;
+}
+
+ssize_t rt_pipe_read(RT_PIPE *pipe,
+                    void *buf, size_t size, RTIME timeout)
+{
+       timeout = alchemy_rel2abs_timeout(timeout);
+       return rt_pipe_read_until(pipe, buf, size, timeout);
+}
+
+static ssize_t do_write_pipe(RT_PIPE *pipe,
+                            const void *buf, size_t size, int flags)
+{
+       struct alchemy_pipe *pcb;
+       struct service svc;
+       ssize_t ret;
+       int err;
+
+       if (threadobj_irq_p())
+               return -EPERM;
+
+       COPPERPLATE_PROTECT(svc);
+
+       pcb = find_alchemy_pipe(pipe, &err);
+       if (pcb == NULL) {
+               ret = err;
+               goto out;
+       }
+
+       ret = __RT(sendto(pcb->sock, buf, size, flags, NULL, 0));
+       if (ret < 0)
+               ret = -errno;
+out:
+       COPPERPLATE_UNPROTECT(svc);
+
+       return ret;
+}
+
+ssize_t rt_pipe_write(RT_PIPE *pipe,
+                     const void *buf, size_t size, int mode)
+{
+       int flags = 0;
+
+       if (mode & P_URGENT)
+               flags |= MSG_OOB;
+
+       return do_write_pipe(pipe, buf, size, flags);
+}
+
+ssize_t rt_pipe_stream(RT_PIPE *pipe,
+                      const void *buf, size_t size)
+{
+       return do_write_pipe(pipe, buf, size, MSG_MORE);
+}
+
+int rt_pipe_bind(RT_PIPE *pipe,
+                const char *name, RTIME timeout)
+{
+       return alchemy_bind_object(name,
+                                  &alchemy_pipe_table,
+                                  timeout,
+                                  offsetof(struct alchemy_pipe, cobj),
+                                  &pipe->handle);
+}
+
+int rt_pipe_unbind(RT_PIPE *pipe)
+{
+       pipe->handle = 0;
+       return 0;
+}
diff --git a/lib/alchemy/pipe.h b/lib/alchemy/pipe.h
new file mode 100644
index 0000000..1cfb6c0
--- /dev/null
+++ b/lib/alchemy/pipe.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 Philippe Gerum <r...@xenomai.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+
+#ifndef _ALCHEMY_PIPE_H
+#define _ALCHEMY_PIPE_H
+
+#include <copperplate/cluster.h>
+#include <alchemy/pipe.h>
+
+/* Fixed default for MSG_MORE accumulation. */
+#define ALCHEMY_PIPE_STREAMSZ  16384
+
+struct alchemy_pipe {
+       unsigned int magic;     /* Must be first. */
+       char name[32];
+       int sock;
+       struct clusterobj cobj;
+};
+
+#define pipe_magic     0x8b8bebeb
+
+#endif /* _ALCHEMY_PIPE_H */


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to