* [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
@ 2013-10-15 8:50 Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 1 of 3] Initial implementation registry pSOS task Kim De Mey
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Kim De Mey @ 2013-10-15 8:50 UTC (permalink / raw)
To: xenomai
This patch set adds an initial implementation of registry for pSOS
tasks, semaphores and queues. It is similar as the already existing
vxworks implementation but with more output data.
Important to mention is that the "size" parameter in the read function
is not used (it is also not used in the vxworks implementation).
This will be an issue if the data to output is larger than the buffer
used. This is now possible to happen as I added messages in the queue
read function and timers in the task read function. In that case an
implementation which uses size & offset is necessary.
I am busy implementing a second patch that does this.
It creates a local buffer which is filled with the data on an "open"
call. A pointer to the local buffer is saved in the fuse_file_info->fh
field (requires FUSE version >= 2.5). A read will then just read from
the local buffer with offset and size given. A release is also needed to
free the buffer.
However while I continue with this I would like to know whether you see
this as the right way to go. Does the data I output (and the format) in
this patch make sense to you? And in case yes, shall I continue to
implement the second patch as described above or are there other views
on this? It might be a bit vague without actually seeing code but if you
want I can already submit a preliminary version of the second patch.
Kim
include/psos/psos.h | 2 ++
lib/psos/queue.c | 77 ++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++
lib/psos/queue.h | 1 +
lib/psos/sem.c | 43 +++++++++++++++++++++++++++++++++++++++++++
lib/psos/sem.h | 1 +
lib/psos/task.c | 115 ++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/psos/task.h | 4 ++++
7 files changed, 243 insertions(+), 0 deletions(-)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Xenomai] [PATCH 1 of 3] Initial implementation registry pSOS task
2013-10-15 8:50 [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Kim De Mey
@ 2013-10-15 8:50 ` Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 2 of 3] Initial implementation registry pSOS semaphore Kim De Mey
` (2 subsequent siblings)
3 siblings, 0 replies; 12+ messages in thread
From: Kim De Mey @ 2013-10-15 8:50 UTC (permalink / raw)
To: xenomai
Initial implementation of the registry functionality
for pSOS tasks.
Signed-off-by: Kim De Mey <kim.demey@gmail.com>
---
diff --git a/include/psos/psos.h b/include/psos/psos.h
--- a/include/psos/psos.h
+++ b/include/psos/psos.h
@@ -367,6 +367,8 @@ u_long tm_wkwhen(u_long date,
int psos_task_normalize_priority(unsigned long psos_prio);
+int psos_task_denormalize_priority(unsigned long core_prio);
+
extern unsigned int psos_long_names;
#ifdef __cplusplus
diff --git a/lib/psos/task.c b/lib/psos/task.c
--- a/lib/psos/task.c
+++ b/lib/psos/task.c
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
+#include <fcntl.h>
#include "copperplate/init.h"
#include "copperplate/heapobj.h"
#include "copperplate/threadobj.h"
@@ -167,8 +168,99 @@ static void task_finalizer(struct thread
/* We have to hold a lock on a syncobj to destroy it. */
syncobj_lock(&task->sobj, &syns);
syncobj_destroy(&task->sobj, &syns);
+
+ registry_destroy_file(&task->fsobj);
}
+#ifdef CONFIG_XENO_REGISTRY
+
+static inline char *task_decode_status(struct psos_task *task, char *buf)
+{
+ int status;
+
+ *buf = '\0';
+ if (threadobj_get_lockdepth(&task->thobj) > 0)
+ strcat(buf, "+sched_lock");
+ status = threadobj_get_status(&task->thobj);
+ if (status & __THREAD_S_RR)
+ strcat(buf, "+sched_rr");
+ if (status & __THREAD_S_SUSPENDED)
+ strcat(buf, "+suspended");
+ if (status & (__THREAD_S_WAIT|__THREAD_S_TIMEDWAIT))
+ strcat(buf, "+pending");
+ else if (status & __THREAD_S_DELAYED)
+ strcat(buf, "+delayed");
+ else
+ strcat(buf, "+ready");
+
+ return buf + 1;
+}
+
+static ssize_t task_registry_read(struct fsobj *fsobj,
+ char *buf, size_t size, off_t offset)
+{
+ struct psos_task *task;
+ char sbuf[64];
+ size_t len;
+ int i;
+ struct psos_tm *tm, *tmp;
+
+ task = container_of(fsobj, struct psos_task, fsobj);
+ len = sprintf(buf, "%-11s= %11s\n", "name", task->name);
+ len += sprintf(buf + len, "%-11s= %11d\n", "errno",
+ threadobj_get_errno(&task->thobj));
+ len += sprintf(buf + len, "%-11s= %11s\n", "status",
+ task_decode_status(task, sbuf));
+ len += sprintf(buf + len, "%-11s= %11d\n", "priority",
+ psos_task_get_priority(task));
+ len += sprintf(buf + len, "%-11s= %11d\n", "lock_depth",
+ threadobj_get_lockdepth(&task->thobj));
+ len += sprintf(buf + len, "%-11s= %11d\n", "mode", task->mode);
+ len += sprintf(buf + len, "%-11s= %#011lx\n", "task_id",
+ mainheap_ref(task, u_long));
+ len += sprintf(buf + len, "%-11s= %11d\n", "process_id",
+ threadobj_get_pid(&task->thobj));
+ len += sprintf(buf + len, "%-11s= %11lu\n", "events", task->events);
+
+ len += sprintf(buf + len, "\n%-11s= \n", "notepad");
+ len += sprintf(buf + len, "%-11s %-11s\n", "register", "value");
+ for (i=0;i<PSOSTASK_NR_REGS;i++) {
+ len += sprintf(buf + len, "%-11i %-11lu\n", i, task->notepad[i]);
+ }
+
+ len += sprintf(buf + len, "\n%-11s= \n", "timer_list");
+ if (!pvlist_empty(&task->timer_list)) {
+ len += sprintf(buf + len, "%-11s %-11s %-11s %-11s %-11s %-11s %-11s\n",
+ "tmid", "tid", "tm_events",
+ "interval_s","interval_ns", "value_s", "value_ns");
+ pvlist_for_each_entry_safe(tm, tmp, &task->timer_list, link) {
+ len += sprintf(buf + len,
+ "%-11lu %#011lx %-11lu %-11ld %-11ld %-11ld %-11ld\n",
+ mainheap_ref(tm, u_long), tm->tid, tm->events,
+ (long) tm->tmobj.itspec.it_interval.tv_sec,
+ tm->tmobj.itspec.it_interval.tv_nsec,
+ (long) tm->tmobj.itspec.it_value.tv_sec,
+ tm->tmobj.itspec.it_value.tv_nsec);
+ }
+ }
+
+ if(len < offset)
+ return (ssize_t)0;
+ else
+ return (ssize_t)len;
+}
+
+static struct registry_operations registry_ops = {
+ .read = task_registry_read
+};
+
+#else
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
+
static void *task_trampoline(void *arg)
{
struct psos_task *task = arg;
@@ -182,6 +274,12 @@ static void *task_trampoline(void *arg)
CANCEL_DEFER(svc);
+ ret = __bt(registry_add_file(&task->fsobj, O_RDONLY,
+ "/psos/tasks/%s", task->name));
+ if (ret)
+ warning("failed to export task %s to registry",
+ task->name);
+
threadobj_wait_start();
threadobj_lock(&task->thobj);
@@ -234,6 +332,13 @@ int psos_task_normalize_priority(unsigne
return psos_prio;
}
+__attribute__ ((weak))
+int psos_task_denormalize_priority(unsigned long core_prio)
+{
+ /* Map a SCHED_RT priority level to a pSOS one. */
+ return core_prio;
+}
+
static int check_task_priority(u_long psos_prio, int *core_prio)
{
if (psos_prio < 1 || psos_prio > 255) /* In theory. */
@@ -244,6 +349,13 @@ static int check_task_priority(u_long ps
return SUCCESS;
}
+int psos_task_get_priority(struct psos_task *task)
+{
+ /* Can't fail if we hold the task lock as we should. */
+ int prio = threadobj_get_priority(&task->thobj);
+ return psos_task_denormalize_priority(prio);
+}
+
u_long t_create(const char *name, u_long prio,
u_long sstack, u_long ustack, u_long flags, u_long *tid_r)
{
@@ -309,6 +421,8 @@ u_long t_create(const char *name, u_long
idata.priority = cprio;
threadobj_init(&task->thobj, &idata);
+ registry_init_file(&task->fsobj, ®istry_ops);
+
cta.prio = cprio;
cta.start = task_trampoline;
cta.arg = task;
@@ -317,6 +431,7 @@ u_long t_create(const char *name, u_long
ret = __bt(copperplate_create_thread(&cta, &task->thobj.tid));
if (ret) {
+ registry_destroy_file(&task->fsobj);
cluster_delobj(&psos_task_table, &task->cobj);
threadobj_destroy(&task->thobj);
ret = ERR_NOTCB;
diff --git a/lib/psos/task.h b/lib/psos/task.h
--- a/lib/psos/task.h
+++ b/lib/psos/task.h
@@ -23,6 +23,7 @@
#include <copperplate/threadobj.h>
#include <copperplate/syncobj.h>
#include <copperplate/cluster.h>
+#include <copperplate/registry.h>
struct psos_task_args {
void (*entry)(u_long a0, u_long a1, u_long a2, u_long a3);
@@ -46,10 +47,13 @@ struct psos_task {
struct psos_task_args args;
struct threadobj thobj;
+ struct fsobj fsobj;
struct syncobj sobj; /* For events. */
struct clusterobj cobj;
};
+int psos_task_get_priority(struct psos_task *task);
+
#define task_magic 0x8181fafa
static inline struct psos_task *psos_task_current(void)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Xenomai] [PATCH 2 of 3] Initial implementation registry pSOS semaphore
2013-10-15 8:50 [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 1 of 3] Initial implementation registry pSOS task Kim De Mey
@ 2013-10-15 8:50 ` Kim De Mey
2013-10-22 16:54 ` Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 3 of 3] Initial implementation registry pSOS queue Kim De Mey
2013-10-19 17:37 ` [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Philippe Gerum
3 siblings, 1 reply; 12+ messages in thread
From: Kim De Mey @ 2013-10-15 8:50 UTC (permalink / raw)
To: xenomai
Initial implementation of the registry functionality
for pSOS semaphores.
Signed-off-by: Kim De Mey <kim.demey@gmail.com>
---
diff --git a/lib/psos/sem.c b/lib/psos/sem.c
--- a/lib/psos/sem.c
+++ b/lib/psos/sem.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
#include <copperplate/heapobj.h>
#include <copperplate/init.h>
#include <copperplate/cluster.h>
@@ -68,10 +69,44 @@ objid_error:
static void sem_finalize(struct semobj *smobj)
{
struct psos_sem *sem = container_of(smobj, struct psos_sem, smobj);
+ registry_destroy_file(&sem->fsobj);
xnfree(sem);
}
fnref_register(libpsos, sem_finalize);
+#ifdef CONFIG_XENO_REGISTRY
+
+static ssize_t sem_registry_read(struct fsobj *fsobj,
+ char *buf, size_t size, off_t offset)
+{
+ struct psos_sem *sem;
+ size_t len;
+ int value;
+
+ sem = container_of(fsobj, struct psos_sem, fsobj);
+ semobj_getvalue(&sem->smobj , &value);
+ len = sprintf(buf, "%-11s= %11s\n", "name", sem->name);
+ len += sprintf(buf + len, "%-11s= %#011lx\n","sem_id", mainheap_ref(sem, u_long));
+ len += sprintf(buf + len, "%-11s= %11d\n", "value", value);
+
+ if(len < offset)
+ return (ssize_t)0;
+ else
+ return (ssize_t)len;
+}
+
+
+static struct registry_operations registry_ops = {
+ .read = sem_registry_read
+};
+
+#else
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
+
u_long sm_create(const char *name,
u_long count, u_long flags, u_long *smid_r)
{
@@ -116,6 +151,14 @@ u_long sm_create(const char *name,
goto out;
}
+ registry_init_file(&sem->fsobj, ®istry_ops);
+
+ ret = __bt(registry_add_file(&sem->fsobj, O_RDONLY,
+ "/psos/semaphores/%s", sem->name));
+ if (ret)
+ warning("failed to export semaphore %s to registry",
+ sem->name);
+
*smid_r = mainheap_ref(sem, u_long);
out:
CANCEL_RESTORE(svc);
diff --git a/lib/psos/sem.h b/lib/psos/sem.h
--- a/lib/psos/sem.h
+++ b/lib/psos/sem.h
@@ -28,6 +28,7 @@ struct psos_sem {
char name[32];
struct semobj smobj;
struct clusterobj cobj;
+ struct fsobj fsobj;
};
extern struct cluster psos_sem_table;
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Xenomai] [PATCH 3 of 3] Initial implementation registry pSOS queue
2013-10-15 8:50 [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 1 of 3] Initial implementation registry pSOS task Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 2 of 3] Initial implementation registry pSOS semaphore Kim De Mey
@ 2013-10-15 8:50 ` Kim De Mey
2013-10-19 17:37 ` [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Philippe Gerum
3 siblings, 0 replies; 12+ messages in thread
From: Kim De Mey @ 2013-10-15 8:50 UTC (permalink / raw)
To: xenomai
Initial implementation of the registry functionality
for pSOS queues.
Signed-off-by: Kim De Mey <kim.demey@gmail.com>
---
diff --git a/lib/psos/queue.c b/lib/psos/queue.c
--- a/lib/psos/queue.c
+++ b/lib/psos/queue.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <stdlib.h>
#include <memory.h>
+#include <fcntl.h>
#include <copperplate/threadobj.h>
#include <copperplate/heapobj.h>
#include <copperplate/clockobj.h>
@@ -74,10 +75,78 @@ objid_error:
static void queue_finalize(struct syncobj *sobj)
{
struct psos_queue *q = container_of(sobj, struct psos_queue, sobj);
+ registry_destroy_file(&q->fsobj);
xnfree(q);
}
fnref_register(libpsos, queue_finalize);
+#ifdef CONFIG_XENO_REGISTRY
+
+static ssize_t queue_registry_read(struct fsobj *fsobj,
+ char *buf, size_t size, off_t offset)
+{
+ struct psos_queue *queue;
+ size_t len;
+ struct msgholder *msg, *tmp;
+ int i;
+ void *msgbuffer = NULL;
+ int typesize;
+
+ queue = container_of(fsobj, struct psos_queue, fsobj);
+
+ if(queue->flags & Q_VARIABLE) {
+ // If queue is variable, we do not know type so we select one byte
+ typesize = 1;
+ }
+ else {
+ typesize = sizeof(unsigned long);
+ }
+ msgbuffer = (void*) malloc(queue->maxlen + 1);
+ if(msgbuffer == NULL)
+ return -ENOMEM;
+
+ len = sprintf(buf, "%-14s= %11s\n", "name", queue->name);
+ len += sprintf(buf + len, "%-14s= %#011lx\n","queue_id", mainheap_ref(queue, u_long));
+ len += sprintf(buf + len, "%-14s= %11lu\n", "message_count", queue->msgcount);
+ len += sprintf(buf + len, "%-14s= %11lu\n", "max_messages", queue->maxmsg);
+ len += sprintf(buf + len, "%-14s= %11lu\n", "max_length", queue->maxlen);
+ len += sprintf(buf + len, "%-14s= \n", "messages");
+
+ if (!list_empty(&queue->msg_list)) {
+ list_for_each_entry_safe(msg, tmp, &queue->msg_list, link) {
+ memcpy(msgbuffer, msg + 1, msg->size);
+ for(i = 0; i < msg->size/typesize; i++){
+ if(queue->flags & Q_VARIABLE) {
+ len += sprintf(buf + len, "%02x ",
+ *(unsigned char *) (msgbuffer + i));
+ }
+ else {
+ len += sprintf(buf + len, "%lu ",
+ *(unsigned long *) (msgbuffer + i * typesize));
+ }
+ }
+ len += sprintf(buf + len, "\n");
+ }
+ }
+ free(msgbuffer);
+
+ if(len < offset)
+ return (ssize_t)0;
+ else
+ return (ssize_t)len;
+}
+
+
+static struct registry_operations registry_ops = {
+ .read = queue_registry_read
+};
+
+#else
+
+static struct registry_operations registry_ops;
+
+#endif /* CONFIG_XENO_REGISTRY */
+
static u_long __q_create(const char *name, u_long count,
u_long flags, u_long maxlen, u_long *qid_r)
{
@@ -122,6 +191,14 @@ static u_long __q_create(const char *nam
q->msgcount = 0;
q->magic = queue_magic;
*qid_r = mainheap_ref(q, u_long);
+
+ registry_init_file(&q->fsobj, ®istry_ops);
+
+ ret = __bt(registry_add_file(&q->fsobj, O_RDONLY,
+ "/psos/queues/%s", q->name));
+ if (ret)
+ warning("failed to export queue %s to registry",
+ q->name);
out:
CANCEL_RESTORE(svc);
diff --git a/lib/psos/queue.h b/lib/psos/queue.h
--- a/lib/psos/queue.h
+++ b/lib/psos/queue.h
@@ -39,6 +39,7 @@ struct psos_queue {
struct syncobj sobj;
struct list msg_list;
struct clusterobj cobj;
+ struct fsobj fsobj;
};
struct psos_queue_wait {
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
2013-10-15 8:50 [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Kim De Mey
` (2 preceding siblings ...)
2013-10-15 8:50 ` [Xenomai] [PATCH 3 of 3] Initial implementation registry pSOS queue Kim De Mey
@ 2013-10-19 17:37 ` Philippe Gerum
2013-10-19 18:56 ` Ronny Meeus
3 siblings, 1 reply; 12+ messages in thread
From: Philippe Gerum @ 2013-10-19 17:37 UTC (permalink / raw)
To: Kim De Mey, xenomai
On 10/15/2013 10:50 AM, Kim De Mey wrote:
> This patch set adds an initial implementation of registry for pSOS
> tasks, semaphores and queues. It is similar as the already existing
> vxworks implementation but with more output data.
>
> Important to mention is that the "size" parameter in the read function
> is not used (it is also not used in the vxworks implementation).
> This will be an issue if the data to output is larger than the buffer
> used. This is now possible to happen as I added messages in the queue
> read function and timers in the task read function. In that case an
> implementation which uses size & offset is necessary.
>
> I am busy implementing a second patch that does this.
> It creates a local buffer which is filled with the data on an "open"
> call. A pointer to the local buffer is saved in the fuse_file_info->fh
> field (requires FUSE version >= 2.5). A read will then just read from
> the local buffer with offset and size given. A release is also needed to
> free the buffer.
>
> However while I continue with this I would like to know whether you see
> this as the right way to go.
IIUC, this would add the quite unexpected requirement of having to
reopen a file for getting fresh data. read() should actually (re-)read
the current object state each time it is invoked, and not resend some
frozen state collected by the corresponding open() indefinitely.
e.g. this has to work with code like:
fd = open("/mnt/xenomai/1235/foo/tasks", O_RDONLY);
for (;;) {
ret = read(fd, buf, sizeof(buf));
... process NEW data ...
}
As I mentioned earlier, referring to fuse_file_info->fh from a registry
client is not acceptable. Exposing this fs-private information to the
clients directly (e.g. psos emulator) would prevent any further use by
copperplate/registry although it's actually the fs implementation layer
(not psos). So the day we'd need to store private data for the registry
fs, we could not use fh, although this is what we should definitely be
using in this case.
If you really need to provide for holding private data in a fuse _file_
object, instead of a copperplate _filesystem_ object (i.e. struct
fsobj), then the fuse file object should be abstracted first in
copperplate/registry (e.g. struct fileobj), then passed as an additional
parameter to all client callbacks. That file (descriptor) object could
then hold a client-specific private data pointer. In short, this change
should be introduced in the generic registry layer, not in the psos
emulator.
The question being: do you really need this?
--
Philippe.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
2013-10-19 17:37 ` [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Philippe Gerum
@ 2013-10-19 18:56 ` Ronny Meeus
2013-10-22 16:45 ` Kim De Mey
0 siblings, 1 reply; 12+ messages in thread
From: Ronny Meeus @ 2013-10-19 18:56 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai
>
>
>
>
> IIUC, this would add the quite unexpected requirement of having to reopen
> a file for getting fresh data. read() should actually (re-)read the current
> object state each time it is invoked, and not resend some frozen state
> collected by the corresponding open() indefinitely.
>
> e.g. this has to work with code like:
>
> fd = open("/mnt/xenomai/1235/foo/**tasks", O_RDONLY);
> for (;;) {
> ret = read(fd, buf, sizeof(buf));
> ... process NEW data ...
> }
>
>
Philippe,
how to handle the case where the data is bigger than de buffer passed by
the user?
Suppose the task data is 20k while the user read only wants 4k. I would
expect that the second read returns the second 4k block and so on.
By generating the complete output in 1 shot (for example at open), the data
would be more consistent in my opinion too.
Suppose the data of a queue is dumped and the queue contains a lot of
messages. I would like to see a consistent view on the queue and not the
first 4k followed by some random messages after it because the application
is processing the queue in parallel.
Ronny
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
2013-10-19 18:56 ` Ronny Meeus
@ 2013-10-22 16:45 ` Kim De Mey
2013-10-22 17:06 ` Philippe Gerum
0 siblings, 1 reply; 12+ messages in thread
From: Kim De Mey @ 2013-10-22 16:45 UTC (permalink / raw)
To: Ronny Meeus; +Cc: xenomai
2013/10/19 Ronny Meeus <ronny.meeus@gmail.com>
>
>>
>>
>> IIUC, this would add the quite unexpected requirement of having to reopen
>> a file for getting fresh data. read() should actually (re-)read the current
>> object state each time it is invoked, and not resend some frozen state
>> collected by the corresponding open() indefinitely.
>>
>> e.g. this has to work with code like:
>>
>> fd = open("/mnt/xenomai/1235/foo/**tasks", O_RDONLY);
>> for (;;) {
>> ret = read(fd, buf, sizeof(buf));
>> ... process NEW data ...
>> }
>>
>>
> Philippe,
>
> how to handle the case where the data is bigger than de buffer passed by
> the user?
> Suppose the task data is 20k while the user read only wants 4k. I would
> expect that the second read returns the second 4k block and so on.
>
> By generating the complete output in 1 shot (for example at open), the
> data would be more consistent in my opinion too.
> Suppose the data of a queue is dumped and the queue contains a lot of
> messages. I would like to see a consistent view on the queue and not the
> first 4k followed by some random messages after it because the application
> is processing the queue in parallel.
>
>
Philippe,
As Ronny explains, the reason of "storing the state" at open is so that the
data we read would be consistent. So yes, I think we need this.
I checked how this is handled in sysfs. There a buffer is also filled but
it is done at the first read and it is refilled at a new read with offset
0. Not at an open. Would it be acceptable to implement it also like this in
the registry?
This brings me to your second remark of referring to fuse_file_info->fh
from a registry client. I understand that it is not acceptable, it belongs
indeed in the registry fs. The open, read and release in registry fs could
be implemented similar like sysfs. Then the read operation of the specific
client would be used for filling the buffer at the first regfs_read, and
the buffer will be allocated there in regfs_read and freed in
regfs_release. The location of the buffer and other necessary data could be
stored then in fuse_file_info->fh.
I am currently not sure if there is still client-specific data that needs
to be stored, but I don't think so.
Kim
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 2 of 3] Initial implementation registry pSOS semaphore
2013-10-15 8:50 ` [Xenomai] [PATCH 2 of 3] Initial implementation registry pSOS semaphore Kim De Mey
@ 2013-10-22 16:54 ` Kim De Mey
0 siblings, 0 replies; 12+ messages in thread
From: Kim De Mey @ 2013-10-22 16:54 UTC (permalink / raw)
To: xenomai
2013/10/15 Kim De Mey <kim.demey@gmail.com>
> Initial implementation of the registry functionality
> for pSOS semaphores.
>
> I noticed now that it is probably better to not let the
registry_add_file() call return the data to the return var of sm_create as
this might give an unexpected error at the creation of a semaphore. The
same happens in the patch for a queue.
It is also not consistent as in the patch for a task the error will not be
returned as the registry_add_file is done in the trampoline.
> Signed-off-by: Kim De Mey <kim.demey@gmail.com>
>
> ---
>
> diff --git a/lib/psos/sem.c b/lib/psos/sem.c
> --- a/lib/psos/sem.c
> +++ b/lib/psos/sem.c
> @@ -21,6 +21,7 @@
> #include <errno.h>
> #include <stdlib.h>
> #include <string.h>
> +#include <fcntl.h>
> #include <copperplate/heapobj.h>
> #include <copperplate/init.h>
> #include <copperplate/cluster.h>
> @@ -68,10 +69,44 @@ objid_error:
> static void sem_finalize(struct semobj *smobj)
> {
> struct psos_sem *sem = container_of(smobj, struct psos_sem, smobj);
> + registry_destroy_file(&sem->fsobj);
> xnfree(sem);
> }
> fnref_register(libpsos, sem_finalize);
>
> +#ifdef CONFIG_XENO_REGISTRY
> +
> +static ssize_t sem_registry_read(struct fsobj *fsobj,
> + char *buf, size_t size, off_t offset)
> +{
> + struct psos_sem *sem;
> + size_t len;
> + int value;
> +
> + sem = container_of(fsobj, struct psos_sem, fsobj);
> + semobj_getvalue(&sem->smobj , &value);
> + len = sprintf(buf, "%-11s= %11s\n", "name", sem->name);
> + len += sprintf(buf + len, "%-11s= %#011lx\n","sem_id",
> mainheap_ref(sem, u_long));
> + len += sprintf(buf + len, "%-11s= %11d\n", "value", value);
> +
> + if(len < offset)
> + return (ssize_t)0;
> + else
> + return (ssize_t)len;
> +}
> +
> +
> +static struct registry_operations registry_ops = {
> + .read = sem_registry_read
> +};
> +
> +#else
> +
> +static struct registry_operations registry_ops;
> +
> +#endif /* CONFIG_XENO_REGISTRY */
> +
> +
> u_long sm_create(const char *name,
> u_long count, u_long flags, u_long *smid_r)
> {
> @@ -116,6 +151,14 @@ u_long sm_create(const char *name,
> goto out;
> }
>
> + registry_init_file(&sem->fsobj, ®istry_ops);
> +
> + ret = __bt(registry_add_file(&sem->fsobj, O_RDONLY,
> + "/psos/semaphores/%s", sem->name));
> + if (ret)
> + warning("failed to export semaphore %s to registry",
> + sem->name);
> +
> *smid_r = mainheap_ref(sem, u_long);
> out:
> CANCEL_RESTORE(svc);
> diff --git a/lib/psos/sem.h b/lib/psos/sem.h
> --- a/lib/psos/sem.h
> +++ b/lib/psos/sem.h
> @@ -28,6 +28,7 @@ struct psos_sem {
> char name[32];
> struct semobj smobj;
> struct clusterobj cobj;
> + struct fsobj fsobj;
> };
>
> extern struct cluster psos_sem_table;
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
2013-10-22 16:45 ` Kim De Mey
@ 2013-10-22 17:06 ` Philippe Gerum
2013-10-22 18:18 ` Kim De Mey
0 siblings, 1 reply; 12+ messages in thread
From: Philippe Gerum @ 2013-10-22 17:06 UTC (permalink / raw)
To: Kim De Mey, Ronny Meeus; +Cc: xenomai
On 10/22/2013 06:45 PM, Kim De Mey wrote:
>
>
>
> 2013/10/19 Ronny Meeus <ronny.meeus@gmail.com
> <mailto:ronny.meeus@gmail.com>>
>
>
> IIUC, this would add the quite unexpected requirement of having
> to reopen a file for getting fresh data. read() should actually
> (re-)read the current object state each time it is invoked, and
> not resend some frozen state collected by the corresponding
> open() indefinitely.
>
> e.g. this has to work with code like:
>
> fd = open("/mnt/xenomai/1235/foo/__tasks", O_RDONLY);
> for (;;) {
> ret = read(fd, buf, sizeof(buf));
> ... process NEW data ...
> }
>
> Philippe,
> how to handle the case where the data is bigger than de buffer
> passed by the user?
> Suppose the task data is 20k while the user read only wants 4k. I
> would expect that the second read returns the second 4k block and so on.
> By generating the complete output in 1 shot (for example at open),
> the data would be more consistent in my opinion too.
> Suppose the data of a queue is dumped and the queue contains a lot
> of messages. I would like to see a consistent view on the queue and
> not the first 4k followed by some random messages after it because
> the application is processing the queue in parallel.
>
> Philippe,
>
> As Ronny explains, the reason of "storing the state" at open is so that
> the data we read would be consistent. So yes, I think we need this.
>
I don't think so. Implementing a snapshot mechanism so that reading from
a channel does return a consistent set of data does not mean that we
should do this in open(). This only means that we should implement a
snapshot mechanism for reading.
Any external code to Xenomai (e.g. "cat") shall be able to open a
registry file once, then read from that channel any number of times,
taking a fresh snapshot of the system state each time. This is why
open() cannot be be used for this.
Whether fuse introduces some issues wrt the size of the read buffer is
another matter which is orthogonal to that matter.
--
Philippe.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
2013-10-22 17:06 ` Philippe Gerum
@ 2013-10-22 18:18 ` Kim De Mey
2013-10-24 8:28 ` Kim De Mey
0 siblings, 1 reply; 12+ messages in thread
From: Kim De Mey @ 2013-10-22 18:18 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai
2013/10/22 Philippe Gerum <rpm@xenomai.org>
> On 10/22/2013 06:45 PM, Kim De Mey wrote:
>
>>
>>
>>
>> 2013/10/19 Ronny Meeus <ronny.meeus@gmail.com
>> <mailto:ronny.meeus@gmail.com>**>
>>
>>
>>
>> IIUC, this would add the quite unexpected requirement of having
>> to reopen a file for getting fresh data. read() should actually
>> (re-)read the current object state each time it is invoked, and
>> not resend some frozen state collected by the corresponding
>> open() indefinitely.
>>
>> e.g. this has to work with code like:
>>
>> fd = open("/mnt/xenomai/1235/foo/__**tasks", O_RDONLY);
>>
>> for (;;) {
>> ret = read(fd, buf, sizeof(buf));
>> ... process NEW data ...
>> }
>>
>> Philippe,
>> how to handle the case where the data is bigger than de buffer
>> passed by the user?
>> Suppose the task data is 20k while the user read only wants 4k. I
>> would expect that the second read returns the second 4k block and so
>> on.
>> By generating the complete output in 1 shot (for example at open),
>> the data would be more consistent in my opinion too.
>> Suppose the data of a queue is dumped and the queue contains a lot
>> of messages. I would like to see a consistent view on the queue and
>> not the first 4k followed by some random messages after it because
>> the application is processing the queue in parallel.
>>
>> Philippe,
>>
>> As Ronny explains, the reason of "storing the state" at open is so that
>> the data we read would be consistent. So yes, I think we need this.
>>
>>
> I don't think so. Implementing a snapshot mechanism so that reading from a
> channel does return a consistent set of data does not mean that we should
> do this in open(). This only means that we should implement a snapshot
> mechanism for reading.
>
I meant that we need to be able to "store the state", not that we necessary
need to do it in the open(). My sentence was confusing, sorry. As I
explained further in my previous post we could do it in the initial read()
like it is done in sysfs for example.
Kim
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
2013-10-22 18:18 ` Kim De Mey
@ 2013-10-24 8:28 ` Kim De Mey
2013-10-24 9:00 ` Philippe Gerum
0 siblings, 1 reply; 12+ messages in thread
From: Kim De Mey @ 2013-10-24 8:28 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai
2013/10/22 Kim De Mey <kim.demey@gmail.com>
>
>
>
> 2013/10/22 Philippe Gerum <rpm@xenomai.org>
>
>> On 10/22/2013 06:45 PM, Kim De Mey wrote:
>>
>>>
>>>
>>>
>>> 2013/10/19 Ronny Meeus <ronny.meeus@gmail.com
>>> <mailto:ronny.meeus@gmail.com>**>
>>>
>>>
>>>
>>> IIUC, this would add the quite unexpected requirement of having
>>> to reopen a file for getting fresh data. read() should actually
>>> (re-)read the current object state each time it is invoked, and
>>> not resend some frozen state collected by the corresponding
>>> open() indefinitely.
>>>
>>> e.g. this has to work with code like:
>>>
>>> fd = open("/mnt/xenomai/1235/foo/__**tasks", O_RDONLY);
>>>
>>> for (;;) {
>>> ret = read(fd, buf, sizeof(buf));
>>> ... process NEW data ...
>>> }
>>>
>>> Philippe,
>>> how to handle the case where the data is bigger than de buffer
>>> passed by the user?
>>> Suppose the task data is 20k while the user read only wants 4k. I
>>> would expect that the second read returns the second 4k block and so
>>> on.
>>> By generating the complete output in 1 shot (for example at open),
>>> the data would be more consistent in my opinion too.
>>> Suppose the data of a queue is dumped and the queue contains a lot
>>> of messages. I would like to see a consistent view on the queue and
>>> not the first 4k followed by some random messages after it because
>>> the application is processing the queue in parallel.
>>>
>>> Philippe,
>>>
>>> As Ronny explains, the reason of "storing the state" at open is so that
>>> the data we read would be consistent. So yes, I think we need this.
>>>
>>>
>> I don't think so. Implementing a snapshot mechanism so that reading from
>> a channel does return a consistent set of data does not mean that we should
>> do this in open(). This only means that we should implement a snapshot
>> mechanism for reading.
>>
>
> I meant that we need to be able to "store the state", not that we
> necessary need to do it in the open(). My sentence was confusing, sorry. As
> I explained further in my previous post we could do it in the initial
> read() like it is done in sysfs for example.
>
> Philippe,
I noticed that you made some changes to the registry code. Does this mean
you have a plan in mind on how to tackle the "issue" in the discussion
above?
Kim
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS
2013-10-24 8:28 ` Kim De Mey
@ 2013-10-24 9:00 ` Philippe Gerum
0 siblings, 0 replies; 12+ messages in thread
From: Philippe Gerum @ 2013-10-24 9:00 UTC (permalink / raw)
To: Kim De Mey; +Cc: xenomai
On 10/24/2013 10:28 AM, Kim De Mey wrote:
>
>
>
> 2013/10/22 Kim De Mey <kim.demey@gmail.com <mailto:kim.demey@gmail.com>>
>
>
>
>
> 2013/10/22 Philippe Gerum <rpm@xenomai.org <mailto:rpm@xenomai.org>>
>
> On 10/22/2013 06:45 PM, Kim De Mey wrote:
>
>
>
>
> 2013/10/19 Ronny Meeus <ronny.meeus@gmail.com
> <mailto:ronny.meeus@gmail.com>
> <mailto:ronny.meeus@gmail.com <mailto:ronny.meeus@gmail.com>>__>
>
>
>
> IIUC, this would add the quite unexpected
> requirement of having
> to reopen a file for getting fresh data. read()
> should actually
> (re-)read the current object state each time it is
> invoked, and
> not resend some frozen state collected by the
> corresponding
> open() indefinitely.
>
> e.g. this has to work with code like:
>
> fd =
> open("/mnt/xenomai/1235/foo/____tasks", O_RDONLY);
>
> for (;;) {
> ret = read(fd, buf, sizeof(buf));
> ... process NEW data ...
> }
>
> Philippe,
> how to handle the case where the data is bigger than de
> buffer
> passed by the user?
> Suppose the task data is 20k while the user read only
> wants 4k. I
> would expect that the second read returns the second 4k
> block and so on.
> By generating the complete output in 1 shot (for
> example at open),
> the data would be more consistent in my opinion too.
> Suppose the data of a queue is dumped and the queue
> contains a lot
> of messages. I would like to see a consistent view on
> the queue and
> not the first 4k followed by some random messages after
> it because
> the application is processing the queue in parallel.
>
> Philippe,
>
> As Ronny explains, the reason of "storing the state" at open
> is so that
> the data we read would be consistent. So yes, I think we
> need this.
>
>
> I don't think so. Implementing a snapshot mechanism so that
> reading from a channel does return a consistent set of data does
> not mean that we should do this in open(). This only means that
> we should implement a snapshot mechanism for reading.
>
>
> I meant that we need to be able to "store the state", not that we
> necessary need to do it in the open(). My sentence was confusing,
> sorry. As I explained further in my previous post we could do it in
> the initial read() like it is done in sysfs for example.
>
> Philippe,
>
> I noticed that you made some changes to the registry code. Does this
> mean you have a plan in mind on how to tackle the "issue" in the
> discussion above?
>
I'm adding flexibility to the registry code, since there won't be any
one-fits-it-all solution, the client code should be able to define its
own policy with respect to handling fuse read requests, without imposing
a standard on the others. This is basically why the snapshot mechanism
should not be implemented in the generic registry code handling file
open requests, because other clients may want to act as unbuffered data
sources, returning fresh values each time they are read, assuming those
values always fit in a fuse read request.
By exposing the open and release requests to the client code, we may
allow clients to deal with snapshot the way you wanted initially,
without imposing it to all others, making the approach acceptable.
I'm considering adding a simple mechanism for accumulating snapshot
data, that would be seekable from the client read() handler, maybe just
based on GNU obstacks, with a revision tag to detect changes in the data
set being snapshot, so that the client code does not have to hold locks
throughout the entire iteration over the object contents. This would be
reminiscent of what we already do with Cobalt's vfiles
(kernel/cobalt/vfile).
--
Philippe.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-10-24 9:00 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-15 8:50 [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 1 of 3] Initial implementation registry pSOS task Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 2 of 3] Initial implementation registry pSOS semaphore Kim De Mey
2013-10-22 16:54 ` Kim De Mey
2013-10-15 8:50 ` [Xenomai] [PATCH 3 of 3] Initial implementation registry pSOS queue Kim De Mey
2013-10-19 17:37 ` [Xenomai] [PATCH 0 of 3] Xenomai-forge: Initial implementation of registry for pSOS Philippe Gerum
2013-10-19 18:56 ` Ronny Meeus
2013-10-22 16:45 ` Kim De Mey
2013-10-22 17:06 ` Philippe Gerum
2013-10-22 18:18 ` Kim De Mey
2013-10-24 8:28 ` Kim De Mey
2013-10-24 9:00 ` Philippe Gerum
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.