Module: xenomai-forge Branch: next Commit: 3ad913bef35df22b7cb0fd1b176ec9c7d75b05a3 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=3ad913bef35df22b7cb0fd1b176ec9c7d75b05a3
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 | 33 ++++++++++++++- lib/alchemy/sem.h | 2 + lib/alchemy/task.c | 47 +++++++++++++++++++++ lib/alchemy/task.h | 2 + 19 files changed, 591 insertions(+), 8 deletions(-) diff --git a/lib/alchemy/alarm.c b/lib/alchemy/alarm.c index e622ea4..fed8df1 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; + + fsobstack_init(o); + + 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_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, ®istry_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, ®istry_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, ®istry_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, ®istry_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, ®istry_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, ®istry_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, ®istry_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..3d3c601 100644 --- a/lib/alchemy/sem.c +++ b/lib/alchemy/sem.c @@ -54,9 +54,30 @@ static DEFINE_NAME_GENERATOR(sem_namegen, "sem", DEFINE_LOOKUP_PRIVATE(sem, RT_SEM); +#ifdef CONFIG_XENO_REGISTRY + +static ssize_t sem_registry_read(struct fsobj *fsobj, + char *buf, size_t size, off_t offset, + void *priv) +{ + return 0; +} + +static struct registry_operations registry_ops = { + .read = sem_registry_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 +175,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(&scb->fsobj, ®istry_ops, 0); + 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, ®istry_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