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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Feb  3 11:51:13 2014 +0100

copperplate/registry: output format helpers via obstack

---

 include/copperplate/Makefile.am        |   29 ++++---
 include/copperplate/Makefile.in        |   27 +++---
 include/copperplate/registry-obstack.h |  111 ++++++++++++++++++++++++
 include/copperplate/registry.h         |    4 +-
 lib/copperplate/registry.c             |  146 ++++++++++++++++++++++++++++++++
 5 files changed, 289 insertions(+), 28 deletions(-)

diff --git a/include/copperplate/Makefile.am b/include/copperplate/Makefile.am
index f25f2e0..50147a7 100644
--- a/include/copperplate/Makefile.am
+++ b/include/copperplate/Makefile.am
@@ -1,17 +1,18 @@
 includesubdir = $(includedir)/copperplate
 
-includesub_HEADERS =   \
-       clockobj.h      \
-       cluster.h       \
-       debug.h         \
-       eventobj.h      \
-       heapobj.h       \
-       init.h          \
-       semobj.h        \
-       notifier.h      \
-       reference.h     \
-       registry.h      \
-       syncobj.h       \
-       threadobj.h     \
-       traceobj.h      \
+includesub_HEADERS =           \
+       clockobj.h              \
+       cluster.h               \
+       debug.h                 \
+       eventobj.h              \
+       heapobj.h               \
+       init.h                  \
+       semobj.h                \
+       notifier.h              \
+       reference.h             \
+       registry.h              \
+       registry-obstack.h      \
+       syncobj.h               \
+       threadobj.h             \
+       traceobj.h              \
        wrappers.h
diff --git a/include/copperplate/Makefile.in b/include/copperplate/Makefile.in
index be6086f..cdbf469 100644
--- a/include/copperplate/Makefile.in
+++ b/include/copperplate/Makefile.in
@@ -333,19 +333,20 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 includesubdir = $(includedir)/copperplate
 includesub_HEADERS = \
-       clockobj.h      \
-       cluster.h       \
-       debug.h         \
-       eventobj.h      \
-       heapobj.h       \
-       init.h          \
-       semobj.h        \
-       notifier.h      \
-       reference.h     \
-       registry.h      \
-       syncobj.h       \
-       threadobj.h     \
-       traceobj.h      \
+       clockobj.h              \
+       cluster.h               \
+       debug.h                 \
+       eventobj.h              \
+       heapobj.h               \
+       init.h                  \
+       semobj.h                \
+       notifier.h              \
+       reference.h             \
+       registry.h              \
+       registry-obstack.h      \
+       syncobj.h               \
+       threadobj.h             \
+       traceobj.h              \
        wrappers.h
 
 all: all-am
diff --git a/include/copperplate/registry-obstack.h 
b/include/copperplate/registry-obstack.h
new file mode 100644
index 0000000..3aec714
--- /dev/null
+++ b/include/copperplate/registry-obstack.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2014 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 _COPPERPLATE_REGISTRY_OBSTACK_H
+#define _COPPERPLATE_REGISTRY_OBSTACK_H
+
+#ifdef CONFIG_XENO_REGISTRY
+
+#include <boilerplate/obstack.h>
+#include <copperplate/registry.h>
+#include <copperplate/heapobj.h>
+
+/*
+ * Assume we may want fast allocation of private memory from real-time
+ * mode when growing the obstack.
+ */
+#define obstack_chunk_alloc    pvmalloc
+#define obstack_chunk_free     pvfree
+
+struct fsobstack {
+       struct obstack obstack;
+       void *data;
+       size_t len;
+};
+
+struct fsobstack_syncops {
+       int (*prepare_cache)(struct fsobstack *o,
+                            struct obstack *cache, int item_count);
+       size_t (*collect_data)(void *p, struct threadobj *thobj);
+       size_t (*format_data)(struct fsobstack *o, void *p);
+};
+
+struct syncobj;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int fsobstack_grow_format(struct fsobstack *o,
+                         const char *fmt, ...);
+
+int fsobstack_grow_syncobj_grant(struct fsobstack *o,
+                                struct syncobj *sobj,
+                                struct fsobstack_syncops *ops);
+
+int fsobstack_grow_syncobj_drain(struct fsobstack *o,
+                                struct syncobj *sobj,
+                                struct fsobstack_syncops *ops);
+
+ssize_t fsobstack_pull(struct fsobstack *o,
+                      char *buf, size_t size);
+
+ssize_t fsobj_obstack_read(struct fsobj *fsobj,
+                          char *buf, size_t size, off_t offset,
+                          void *priv);
+
+int fsobj_obstack_release(struct fsobj *fsobj, void *priv);
+
+#ifdef __cplusplus
+}
+#endif
+
+static inline void fsobstack_init(struct fsobstack *o)
+{
+       obstack_init(&o->obstack);
+       o->data = NULL;
+       o->len = 0;
+}
+
+static inline void fsobstack_destroy(struct fsobstack *o)
+{
+       obstack_free(&o->obstack, NULL);
+}
+
+static inline void fsobstack_finish(struct fsobstack *o)
+{
+       o->len = obstack_object_size(&o->obstack);
+       o->data = obstack_finish(&o->obstack);
+}
+
+static inline
+void registry_init_file_obstack(struct fsobj *fsobj, 
+                               const struct registry_operations *ops)
+{
+       registry_init_file(fsobj, ops, sizeof(struct fsobstack));
+}
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static inline
+void registry_init_file_obstack(struct fsobj *fsobj, 
+                               const struct registry_operations *ops)
+{ }
+
+#endif /* !CONFIG_XENO_REGISTRY */
+
+#endif /* !_COPPERPLATE_REGISTRY_OBSTACK_H */
diff --git a/include/copperplate/registry.h b/include/copperplate/registry.h
index 893bfb1..84a7d84 100644
--- a/include/copperplate/registry.h
+++ b/include/copperplate/registry.h
@@ -21,8 +21,10 @@
 
 #include <sys/types.h>
 #include <pthread.h>
+#include <fcntl.h>
 #include <boilerplate/list.h>
 #include <boilerplate/hash.h>
+#include <boilerplate/obstack.h>
 #include <copperplate/init.h>
 
 struct fsobj;
@@ -138,4 +140,4 @@ void registry_pkg_destroy(void)
 
 #endif /* !CONFIG_XENO_REGISTRY */
 
-#endif /* _COPPERPLATE_REGISTRY_H */
+#endif /* !_COPPERPLATE_REGISTRY_H */
diff --git a/lib/copperplate/registry.c b/lib/copperplate/registry.c
index 67b5982..d074243 100644
--- a/lib/copperplate/registry.c
+++ b/lib/copperplate/registry.c
@@ -38,7 +38,10 @@
 #include <xeno_config.h>
 #include "boilerplate/hash.h"
 #include "copperplate/heapobj.h"
+#include "copperplate/threadobj.h"
+#include "copperplate/syncobj.h"
 #include "copperplate/registry.h"
+#include "copperplate/registry-obstack.h"
 #include "copperplate/clockobj.h"
 #include "boilerplate/lock.h"
 #include "copperplate/debug.h"
@@ -715,3 +718,146 @@ void registry_pkg_destroy(void)
                regfs_thid = 0;
        }
 }
+
+int fsobj_obstack_release(struct fsobj *fsobj, void *priv)
+{
+       fsobstack_destroy(priv);
+
+       return 0;
+}
+
+ssize_t fsobj_obstack_read(struct fsobj *fsobj,
+                          char *buf, size_t size, off_t offset,
+                          void *priv)
+{
+       return fsobstack_pull(priv, buf, size);
+}
+
+int fsobstack_grow_format(struct fsobstack *o, const char *fmt, ...)
+{
+       char buf[256], *p = buf;
+       int len = sizeof(buf), n;
+       va_list ap;
+
+       for (;;) {
+               va_start(ap, fmt);
+               n = vsnprintf(p, len, fmt, ap);
+               va_end(ap);
+
+              if (n > 0 && n < len)
+                      obstack_grow(&o->obstack, p, n);
+
+              if (p != buf)
+                      xnfree(p);
+
+               if (n < len)
+                      return n < 0 ? -EINVAL : n;
+
+              len = n + 1;
+              p = xnmalloc(len);
+              if (p == NULL)
+                      break;
+           }
+
+       return -ENOMEM;
+}
+
+ssize_t fsobstack_pull(struct fsobstack *o, char *buf, size_t size)
+{
+       size_t len;
+
+       if (o->data == NULL)    /* Not finished. */
+               return -EIO;
+
+       len = o->len;
+       if (len > 0) {
+               if (len > size)
+                       len = size;
+               o->len -= len;
+               memcpy(buf, o->data, len);
+               o->data += len;
+       }
+
+       return len;
+}
+
+static int collect_wait_list(struct fsobstack *o,
+                            struct syncobj *sobj,
+                            struct list *wait_list,
+                            int *wait_count,
+                            struct fsobstack_syncops *ops)
+{
+       struct threadobj *thobj;
+       struct syncstate syns;
+       struct obstack cache;
+       int count, ret;
+       void *p, *e;
+
+       obstack_init(&cache);
+redo:
+       smp_rmb();
+       count = *wait_count;
+       if (count == 0)
+               goto out;
+
+       /* Pre-allocate the obstack room without holding any lock. */
+       ret = ops->prepare_cache(o, &cache, count);
+       if (ret)
+               goto out;
+
+       ret = syncobj_lock(sobj, &syns);
+       if (ret) {
+               obstack_free(&cache, NULL);
+               return ret;
+       }
+
+       /* Re-validate the previous item count under lock. */
+       if (count != *wait_count) {
+               syncobj_unlock(sobj, &syns);
+               obstack_free(&cache, NULL);
+               goto redo;
+       }
+
+       p = obstack_base(&cache);
+       list_for_each_entry(thobj, wait_list, wait_link)
+               p += ops->collect_data(p, thobj);
+
+       syncobj_unlock(sobj, &syns);
+
+       /*
+        * Some may want to format data directly from the collect
+        * handler, when no gain is expected from splitting the
+        * collect and format steps. In that case, we may have no
+        * format handler.
+        */
+       e = obstack_next_free(&cache);
+       p = obstack_finish(&cache);
+       if (ops->format_data == NULL) {
+               if (e != p)
+                       obstack_grow(&o->obstack, p, e - p);
+               goto out;
+       }
+
+       /* Finally, format the output without holding any lock. */
+       do
+               p += ops->format_data(o, p);
+       while (p < e);
+out:
+       obstack_free(&cache, NULL);
+
+       return count;
+}
+
+int fsobstack_grow_syncobj_grant(struct fsobstack *o, struct syncobj *sobj,
+                                struct fsobstack_syncops *ops)
+{
+       return collect_wait_list(o, sobj, &sobj->grant_list,
+                                &sobj->grant_count, ops);
+}
+
+int fsobstack_grow_syncobj_drain(struct fsobstack *o, struct syncobj *sobj,
+                                struct fsobstack_syncops *ops)
+{
+       return collect_wait_list(o, sobj, &sobj->drain_list,
+                                &sobj->drain_count, ops);
+}


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to