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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Jan 31 17:40:20 2014 +0100

alchemy: export objects to registry (WIP)

---

 lib/alchemy/alarm.c  |   60 +++++++++++++++++++++++++++
 lib/alchemy/alarm.h  |    3 ++
 lib/alchemy/buffer.c |  107 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/alchemy/buffer.h |    2 +
 lib/alchemy/cond.c   |   32 ++++++++++++++-
 lib/alchemy/cond.h   |    2 +
 lib/alchemy/event.c  |   51 ++++++++++++++++++++++-
 lib/alchemy/event.h  |    2 +
 lib/alchemy/heap.c   |  110 +++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/alchemy/heap.h   |    2 +
 lib/alchemy/init.c   |   11 +++++
 lib/alchemy/mutex.c  |   32 ++++++++++++++-
 lib/alchemy/mutex.h  |    2 +
 lib/alchemy/queue.c  |   97 +++++++++++++++++++++++++++++++++++++++++++-
 lib/alchemy/queue.h  |    2 +
 lib/alchemy/sem.c    |   72 ++++++++++++++++++++++++++++++++-
 lib/alchemy/sem.h    |    2 +
 lib/alchemy/task.c   |   47 +++++++++++++++++++++
 lib/alchemy/task.h   |    2 +
 19 files changed, 630 insertions(+), 8 deletions(-)

diff --git a/lib/alchemy/alarm.c b/lib/alchemy/alarm.c
index e622ea4..84c34eb 100644
--- a/lib/alchemy/alarm.c
+++ b/lib/alchemy/alarm.c
@@ -42,6 +42,54 @@ struct pvcluster alchemy_alarm_table;
 static DEFINE_NAME_GENERATOR(alarm_namegen, "alarm",
                             struct alchemy_alarm, name);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static int alarm_registry_open(struct fsobj *fsobj, void *priv)
+{
+       struct fsobstack *o = priv;
+       struct alchemy_alarm *acb;
+       struct itimerspec itmspec;
+       unsigned long expiries;
+       struct timespec delta;
+       int ret;
+
+       acb = container_of(fsobj, struct alchemy_alarm, fsobj);
+       ret = timerobj_lock(&acb->tmobj);
+       if (ret)
+               return ret;
+       itmspec = acb->itmspec;
+       expiries = acb->expiries;
+       timerobj_unlock(&acb->tmobj);
+
+       fsobstack_init(o);
+
+       fsobstack_grow_format(o, "%-12s%-12s%-12s\n",
+                             "[EXPIRIES]", "[DISTANCE]", "[INTERVAL]");
+       clockobj_get_distance(&alchemy_clock, &itmspec, &delta);
+       fsobstack_grow_format(o, "%8lu%10ld\"%ld%10ld\"%ld\n",
+                             expiries,
+                             delta.tv_sec,
+                             delta.tv_nsec / 100000000,
+                             itmspec.it_interval.tv_sec,
+                             itmspec.it_interval.tv_nsec / 100000000);
+
+       fsobstack_finish(o);
+
+       return 0;
+}
+
+static struct registry_operations registry_ops = {
+       .open           = alarm_registry_open,
+       .release        = fsobj_obstack_release,
+       .read           = fsobj_obstack_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 static struct alchemy_alarm *get_alchemy_alarm(RT_ALARM *alarm, int *err_r)
 {
        struct alchemy_alarm *acb;
@@ -140,6 +188,7 @@ int rt_alarm_create(RT_ALARM *alarm, const char *name,
        acb->handler = handler;
        acb->arg = arg;
        acb->expiries = 0;
+       memset(&acb->itmspec, 0, sizeof(acb->itmspec));
        acb->magic = alarm_magic;
        alarm->handle = (uintptr_t)acb;
 
@@ -149,6 +198,14 @@ int rt_alarm_create(RT_ALARM *alarm, const char *name,
                goto fail;
        }
 
+       registry_init_file_obstack(&acb->fsobj, &registry_ops);
+       ret = __bt(registry_add_file(&acb->fsobj, O_RDONLY,
+                                    "/alchemy/alarms/%s",
+                                    acb->name));
+       if (ret)
+               warning("failed to export alarm %s to registry",
+                       acb->name);
+
        CANCEL_RESTORE(svc);
 
        return 0;
@@ -196,6 +253,7 @@ int rt_alarm_delete(RT_ALARM *alarm)
        timerobj_destroy(&acb->tmobj);
        pvcluster_delobj(&alchemy_alarm_table, &acb->cobj);
        acb->magic = ~alarm_magic;
+       registry_destroy_file(&acb->fsobj);
        pvfree(acb);
 out:
        CANCEL_RESTORE(svc);
@@ -255,6 +313,7 @@ int rt_alarm_start(RT_ALARM *alarm,
 
        clockobj_ticks_to_timeout(&alchemy_clock, value, &it.it_value);
        clockobj_ticks_to_timespec(&alchemy_clock, interval, &it.it_interval);
+       acb->itmspec = it;
        ret = timerobj_start(&acb->tmobj, alarm_handler, &it);
 out:
        CANCEL_RESTORE(svc);
@@ -289,6 +348,7 @@ int rt_alarm_stop(RT_ALARM *alarm)
        if (acb == NULL)
                goto out;
 
+       memset(&acb->itmspec, 0, sizeof(acb->itmspec));
        ret = timerobj_stop(&acb->tmobj);
 out:
        CANCEL_RESTORE(svc);
diff --git a/lib/alchemy/alarm.h b/lib/alchemy/alarm.h
index 58adefa..2abd5ce 100644
--- a/lib/alchemy/alarm.h
+++ b/lib/alchemy/alarm.h
@@ -19,6 +19,7 @@
 #ifndef _ALCHEMY_ALARM_H
 #define _ALCHEMY_ALARM_H
 
+#include <copperplate/registry-obstack.h>
 #include <copperplate/timerobj.h>
 #include <copperplate/cluster.h>
 #include <alchemy/alarm.h>
@@ -30,7 +31,9 @@ struct alchemy_alarm {
        struct pvclusterobj cobj;
        void (*handler)(void *arg);
        void *arg;
+       struct itimerspec itmspec;
        unsigned long expiries;
+       struct fsobj fsobj;
 };
 
 #define alarm_magic    0x8888ebeb
diff --git a/lib/alchemy/buffer.c b/lib/alchemy/buffer.c
index 4f4b5f6..36f9e12 100644
--- a/lib/alchemy/buffer.c
+++ b/lib/alchemy/buffer.c
@@ -48,10 +48,109 @@ static DEFINE_NAME_GENERATOR(buffer_namegen, "buffer",
 
 DEFINE_SYNC_LOOKUP(buffer, RT_BUFFER);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static inline
+void prepare_waiter_cache(struct obstack *cache, int item_count)
+{
+       const struct alchemy_buffer *bcb;
+       obstack_blank(cache, item_count * sizeof(bcb->name));
+}
+
+static int prepare_grant_cache(struct fsobstack *o,
+                              struct obstack *cache, int item_count)
+{
+       fsobstack_grow_format(o, "--\n[INPUT-WAIT]\n");
+       prepare_waiter_cache(cache, item_count);
+
+       return 0;
+}
+
+static int prepare_drain_cache(struct fsobstack *o,
+                              struct obstack *cache, int item_count)
+{
+       fsobstack_grow_format(o, "--\n[OUTPUT-WAIT]\n");
+       prepare_waiter_cache(cache, item_count);
+
+       return 0;
+}
+
+static size_t collect_waiter_data(void *p, struct threadobj *thobj)
+{
+       const char *name = threadobj_get_name(thobj);
+       int len = strlen(name);
+
+       strcpy(p, name);
+       *(char *)(p + len) = '\n';
+
+       return len + 1;
+}
+
+static struct fsobstack_syncops fill_grant_ops = {
+       .prepare_cache = prepare_grant_cache,
+       .collect_data = collect_waiter_data,
+};
+
+static struct fsobstack_syncops fill_drain_ops = {
+       .prepare_cache = prepare_drain_cache,
+       .collect_data = collect_waiter_data,
+};
+
+static int buffer_registry_open(struct fsobj *fsobj, void *priv)
+{
+       struct fsobstack *o = priv;
+       struct alchemy_buffer *bcb;
+       struct syncstate syns;
+       size_t bufsz, fillsz;
+       int ret, mode;
+
+       bcb = container_of(fsobj, struct alchemy_buffer, fsobj);
+
+       ret = syncobj_lock(&bcb->sobj, &syns);
+       if (ret)
+               return -EIO;
+
+       bufsz = bcb->bufsz;
+       fillsz = bcb->fillsz;
+       mode = bcb->mode;
+
+       syncobj_unlock(&bcb->sobj, &syns);
+
+       fsobstack_init(o);
+
+       fsobstack_grow_format(o, "%6s  %10s  %9s\n",
+                             "[TYPE]", "[TOTALMEM]", "[USEDMEM]");
+
+       fsobstack_grow_format(o, " %s   %9Zu  %9Zu\n",
+                             mode & B_PRIO ? "PRIO" : "FIFO",
+                             bufsz, fillsz);
+
+       fsobstack_grow_syncobj_grant(o, &bcb->sobj, &fill_grant_ops);
+       fsobstack_grow_syncobj_drain(o, &bcb->sobj, &fill_drain_ops);
+
+       fsobstack_finish(o);
+
+       return 0;
+}
+
+static struct registry_operations registry_ops = {
+       .open           = buffer_registry_open,
+       .release        = fsobj_obstack_release,
+       .read           = fsobj_obstack_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 static void buffer_finalize(struct syncobj *sobj)
 {
        struct alchemy_buffer *bcb;
+
        bcb = container_of(sobj, struct alchemy_buffer, sobj);
+       registry_destroy_file(&bcb->fsobj);
        xnfree(bcb->buf);
        xnfree(bcb);
 }
@@ -158,6 +257,14 @@ int rt_buffer_create(RT_BUFFER *bf, const char *name,
 
        bf->handle = mainheap_ref(bcb, uintptr_t);
 
+       registry_init_file_obstack(&bcb->fsobj, &registry_ops);
+       ret = __bt(registry_add_file(&bcb->fsobj, O_RDONLY,
+                                    "/alchemy/buffers/%s",
+                                    bcb->name));
+       if (ret)
+               warning("failed to export buffer %s to registry",
+                       bcb->name);
+
        CANCEL_RESTORE(svc);
 
        return 0;
diff --git a/lib/alchemy/buffer.h b/lib/alchemy/buffer.h
index 6eedcae..b130715 100644
--- a/lib/alchemy/buffer.h
+++ b/lib/alchemy/buffer.h
@@ -19,6 +19,7 @@
 #ifndef _ALCHEMY_BUFFER_H
 #define _ALCHEMY_BUFFER_H
 
+#include <copperplate/registry-obstack.h>
 #include <copperplate/syncobj.h>
 #include <copperplate/cluster.h>
 #include <alchemy/buffer.h>
@@ -34,6 +35,7 @@ struct alchemy_buffer {
        size_t rdoff;
        size_t wroff;
        size_t fillsz;
+       struct fsobj fsobj;
 };
 
 struct alchemy_buffer_wait {
diff --git a/lib/alchemy/cond.c b/lib/alchemy/cond.c
index 3ecd0de..2810bda 100644
--- a/lib/alchemy/cond.c
+++ b/lib/alchemy/cond.c
@@ -54,6 +54,25 @@ static DEFINE_NAME_GENERATOR(cond_namegen, "cond",
 
 DEFINE_LOOKUP_PRIVATE(cond, RT_COND);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static ssize_t cond_registry_read(struct fsobj *fsobj,
+                                 char *buf, size_t size, off_t offset,
+                                 void *priv)
+{
+       return 0;               /* FIXME */
+}
+
+static struct registry_operations registry_ops = {
+       .read   = cond_registry_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 /**
  * @fn int rt_cond_create(RT_COND *cond, const char *name)
  * @brief Create a condition variable.
@@ -119,8 +138,18 @@ int rt_cond_create(RT_COND *cond, const char *name)
                __RT(pthread_cond_destroy(&ccb->cond));
                xnfree(ccb);
                ret = -EEXIST;
-       } else
+       } else {
                cond->handle = mainheap_ref(ccb, uintptr_t);
+               registry_init_file(&ccb->fsobj, &registry_ops, 0);
+               ret = __bt(registry_add_file(&ccb->fsobj, O_RDONLY,
+                                            "/alchemy/condvars/%s",
+                                            ccb->name));
+               if (ret) {
+                       warning("failed to export condvar %s to registry",
+                               ccb->name);
+                       ret = 0;
+               }
+       }
 out:
        CANCEL_RESTORE(svc);
 
@@ -174,6 +203,7 @@ int rt_cond_delete(RT_COND *cond)
                goto out;
 
        ccb->magic = ~cond_magic;
+       registry_destroy_file(&ccb->fsobj);
        syncluster_delobj(&alchemy_cond_table, &ccb->cobj);
        xnfree(ccb);
 out:
diff --git a/lib/alchemy/cond.h b/lib/alchemy/cond.h
index 90d46e6..faf2166 100644
--- a/lib/alchemy/cond.h
+++ b/lib/alchemy/cond.h
@@ -19,6 +19,7 @@
 #ifndef _ALCHEMY_COND_H
 #define _ALCHEMY_COND_H
 
+#include <copperplate/registry.h>
 #include <copperplate/cluster.h>
 #include <alchemy/cond.h>
 
@@ -29,6 +30,7 @@ struct alchemy_cond {
        char name[32];
        pthread_cond_t cond;
        struct clusterobj cobj;
+       struct fsobj fsobj;
 };
 
 #define cond_magic     0x8686ebeb
diff --git a/lib/alchemy/event.c b/lib/alchemy/event.c
index 459d232..4c81193 100644
--- a/lib/alchemy/event.c
+++ b/lib/alchemy/event.c
@@ -37,6 +37,7 @@
 #include <string.h>
 #include <copperplate/threadobj.h>
 #include <copperplate/heapobj.h>
+#include <copperplate/registry-obstack.h>
 #include "reference.h"
 #include "internal.h"
 #include "event.h"
@@ -49,9 +50,47 @@ static DEFINE_NAME_GENERATOR(event_namegen, "event",
 
 DEFINE_LOOKUP_PRIVATE(event, RT_EVENT);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static int event_registry_open(struct fsobj *fsobj, void *priv)
+{
+       struct fsobstack *o = priv;
+       struct alchemy_event *evcb;
+       unsigned long value;
+       int ret;
+
+       evcb = container_of(fsobj, struct alchemy_event, fsobj);
+
+       ret = eventobj_inquire(&evcb->evobj, &value);
+       if (ret < 0)
+               return -EIO;
+
+       fsobstack_init(o);
+
+       fsobstack_grow_format(o, "0x%lx\n", value);
+
+       fsobstack_finish(o);
+
+       return 0;
+}
+
+static struct registry_operations registry_ops = {
+       .open           = event_registry_open,
+       .release        = fsobj_obstack_release,
+       .read           = fsobj_obstack_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 static void event_finalize(struct eventobj *evobj)
 {
        struct alchemy_event *evcb = container_of(evobj, struct alchemy_event, 
evobj);
+
+       registry_destroy_file(&evcb->fsobj);
        /* We should never fail here, so we backtrace. */
        __bt(syncluster_delobj(&alchemy_event_table, &evcb->cobj));
        evcb->magic = ~event_magic;
@@ -138,8 +177,18 @@ int rt_event_create(RT_EVENT *event, const char *name,
                eventobj_destroy(&evcb->evobj);
                xnfree(evcb);
                ret = -EEXIST;
-       } else
+       } else {
                event->handle = mainheap_ref(evcb, uintptr_t);
+               registry_init_file_obstack(&evcb->fsobj, &registry_ops);
+               ret = __bt(registry_add_file(&evcb->fsobj, O_RDONLY,
+                                            "/alchemy/events/%s",
+                                            evcb->name));
+               if (ret) {
+                       warning("failed to export event %s to registry",
+                               evcb->name);
+                       ret = 0;
+               }
+       }
 out:
        CANCEL_RESTORE(svc);
 
diff --git a/lib/alchemy/event.h b/lib/alchemy/event.h
index 99d719a..f973016 100644
--- a/lib/alchemy/event.h
+++ b/lib/alchemy/event.h
@@ -20,6 +20,7 @@
 #define _ALCHEMY_EVENT_H
 
 #include <copperplate/eventobj.h>
+#include <copperplate/registry.h>
 #include <copperplate/cluster.h>
 #include <alchemy/event.h>
 
@@ -28,6 +29,7 @@ struct alchemy_event {
        char name[32];
        struct eventobj evobj;
        struct clusterobj cobj;
+       struct fsobj fsobj;
 };
 
 #define event_magic    0x8484ebeb
diff --git a/lib/alchemy/heap.c b/lib/alchemy/heap.c
index 63da6c2..19a1c61 100644
--- a/lib/alchemy/heap.c
+++ b/lib/alchemy/heap.c
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <copperplate/threadobj.h>
 #include <copperplate/heapobj.h>
+#include <copperplate/registry-obstack.h>
 #include "reference.h"
 #include "internal.h"
 #include "heap.h"
@@ -42,10 +43,106 @@ static DEFINE_NAME_GENERATOR(heap_namegen, "heap",
 
 DEFINE_SYNC_LOOKUP(heap, RT_HEAP);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+struct heap_waiter_data {
+       char name[32];
+       size_t reqsz;
+};
+
+static int prepare_waiter_cache(struct fsobstack *o,
+                               struct obstack *cache, int item_count)
+{
+       fsobstack_grow_format(o, "--\n%-10s  %s\n", "[REQ-SIZE]", "[WAITER]");
+       obstack_blank(cache, item_count * sizeof(struct heap_waiter_data));
+
+       return 0;
+}
+
+static size_t collect_waiter_data(void *p, struct threadobj *thobj)
+{
+       struct alchemy_heap_wait *wait;
+       struct heap_waiter_data data;
+
+       strcpy(data.name, threadobj_get_name(thobj));
+       wait = threadobj_get_wait(thobj);
+       data.reqsz = wait->size;
+       memcpy(p, &data, sizeof(data));
+
+       return sizeof(data);
+}
+
+static size_t format_waiter_data(struct fsobstack *o, void *p)
+{
+       struct heap_waiter_data *data = p;
+
+       fsobstack_grow_format(o, "%9Zu    %s\n",
+                             data->reqsz, data->name);
+
+       return sizeof(*data);
+}
+
+static struct fsobstack_syncops fill_ops = {
+       .prepare_cache = prepare_waiter_cache,
+       .collect_data = collect_waiter_data,
+       .format_data = format_waiter_data,
+};
+
+static int heap_registry_open(struct fsobj *fsobj, void *priv)
+{
+       size_t usable_mem, used_mem;
+       struct fsobstack *o = priv;
+       struct alchemy_heap *hcb;
+       struct syncstate syns;
+       int mode, ret;
+
+       hcb = container_of(fsobj, struct alchemy_heap, fsobj);
+
+       ret = syncobj_lock(&hcb->sobj, &syns);
+       if (ret)
+               return -EIO;
+
+       usable_mem = heapobj_size(&hcb->hobj);
+       used_mem = heapobj_inquire(&hcb->hobj);
+       mode = hcb->mode;
+
+       syncobj_unlock(&hcb->sobj, &syns);
+
+       fsobstack_init(o);
+
+       fsobstack_grow_format(o, "%6s  %10s  %9s\n",
+                             "[TYPE]", "[TOTALMEM]", "[USEDMEM]");
+
+       fsobstack_grow_format(o, " %s  %10Zu %10Zu\n",
+                             mode & H_PRIO ? "PRIO" : "FIFO",
+                             usable_mem,
+                             used_mem);
+
+       fsobstack_grow_syncobj_grant(o, &hcb->sobj, &fill_ops);
+
+       fsobstack_finish(o);
+
+       return 0;
+}
+
+static struct registry_operations registry_ops = {
+       .open           = heap_registry_open,
+       .release        = fsobj_obstack_release,
+       .read           = fsobj_obstack_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 static void heap_finalize(struct syncobj *sobj)
 {
        struct alchemy_heap *hcb;
+
        hcb = container_of(sobj, struct alchemy_heap, sobj);
+       registry_destroy_file(&hcb->fsobj);
        heapobj_destroy(&hcb->hobj);
        xnfree(hcb);
 }
@@ -156,14 +253,23 @@ int rt_heap_create(RT_HEAP *heap,
        syncobj_init(&hcb->sobj, CLOCK_COPPERPLATE, sobj_flags,
                     fnref_put(libalchemy, heap_finalize));
 
-       ret = 0;
        if (syncluster_addobj(&alchemy_heap_table, hcb->name, &hcb->cobj)) {
                syncobj_uninit(&hcb->sobj);
                heapobj_destroy(&hcb->hobj);
                xnfree(hcb);
                ret = -EEXIST;
-       } else
+       } else {
                heap->handle = mainheap_ref(hcb, uintptr_t);
+               registry_init_file_obstack(&hcb->fsobj, &registry_ops);
+               ret = __bt(registry_add_file(&hcb->fsobj, O_RDONLY,
+                                            "/alchemy/heaps/%s",
+                                            hcb->name));
+               if (ret) {
+                       warning("failed to export heap %s to registry",
+                               hcb->name);
+                       ret = 0;
+               }
+       }
 out:
        CANCEL_RESTORE(svc);
 
diff --git a/lib/alchemy/heap.h b/lib/alchemy/heap.h
index 58a2b0b..91bdce2 100644
--- a/lib/alchemy/heap.h
+++ b/lib/alchemy/heap.h
@@ -20,6 +20,7 @@
 #define _ALCHEMY_HEAP_H
 
 #include <copperplate/syncobj.h>
+#include <copperplate/registry.h>
 #include <copperplate/cluster.h>
 #include <copperplate/heapobj.h>
 #include <alchemy/heap.h>
@@ -33,6 +34,7 @@ struct alchemy_heap {
        int mode;
        size_t size;
        void *sba;
+       struct fsobj fsobj;
 };
 
 struct alchemy_heap_wait {
diff --git a/lib/alchemy/init.c b/lib/alchemy/init.c
index d14c2ed..ad2e72b 100644
--- a/lib/alchemy/init.c
+++ b/lib/alchemy/init.c
@@ -91,6 +91,17 @@ static int alchemy_init(void)
                return __bt(ret);
        }
 
+       registry_add_dir("/alchemy");
+       registry_add_dir("/alchemy/tasks");
+       registry_add_dir("/alchemy/semaphores");
+       registry_add_dir("/alchemy/events");
+       registry_add_dir("/alchemy/condvars");
+       registry_add_dir("/alchemy/mutexes");
+       registry_add_dir("/alchemy/queues");
+       registry_add_dir("/alchemy/buffers");
+       registry_add_dir("/alchemy/heaps");
+       registry_add_dir("/alchemy/alarms");
+
        return 0;
 }
 
diff --git a/lib/alchemy/mutex.c b/lib/alchemy/mutex.c
index 4c4d980..a2c75d8 100644
--- a/lib/alchemy/mutex.c
+++ b/lib/alchemy/mutex.c
@@ -57,6 +57,25 @@ static DEFINE_NAME_GENERATOR(mutex_namegen, "mutex",
 
 DEFINE_LOOKUP(mutex, RT_MUTEX);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static ssize_t mutex_registry_read(struct fsobj *fsobj,
+                                  char *buf, size_t size, off_t offset,
+                                  void *priv)
+{
+       return 0;               /* FIXME */
+}
+
+static struct registry_operations registry_ops = {
+       .read   = mutex_registry_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 /**
  * @fn int rt_mutex_create(RT_MUTEX *mutex, const char *name)
  * @brief Create a mutex.
@@ -126,8 +145,18 @@ int rt_mutex_create(RT_MUTEX *mutex, const char *name)
        if (syncluster_addobj(&alchemy_mutex_table, mcb->name, &mcb->cobj)) {
                xnfree(mcb);
                ret = -EEXIST;
-       } else
+       } else {
                mutex->handle = mainheap_ref(mcb, uintptr_t);
+               registry_init_file(&mcb->fsobj, &registry_ops, 0);
+               ret = __bt(registry_add_file(&mcb->fsobj, O_RDONLY,
+                                            "/alchemy/mutexes/%s",
+                                            mcb->name));
+               if (ret) {
+                       warning("failed to export mutex %s to registry",
+                               mcb->name);
+                       ret = 0;
+               }
+       }
 out:
        CANCEL_RESTORE(svc);
 
@@ -181,6 +210,7 @@ int rt_mutex_delete(RT_MUTEX *mutex)
 
        mcb->magic = ~mutex_magic;
        syncluster_delobj(&alchemy_mutex_table, &mcb->cobj);
+       registry_destroy_file(&mcb->fsobj);
        xnfree(mcb);
 out:
        CANCEL_RESTORE(svc);
diff --git a/lib/alchemy/mutex.h b/lib/alchemy/mutex.h
index 8db7acb..8a55b5c 100644
--- a/lib/alchemy/mutex.h
+++ b/lib/alchemy/mutex.h
@@ -20,6 +20,7 @@
 #define _ALCHEMY_MUTEX_H
 
 #include <copperplate/cluster.h>
+#include <copperplate/registry.h>
 #include <alchemy/mutex.h>
 #include <alchemy/task.h>
 
@@ -29,6 +30,7 @@ struct alchemy_mutex {
        pthread_mutex_t lock;
        struct clusterobj cobj;
        RT_TASK owner;
+       struct fsobj fsobj;
 };
 
 #define mutex_magic    0x8585ebeb
diff --git a/lib/alchemy/queue.c b/lib/alchemy/queue.c
index 0f536c5..ef9320f 100644
--- a/lib/alchemy/queue.c
+++ b/lib/alchemy/queue.c
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <copperplate/threadobj.h>
 #include <copperplate/heapobj.h>
+#include <copperplate/registry-obstack.h>
 #include "reference.h"
 #include "internal.h"
 #include "queue.h"
@@ -44,11 +45,94 @@ static DEFINE_NAME_GENERATOR(queue_namegen, "queue",
 
 DEFINE_SYNC_LOOKUP(queue, RT_QUEUE);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static int prepare_waiter_cache(struct fsobstack *o,
+                               struct obstack *cache, int item_count)
+{
+       const struct alchemy_queue *qcb;
+
+       fsobstack_grow_format(o, "--\n[WAITER]\n");
+       obstack_blank(cache, item_count * sizeof(qcb->name));
+
+       return 0;
+}
+
+static size_t collect_waiter_data(void *p, struct threadobj *thobj)
+{
+       const char *name = threadobj_get_name(thobj);
+       int len = strlen(name);
+
+       strcpy(p, name);
+       *(char *)(p + len) = '\n';
+
+       return len + 1;
+}
+
+static struct fsobstack_syncops fill_ops = {
+       .prepare_cache = prepare_waiter_cache,
+       .collect_data = collect_waiter_data,
+};
+
+static int queue_registry_open(struct fsobj *fsobj, void *priv)
+{
+       size_t usable_mem, used_mem, limit;
+       struct fsobstack *o = priv;
+       struct alchemy_queue *qcb;
+       struct syncstate syns;
+       unsigned int mcount;
+       int mode, ret;
+
+       qcb = container_of(fsobj, struct alchemy_queue, fsobj);
+
+       ret = syncobj_lock(&qcb->sobj, &syns);
+       if (ret)
+               return -EIO;
+
+       usable_mem = heapobj_size(&qcb->hobj);
+       used_mem = heapobj_inquire(&qcb->hobj);
+       limit = qcb->limit;
+       mcount = qcb->mcount;
+       mode = qcb->mode;
+
+       syncobj_unlock(&qcb->sobj, &syns);
+
+       fsobstack_init(o);
+
+       fsobstack_grow_format(o, "%6s  %10s  %9s  %8s  %s\n",
+                             "[TYPE]", "[TOTALMEM]", "[USEDMEM]", "[QLIMIT]", 
"[MCOUNT]");
+       fsobstack_grow_format(o, " %s   %9Zu  %9Zu  %8Zu  %8u\n",
+                             mode & Q_PRIO ? "PRIO" : "FIFO",
+                             usable_mem,
+                             used_mem,
+                             limit,
+                             mcount);
+
+       fsobstack_grow_syncobj_grant(o, &qcb->sobj, &fill_ops);
+
+       fsobstack_finish(o);
+
+       return 0;
+}
+
+static struct registry_operations registry_ops = {
+       .open           = queue_registry_open,
+       .release        = fsobj_obstack_release,
+       .read           = fsobj_obstack_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 static void queue_finalize(struct syncobj *sobj)
 {
        struct alchemy_queue *qcb;
 
        qcb = container_of(sobj, struct alchemy_queue, sobj);
+       registry_destroy_file(&qcb->fsobj);
        heapobj_destroy(&qcb->hobj);
        xnfree(qcb);
 }
@@ -169,14 +253,23 @@ int rt_queue_create(RT_QUEUE *queue, const char *name,
        syncobj_init(&qcb->sobj, CLOCK_COPPERPLATE, sobj_flags,
                     fnref_put(libalchemy, queue_finalize));
 
-       ret = 0;
        if (syncluster_addobj(&alchemy_queue_table, qcb->name, &qcb->cobj)) {
                heapobj_destroy(&qcb->hobj);
                syncobj_uninit(&qcb->sobj);
                xnfree(qcb);
                ret = -EEXIST;
-       } else
+       } else {
                queue->handle = mainheap_ref(qcb, uintptr_t);
+               registry_init_file_obstack(&qcb->fsobj, &registry_ops);
+               ret = __bt(registry_add_file(&qcb->fsobj, O_RDONLY,
+                                            "/alchemy/queues/%s",
+                                            qcb->name));
+               if (ret) {
+                       warning("failed to export queue %s to registry",
+                               qcb->name);
+                       ret = 0;
+               }
+       }
 out:
        CANCEL_RESTORE(svc);
 
diff --git a/lib/alchemy/queue.h b/lib/alchemy/queue.h
index 2fdb72f..ddfe2ed 100644
--- a/lib/alchemy/queue.h
+++ b/lib/alchemy/queue.h
@@ -21,6 +21,7 @@
 
 #include <boilerplate/list.h>
 #include <copperplate/syncobj.h>
+#include <copperplate/registry.h>
 #include <copperplate/cluster.h>
 #include <copperplate/heapobj.h>
 #include <alchemy/queue.h>
@@ -35,6 +36,7 @@ struct alchemy_queue {
        struct clusterobj cobj;
        struct list mq;
        unsigned int mcount;
+       struct fsobj fsobj;
 };
 
 #define queue_magic    0x8787ebeb
diff --git a/lib/alchemy/sem.c b/lib/alchemy/sem.c
index 16ab4ba..d5ed5a7 100644
--- a/lib/alchemy/sem.c
+++ b/lib/alchemy/sem.c
@@ -40,8 +40,10 @@
 
 #include <errno.h>
 #include <string.h>
+#include <stdlib.h>
 #include <copperplate/threadobj.h>
 #include <copperplate/heapobj.h>
+#include <copperplate/registry-obstack.h>
 #include "reference.h"
 #include "internal.h"
 #include "sem.h"
@@ -54,9 +56,67 @@ static DEFINE_NAME_GENERATOR(sem_namegen, "sem",
 
 DEFINE_LOOKUP_PRIVATE(sem, RT_SEM);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static int sem_registry_open(struct fsobj *fsobj, void *priv)
+{
+       struct semobj_waitentry *waitlist, *p;
+       struct fsobstack *o = priv;
+       struct alchemy_sem *scb;
+       size_t waitsz;
+       int ret, val;
+
+       scb = container_of(fsobj, struct alchemy_sem, fsobj);
+
+       waitsz = sizeof(*p) * 256;
+       waitlist = __STD(malloc(waitsz));
+       if (waitlist == NULL)
+               return -ENOMEM;
+
+       ret = semobj_inquire(&scb->smobj, waitsz, waitlist, &val);
+       if (ret < 0)
+               goto out;
+
+       fsobstack_init(o);
+
+       if (val < 0)
+               val = 0; /* Report depleted state as null. */
+
+       fsobstack_grow_format(o, "=%d\n", val);
+
+       if (ret) {
+               fsobstack_grow_format(o, "--\n[WAITER]\n");
+               p = waitlist;
+               do {
+                       fsobstack_grow_format(o, "%s\n", p->name);
+                       p++;
+               } while (--ret > 0);
+       }
+
+       fsobstack_finish(o);
+out:
+       __STD(free(waitlist));
+
+       return ret;
+}
+
+static struct registry_operations registry_ops = {
+       .open           = sem_registry_open,
+       .release        = fsobj_obstack_release,
+       .read           = fsobj_obstack_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 static void sem_finalize(struct semobj *smobj)
 {
        struct alchemy_sem *scb = container_of(smobj, struct alchemy_sem, 
smobj);
+
+       registry_destroy_file(&scb->fsobj);
        /* We should never fail here, so we backtrace. */
        __bt(syncluster_delobj(&alchemy_sem_table, &scb->cobj));
        scb->magic = ~sem_magic;
@@ -154,8 +214,18 @@ int rt_sem_create(RT_SEM *sem, const char *name,
                semobj_destroy(&scb->smobj);
                xnfree(scb);
                ret = -EEXIST;
-       } else
+       } else {
                sem->handle = mainheap_ref(scb, uintptr_t);
+               registry_init_file_obstack(&scb->fsobj, &registry_ops);
+               ret = __bt(registry_add_file(&scb->fsobj, O_RDONLY,
+                                            "/alchemy/semaphores/%s",
+                                            scb->name));
+               if (ret) {
+                       warning("failed to export semaphore %s to registry",
+                               scb->name);
+                       ret = 0;
+               }
+       }
 out:
        CANCEL_RESTORE(svc);
 
diff --git a/lib/alchemy/sem.h b/lib/alchemy/sem.h
index a916021..f8bacf1 100644
--- a/lib/alchemy/sem.h
+++ b/lib/alchemy/sem.h
@@ -20,6 +20,7 @@
 #define _ALCHEMY_SEM_H
 
 #include <copperplate/semobj.h>
+#include <copperplate/registry.h>
 #include <copperplate/cluster.h>
 #include <alchemy/sem.h>
 
@@ -28,6 +29,7 @@ struct alchemy_sem {
        char name[32];
        struct semobj smobj;
        struct clusterobj cobj;
+       struct fsobj fsobj;
 };
 
 #define sem_magic      0x8383ebeb
diff --git a/lib/alchemy/task.c b/lib/alchemy/task.c
index 59a076a..bd238c3 100644
--- a/lib/alchemy/task.c
+++ b/lib/alchemy/task.c
@@ -42,6 +42,44 @@ struct syncluster alchemy_task_table;
 static DEFINE_NAME_GENERATOR(task_namegen, "task",
                             struct alchemy_task, name);
 
+#ifdef CONFIG_XENO_REGISTRY
+
+static int task_registry_open(struct fsobj *fsobj, void *priv)
+{
+       struct fsobstack *o = priv;
+       struct threadobj_stat buf;
+       struct alchemy_task *tcb;
+       int ret;
+
+       tcb = container_of(fsobj, struct alchemy_task, fsobj);
+       ret = threadobj_lock(&tcb->thobj);
+       if (ret)
+               return -EIO;
+
+       ret = threadobj_stat(&tcb->thobj, &buf);
+       threadobj_unlock(&tcb->thobj);
+       if (ret)
+               return ret;
+
+       fsobstack_init(o);
+
+       fsobstack_finish(o);
+
+       return 0;
+}
+
+static struct registry_operations registry_ops = {
+       .open           = task_registry_open,
+       .release        = fsobj_obstack_release,
+       .read           = fsobj_obstack_read
+};
+
+#else /* !CONFIG_XENO_REGISTRY */
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
 static struct alchemy_task *find_alchemy_task(RT_TASK *task, int *err_r)
 {
        struct alchemy_task *tcb;
@@ -134,6 +172,7 @@ static void task_finalizer(struct threadobj *thobj)
        struct syncstate syns;
 
        tcb = container_of(thobj, struct alchemy_task, thobj);
+       registry_destroy_file(&tcb->fsobj);
        syncluster_delobj(&alchemy_task_table, &tcb->cobj);
        /*
         * The msg sync may be pended by other threads, so we do have
@@ -243,6 +282,14 @@ static int create_tcb(struct alchemy_task **tcbp, RT_TASK 
*task,
                return -EEXIST;
        }
 
+       registry_init_file_obstack(&tcb->fsobj, &registry_ops);
+       ret = __bt(registry_add_file(&tcb->fsobj, O_RDONLY,
+                                    "/alchemy/tasks/%s",
+                                    tcb->name));
+       if (ret)
+               warning("failed to export task %s to registry",
+                       tcb->name);
+
        if (task)
                task->handle = tcb->self.handle;
 
diff --git a/lib/alchemy/task.h b/lib/alchemy/task.h
index 3e3320d..b7277a1 100644
--- a/lib/alchemy/task.h
+++ b/lib/alchemy/task.h
@@ -25,6 +25,7 @@
 #include <boilerplate/list.h>
 #include <copperplate/syncobj.h>
 #include <copperplate/threadobj.h>
+#include <copperplate/registry.h>
 #include <copperplate/cluster.h>
 #include <alchemy/task.h>
 
@@ -40,6 +41,7 @@ struct alchemy_task {
        void (*entry)(void *arg);
        void *arg;
        RT_TASK self;
+       struct fsobj fsobj;
 };
 
 struct alchemy_task_wait {


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

Reply via email to