* [Xenomai-core] [RFC][patch] per-process data.
@ 2006-05-07 18:00 Gilles Chanteperdrix
2006-05-07 21:15 ` Jan Kiszka
2006-05-08 12:51 ` Gilles Chanteperdrix
0 siblings, 2 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-07 18:00 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 1079 bytes --]
Hi,
for review, here are patches that provide Xenomai skins with a
per-process per-skin data structures. It will allow skins to do
per-process cleanup for example, or the posix skin to maintain a
per-process signal mask.
In order to use it, the skins must pass an eventcb function to the
xnshadow_register_interface service. This eventcb function gets called
when:
- a process bind the interfaces, the eventcb has to allocate the
per-process structure and must return a pointer to an xnppd_holder_t
member of this structure;
- the process exits, the eventcb function is then passed the
xnppd_holder_t pointer and may free the container structure.
The patch also add a service called xnppd_get, which must be passed the
skin magic, and returns the xnppd_holder_t pointer attached to the
current process.
This support relies on a new adeos event called "PEXIT" for
process-exit, that get triggered in the mmput function when a process
mm_struct get deallocated.
These patches are not ready for inclusion, they are not tested
yet.
--
Gilles Chanteperdrix.
[-- Attachment #2: adeos-process-exit-event.diff --]
[-- Type: text/plain, Size: 1782 bytes --]
--- ./include/asm-i386/ipipe.h~ 2006-05-07 16:00:37.000000000 +0200
+++ ./include/asm-i386/ipipe.h 2006-05-07 19:00:34.000000000 +0200
@@ -135,7 +135,8 @@ do { \
#define IPIPE_EVENT_SIGWAKE (IPIPE_FIRST_EVENT + 2)
#define IPIPE_EVENT_SETSCHED (IPIPE_FIRST_EVENT + 3)
#define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 4)
-#define IPIPE_LAST_EVENT IPIPE_EVENT_EXIT
+#define IPIPE_EVENT_PEXIT (IPIPE_FIRST_EVENT + 5)
+#define IPIPE_LAST_EVENT IPIPE_EVENT_PEXIT
#define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1)
struct ipipe_domain;
--- ./include/linux/ipipe.h~ 2006-05-07 16:00:36.000000000 +0200
+++ ./include/linux/ipipe.h 2006-05-07 19:01:01.000000000 +0200
@@ -439,6 +439,12 @@ static inline void ipipe_exit_notify(str
__ipipe_dispatch_event(IPIPE_EVENT_EXIT,p);
}
+static inline void ipipe_pexit_notify(struct mm_struct *m)
+{
+ if (__ipipe_event_pipelined_p(IPIPE_EVENT_PEXIT))
+ __ipipe_dispatch_event(IPIPE_EVENT_PEXIT,m);
+}
+
static inline int ipipe_trap_notify(int ex, struct pt_regs *regs)
{
return __ipipe_event_pipelined_p(ex) ? __ipipe_dispatch_event(ex,regs) : 0;
@@ -633,6 +639,7 @@ void fastcall *ipipe_get_ptd(int key);
#define ipipe_sigwake_notify(p) do { } while(0)
#define ipipe_setsched_notify(p) do { } while(0)
#define ipipe_exit_notify(p) do { } while(0)
+#define ipipe_mmput_notify(m) do { } while(0)
#define ipipe_init_proc() do { } while(0)
#define ipipe_trap_notify(t,r) 0
--- ./kernel/fork.c~ 2006-05-07 16:00:36.000000000 +0200
+++ ./kernel/fork.c 2006-05-07 19:00:02.000000000 +0200
@@ -368,6 +368,7 @@ void fastcall __mmdrop(struct mm_struct
void mmput(struct mm_struct *mm)
{
if (atomic_dec_and_test(&mm->mm_users)) {
+ ipipe_pexit_notify(mm);
exit_aio(mm);
exit_mmap(mm);
if (!list_empty(&mm->mmlist)) {
[-- Attachment #3: xenomai-ppd.diff --]
[-- Type: text/plain, Size: 6839 bytes --]
Index: include/asm-generic/hal.h
===================================================================
--- include/asm-generic/hal.h (revision 1029)
+++ include/asm-generic/hal.h (working copy)
@@ -236,6 +236,14 @@
return RTHAL_EVENT_PROPAGATE; \
}
+#define RTHAL_DECLARE_PEXIT_EVENT(hdlr) \
+static int hdlr (unsigned event, struct ipipe_domain *ipd, void *data) \
+{ \
+ struct mm_struct *mm = (struct mm_struct *)data; \
+ do_##hdlr(mm); \
+ return RTHAL_EVENT_PROPAGATE; \
+}
+
#ifndef IPIPE_EVENT_SELF
/* Some early I-pipe versions don't have this. */
#define IPIPE_EVENT_SELF 0
@@ -255,6 +263,8 @@
#define IPIPE_WIRED_MASK 0
#endif /* !IPIPE_WIRED_MASK */
+#define rthal_catch_pexit(hdlr) \
+ ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_PEXIT,hdlr)
#define rthal_catch_taskexit(hdlr) \
ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_EXIT,hdlr)
#define rthal_catch_sigwake(hdlr) \
--- /dev/null 2006-05-07 17:27:37.880481000 +0200
+++ include/nucleus/ppd.h 2006-05-07 18:42:46.000000000 +0200
@@ -0,0 +1,22 @@
+#ifndef PPD_H
+#define PPD_H
+
+#include <nucleus/queue.h>
+
+struct mm_struct;
+
+typedef struct xnppd_key {
+ unsigned long skin_magic;
+ struct mm_struct *mm;
+} xnppd_key_t;
+
+typedef struct xnppd_holder {
+ xnppd_key_t key;
+ xnholder_t link;
+#define link2ppd(laddr) \
+ (xnppd_holder_t *)((char *)(laddr) - offsetof(xnppd_holder_t, link))
+} xnppd_holder_t;
+
+xnppd_holder_t *xnppd_get(unsigned skin_magic);
+
+#endif /* PPD_H */
Index: include/nucleus/shadow.h
===================================================================
--- include/nucleus/shadow.h (revision 1029)
+++ include/nucleus/shadow.h (working copy)
@@ -48,7 +48,7 @@
unsigned magic;
int nrcalls;
atomic_counter_t refcnt;
- int (*eventcb)(int);
+ void *(*eventcb)(int, void *);
xnsysent_t *systab;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
@@ -89,7 +89,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int event));
+ void *(*eventcb)(int event, void *data));
int xnshadow_unregister_interface(int muxid);
Index: ksrc/nucleus/shadow.c
===================================================================
--- ksrc/nucleus/shadow.c (revision 1029)
+++ ksrc/nucleus/shadow.c (working copy)
@@ -48,6 +48,8 @@
#include <nucleus/shadow.h>
#include <nucleus/core.h>
#include <nucleus/ltt.h>
+#include <nucleus/jhash.h>
+#include <nucleus/ppd.h>
#include <asm/xenomai/features.h>
int nkthrptd;
@@ -95,10 +97,64 @@
static struct task_struct *switch_lock_owner[XNARCH_NR_CPUS];
+static xnqueue_t *xnppd_hash;
+#define XNPPD_HASH_SIZE 13
+
void xnpod_declare_iface_proc(struct xnskentry *iface);
void xnpod_discard_iface_proc(struct xnskentry *iface);
+static inline unsigned
+xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
+{
+ unsigned bucket = jhash2((uint32_t *)key, sizeof(*key)/sizeof(uint32_t), 0);
+ xnholder_t *holder;
+
+ *pq = &xnppd_hash[bucket % XNPPD_HASH_SIZE];
+ for (holder = getheadq(*pq); holder; holder = nextq(*pq, holder))
+ {
+ xnppd_holder_t *ppd = link2ppd(holder);
+
+ if (ppd->key.skin_magic == key->skin_magic && ppd->key.mm == key->mm)
+ {
+ *pholder = ppd;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void xnppd_insert(xnppd_holder_t *holder)
+{
+ xnppd_holder_t *ignored;
+ xnqueue_t *q;
+ unsigned found = xnppd_lookup_inner(&q, &ignored, &holder->key);
+ BUG_ON(found);
+ appendq(q, &holder->link);
+}
+
+static inline struct xnppd_holder *
+xnppd_lookup(unsigned skin_magic, struct mm_struct *mm, unsigned remove)
+{
+ xnppd_holder_t *holder;
+ xnppd_key_t key;
+ unsigned found;
+ xnqueue_t *q;
+
+ key.skin_magic = skin_magic;
+ key.mm = mm;
+ found = xnppd_lookup_inner(&q, &holder, &key);
+
+ if (!found)
+ return NULL;
+
+ if (remove)
+ removeq(q, &holder->link);
+
+ return holder;
+}
+
static inline void request_syscall_restart (xnthread_t *thread, struct pt_regs *regs)
{
@@ -1024,13 +1080,20 @@
if (muxtable[muxid].eventcb)
{
- int err = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH);
+ xnppd_holder_t *ppd;
- if (err)
+ ppd = (xnppd_holder_t *) muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH,
+ curr);
+
+ if (IS_ERR(ppd))
{
xnarch_atomic_dec(&muxtable[muxid].refcnt);
- return err;
+ return PTR_ERR(ppd);
}
+
+ ppd->key.skin_magic = muxtable[muxid].magic;
+ ppd->key.mm = curr->mm;
+ xnppd_insert(ppd);
}
if (!nkpod || testbits(nkpod->status,XNPIDLE))
@@ -1733,6 +1796,29 @@
RTHAL_DECLARE_SETSCHED_EVENT(setsched_event);
+static inline void do_pexit_event (struct mm_struct *mm)
+{
+ unsigned muxid;
+ spl_t s;
+
+ for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++)
+ {
+ xnlock_get_irqsave(&nklock, s);
+ if (muxtable[muxid].systab && muxtable[muxid].eventcb)
+ {
+ struct xnppd_holder *ppd;
+
+ ppd = xnppd_lookup(muxtable[muxid].magic, mm, 1);
+
+ if (ppd)
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
+ }
+ xnlock_put_irqrestore(&nklock, s);
+ }
+}
+
+RTHAL_DECLARE_PEXIT_EVENT(pexit_event);
+
/*
* xnshadow_register_interface() -- Register a new skin/interface.
* NOTE: an interface can be registered without its pod being
@@ -1745,7 +1831,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int))
+ void *(*eventcb)(int, void *))
{
int muxid;
spl_t s;
@@ -1819,6 +1905,15 @@
return err;
}
+/* Call with nklock locked irqs off. */
+xnppd_holder_t *xnppd_get(unsigned skin_magic)
+{
+ if (xnpod_root_p() || xnpod_shadow_p())
+ return xnppd_lookup(skin_magic, current->mm, 0);
+
+ return NULL;
+}
+
void xnshadow_grab_events (void)
{
@@ -1826,6 +1921,7 @@
rthal_catch_sigwake(&sigwake_event);
rthal_catch_schedule(&schedule_event);
rthal_catch_setsched(&setsched_event);
+ rthal_catch_pexit(&pexit_event);
}
void xnshadow_release_events (void)
@@ -1835,11 +1931,13 @@
rthal_catch_sigwake(NULL);
rthal_catch_schedule(NULL);
rthal_catch_setsched(NULL);
+ rthal_catch_pexit(NULL);
}
int xnshadow_mount (void)
{
+ unsigned size;
int cpu;
#ifdef CONFIG_XENO_OPT_ISHIELD
@@ -1878,6 +1976,8 @@
rthal_catch_losyscall(&losyscall_event);
rthal_catch_hisyscall(&hisyscall_event);
+ size = sizeof(xnqueue_t) * XNPPD_HASH_SIZE;
+ xnppd_hash = (xnqueue_t *) xnarch_sysalloc(size);
return 0;
}
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-07 18:00 [Xenomai-core] [RFC][patch] per-process data Gilles Chanteperdrix
@ 2006-05-07 21:15 ` Jan Kiszka
2006-05-07 23:04 ` Gilles Chanteperdrix
2006-05-08 12:51 ` Gilles Chanteperdrix
1 sibling, 1 reply; 15+ messages in thread
From: Jan Kiszka @ 2006-05-07 21:15 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
[-- Attachment #1: Type: text/plain, Size: 1461 bytes --]
Gilles Chanteperdrix wrote:
> Hi,
>
> for review, here are patches that provide Xenomai skins with a
> per-process per-skin data structures. It will allow skins to do
> per-process cleanup for example, or the posix skin to maintain a
> per-process signal mask.
That sounds promising!
>
> In order to use it, the skins must pass an eventcb function to the
> xnshadow_register_interface service. This eventcb function gets called
> when:
> - a process bind the interfaces, the eventcb has to allocate the
> per-process structure and must return a pointer to an xnppd_holder_t
> member of this structure;
> - the process exits, the eventcb function is then passed the
> xnppd_holder_t pointer and may free the container structure.
>
> The patch also add a service called xnppd_get, which must be passed the
> skin magic, and returns the xnppd_holder_t pointer attached to the
> current process.
>
> This support relies on a new adeos event called "PEXIT" for
> process-exit, that get triggered in the mmput function when a process
> mm_struct get deallocated.
Likely I did not yet get the full picture: What prevents using another
adeos per-task key for this? And why is it required to establish a new
termination hook? Are there scenarios where the existing
task-termination hook is not suited for the planned cleanup work?
>
> These patches are not ready for inclusion, they are not tested
> yet.
>
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-07 21:15 ` Jan Kiszka
@ 2006-05-07 23:04 ` Gilles Chanteperdrix
2006-05-08 10:18 ` Dmitry Adamushko
2006-05-08 13:05 ` Jan Kiszka
0 siblings, 2 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-07 23:04 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai
Jan Kiszka wrote:
> Likely I did not yet get the full picture: What prevents using another
> adeos per-task key for this?
We would need a per-task key for every skin that needs a per-process
data, but more importantly, we would need to track the clone syscalls
(that would be another adeos event) in order to propagate the per-task
data to each thread of the process. Or maybe ptds are inherited upon
clone ?
And why is it required to establish a new
> termination hook? Are there scenarios where the existing
> task-termination hook is not suited for the planned cleanup work?
Because the existing hook is called once for every thread exit, whereas
the pexit event get triggered when the last thread of a process exits,
this is the only moment we are sure we can destroy per-process data.
Using the existing hook, we would need to decrement a reference counter
in the hook, but then we would (again) need to track the clone syscalls
in order to increment the reference counter.
Both implementations require to add an adeos event, the one I chose, if
it works, avoid reference counting.
--
Gilles Chanteperdrix.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-07 23:04 ` Gilles Chanteperdrix
@ 2006-05-08 10:18 ` Dmitry Adamushko
2006-05-08 12:47 ` Gilles Chanteperdrix
2006-05-08 13:05 ` Jan Kiszka
1 sibling, 1 reply; 15+ messages in thread
From: Dmitry Adamushko @ 2006-05-08 10:18 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: Jan Kiszka, xenomai
On 08/05/06, Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org> wrote:
> Jan Kiszka wrote:
> > Likely I did not yet get the full picture: What prevents using another
> > adeos per-task key for this?
>
> We would need a per-task key for every skin that needs a per-process
> data, but more importantly, we would need to track the clone syscalls
> (that would be another adeos event) in order to propagate the per-task
> data to each thread of the process. Or maybe ptds are inherited upon
> clone ?
All of them are cleared in kernel/fork.c :: copy_process(). At least,
the one pointed by "nkgkptd" (keeps shadow's xnthread_t *) must be
cleared. Another logic could be applied for the rest, I guess.
p.s. I haven't read you patch yet so all said above is out of current context :)
--
Best regards,
Dmitry Adamushko
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-08 10:18 ` Dmitry Adamushko
@ 2006-05-08 12:47 ` Gilles Chanteperdrix
0 siblings, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-08 12:47 UTC (permalink / raw)
To: Dmitry Adamushko; +Cc: Jan Kiszka, xenomai
Dmitry Adamushko wrote:
> On 08/05/06, Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org> wrote:
> > Jan Kiszka wrote:
> > > Likely I did not yet get the full picture: What prevents using another
> > > adeos per-task key for this?
> >
> > We would need a per-task key for every skin that needs a per-process
> > data, but more importantly, we would need to track the clone syscalls
> > (that would be another adeos event) in order to propagate the per-task
> > data to each thread of the process. Or maybe ptds are inherited upon
> > clone ?
>
> All of them are cleared in kernel/fork.c :: copy_process(). At least,
> the one pointed by "nkgkptd" (keeps shadow's xnthread_t *) must be
> cleared. Another logic could be applied for the rest, I guess.
It make sense, if they were not cleared, they would not be per-thread
data.
--
Gilles Chanteperdrix.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-07 18:00 [Xenomai-core] [RFC][patch] per-process data Gilles Chanteperdrix
2006-05-07 21:15 ` Jan Kiszka
@ 2006-05-08 12:51 ` Gilles Chanteperdrix
2006-05-08 13:14 ` Gilles Chanteperdrix
2006-05-08 13:51 ` Philippe Gerum
1 sibling, 2 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-08 12:51 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 342 bytes --]
Gilles Chanteperdrix wrote:
> These patches are not ready for inclusion, they are not tested
> yet.
The attached versions are tested. I still wonder if handling this in
shadow.c is the right solution, or if there should be an xnppd_set call
that could be called from within the skins event callbacks.
--
Gilles Chanteperdrix.
[-- Attachment #2: adeos-process-exit-event.diff --]
[-- Type: text/plain, Size: 1782 bytes --]
--- ./include/asm-i386/ipipe.h~ 2006-05-07 16:00:37.000000000 +0200
+++ ./include/asm-i386/ipipe.h 2006-05-07 19:00:34.000000000 +0200
@@ -135,7 +135,8 @@ do { \
#define IPIPE_EVENT_SIGWAKE (IPIPE_FIRST_EVENT + 2)
#define IPIPE_EVENT_SETSCHED (IPIPE_FIRST_EVENT + 3)
#define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 4)
-#define IPIPE_LAST_EVENT IPIPE_EVENT_EXIT
+#define IPIPE_EVENT_PEXIT (IPIPE_FIRST_EVENT + 5)
+#define IPIPE_LAST_EVENT IPIPE_EVENT_PEXIT
#define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1)
struct ipipe_domain;
--- ./include/linux/ipipe.h~ 2006-05-07 16:00:36.000000000 +0200
+++ ./include/linux/ipipe.h 2006-05-07 19:01:01.000000000 +0200
@@ -439,6 +439,12 @@ static inline void ipipe_exit_notify(str
__ipipe_dispatch_event(IPIPE_EVENT_EXIT,p);
}
+static inline void ipipe_pexit_notify(struct mm_struct *m)
+{
+ if (__ipipe_event_pipelined_p(IPIPE_EVENT_PEXIT))
+ __ipipe_dispatch_event(IPIPE_EVENT_PEXIT,m);
+}
+
static inline int ipipe_trap_notify(int ex, struct pt_regs *regs)
{
return __ipipe_event_pipelined_p(ex) ? __ipipe_dispatch_event(ex,regs) : 0;
@@ -633,6 +639,7 @@ void fastcall *ipipe_get_ptd(int key);
#define ipipe_sigwake_notify(p) do { } while(0)
#define ipipe_setsched_notify(p) do { } while(0)
#define ipipe_exit_notify(p) do { } while(0)
+#define ipipe_mmput_notify(m) do { } while(0)
#define ipipe_init_proc() do { } while(0)
#define ipipe_trap_notify(t,r) 0
--- ./kernel/fork.c~ 2006-05-07 16:00:36.000000000 +0200
+++ ./kernel/fork.c 2006-05-07 19:00:02.000000000 +0200
@@ -368,6 +368,7 @@ void fastcall __mmdrop(struct mm_struct
void mmput(struct mm_struct *mm)
{
if (atomic_dec_and_test(&mm->mm_users)) {
+ ipipe_pexit_notify(mm);
exit_aio(mm);
exit_mmap(mm);
if (!list_empty(&mm->mmlist)) {
[-- Attachment #3: xenomai-ppd.2.diff --]
[-- Type: text/plain, Size: 8083 bytes --]
Index: include/asm-generic/hal.h
===================================================================
--- include/asm-generic/hal.h (revision 1029)
+++ include/asm-generic/hal.h (working copy)
@@ -236,6 +236,14 @@
return RTHAL_EVENT_PROPAGATE; \
}
+#define RTHAL_DECLARE_PEXIT_EVENT(hdlr) \
+static int hdlr (unsigned event, struct ipipe_domain *ipd, void *data) \
+{ \
+ struct mm_struct *mm = (struct mm_struct *)data; \
+ do_##hdlr(mm); \
+ return RTHAL_EVENT_PROPAGATE; \
+}
+
#ifndef IPIPE_EVENT_SELF
/* Some early I-pipe versions don't have this. */
#define IPIPE_EVENT_SELF 0
@@ -255,6 +263,8 @@
#define IPIPE_WIRED_MASK 0
#endif /* !IPIPE_WIRED_MASK */
+#define rthal_catch_pexit(hdlr) \
+ ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_PEXIT,hdlr)
#define rthal_catch_taskexit(hdlr) \
ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_EXIT,hdlr)
#define rthal_catch_sigwake(hdlr) \
--- /dev/null 2006-05-08 00:21:12.004363750 +0200
+++ include/nucleus/ppd.h 2006-05-07 18:42:46.000000000 +0200
@@ -0,0 +1,22 @@
+#ifndef PPD_H
+#define PPD_H
+
+#include <nucleus/queue.h>
+
+struct mm_struct;
+
+typedef struct xnppd_key {
+ unsigned long skin_magic;
+ struct mm_struct *mm;
+} xnppd_key_t;
+
+typedef struct xnppd_holder {
+ xnppd_key_t key;
+ xnholder_t link;
+#define link2ppd(laddr) \
+ (xnppd_holder_t *)((char *)(laddr) - offsetof(xnppd_holder_t, link))
+} xnppd_holder_t;
+
+xnppd_holder_t *xnppd_get(unsigned skin_magic);
+
+#endif /* PPD_H */
Index: include/nucleus/shadow.h
===================================================================
--- include/nucleus/shadow.h (revision 1029)
+++ include/nucleus/shadow.h (working copy)
@@ -48,7 +48,7 @@
unsigned magic;
int nrcalls;
atomic_counter_t refcnt;
- int (*eventcb)(int);
+ void *(*eventcb)(int, void *);
xnsysent_t *systab;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
@@ -89,7 +89,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int event));
+ void *(*eventcb)(int event, void *data));
int xnshadow_unregister_interface(int muxid);
Index: ksrc/nucleus/shadow.c
===================================================================
--- ksrc/nucleus/shadow.c (revision 1029)
+++ ksrc/nucleus/shadow.c (working copy)
@@ -48,6 +48,8 @@
#include <nucleus/shadow.h>
#include <nucleus/core.h>
#include <nucleus/ltt.h>
+#include <nucleus/jhash.h>
+#include <nucleus/ppd.h>
#include <asm/xenomai/features.h>
int nkthrptd;
@@ -95,10 +97,65 @@
static struct task_struct *switch_lock_owner[XNARCH_NR_CPUS];
+static xnqueue_t *xnppd_hash;
+#define XNPPD_HASH_SIZE 13
+
void xnpod_declare_iface_proc(struct xnskentry *iface);
void xnpod_discard_iface_proc(struct xnskentry *iface);
+static inline unsigned
+xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
+{
+ unsigned bucket = jhash2((uint32_t *)key, sizeof(*key)/sizeof(uint32_t), 0);
+ xnholder_t *holder;
+
+ *pq = &xnppd_hash[bucket % XNPPD_HASH_SIZE];
+ for (holder = getheadq(*pq); holder; holder = nextq(*pq, holder))
+ {
+ xnppd_holder_t *ppd = link2ppd(holder);
+
+ if (ppd->key.skin_magic == key->skin_magic && ppd->key.mm == key->mm)
+ {
+ *pholder = ppd;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void xnppd_insert(xnppd_holder_t *holder)
+{
+ xnppd_holder_t *ignored;
+ xnqueue_t *q;
+ unsigned found = xnppd_lookup_inner(&q, &ignored, &holder->key);
+ BUG_ON(found);
+ inith(&holder->link);
+ appendq(q, &holder->link);
+}
+
+static inline struct xnppd_holder *
+xnppd_lookup(unsigned skin_magic, struct mm_struct *mm, unsigned remove)
+{
+ xnppd_holder_t *holder;
+ xnppd_key_t key;
+ unsigned found;
+ xnqueue_t *q;
+
+ key.skin_magic = skin_magic;
+ key.mm = mm;
+ found = xnppd_lookup_inner(&q, &holder, &key);
+
+ if (!found)
+ return NULL;
+
+ if (remove)
+ removeq(q, &holder->link);
+
+ return holder;
+}
+
static inline void request_syscall_restart (xnthread_t *thread, struct pt_regs *regs)
{
@@ -1024,19 +1081,37 @@
if (muxtable[muxid].eventcb)
{
- int err = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH);
+ xnppd_holder_t *ppd;
- if (err)
- {
- xnarch_atomic_dec(&muxtable[muxid].refcnt);
- return err;
- }
- }
+ ppd = xnppd_lookup(muxtable[muxid].magic, curr->mm, 0);
+ /* protect from the same process binding several time. */
+ if (!ppd)
+ {
+ ppd = (xnppd_holder_t *)
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH, curr);
+
+ if (IS_ERR(ppd))
+ {
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
+ return PTR_ERR(ppd);
+ }
+
+ ppd->key.skin_magic = muxtable[muxid].magic;
+ ppd->key.mm = curr->mm;
+ xnppd_insert(ppd);
+ }
+ }
+
if (!nkpod || testbits(nkpod->status,XNPIDLE))
/* Ok mate, but you really ought to create some pod in a way
or another if you want me to be of some help here... */
+ {
+ if (muxtable[muxid].eventcb)
+ xnppd_lookup(muxtable[muxid].magic, curr->mm, 1);
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
return -ENOSYS;
+ }
return ++muxid;
}
@@ -1733,6 +1808,29 @@
RTHAL_DECLARE_SETSCHED_EVENT(setsched_event);
+static inline void do_pexit_event (struct mm_struct *mm)
+{
+ unsigned muxid;
+ spl_t s;
+
+ for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++)
+ {
+ xnlock_get_irqsave(&nklock, s);
+ if (muxtable[muxid].systab && muxtable[muxid].eventcb)
+ {
+ struct xnppd_holder *ppd;
+
+ ppd = xnppd_lookup(muxtable[muxid].magic, mm, 1);
+
+ if (ppd)
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
+ }
+ xnlock_put_irqrestore(&nklock, s);
+ }
+}
+
+RTHAL_DECLARE_PEXIT_EVENT(pexit_event);
+
/*
* xnshadow_register_interface() -- Register a new skin/interface.
* NOTE: an interface can be registered without its pod being
@@ -1745,7 +1843,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int))
+ void *(*eventcb)(int, void *))
{
int muxid;
spl_t s;
@@ -1819,6 +1917,15 @@
return err;
}
+/* Call with nklock locked irqs off. */
+xnppd_holder_t *xnppd_get(unsigned skin_magic)
+{
+ if (xnpod_userspace_p())
+ return xnppd_lookup(skin_magic, current->mm, 0);
+
+ return NULL;
+}
+
void xnshadow_grab_events (void)
{
@@ -1826,6 +1933,7 @@
rthal_catch_sigwake(&sigwake_event);
rthal_catch_schedule(&schedule_event);
rthal_catch_setsched(&setsched_event);
+ rthal_catch_pexit(&pexit_event);
}
void xnshadow_release_events (void)
@@ -1835,11 +1943,13 @@
rthal_catch_sigwake(NULL);
rthal_catch_schedule(NULL);
rthal_catch_setsched(NULL);
+ rthal_catch_pexit(NULL);
}
int xnshadow_mount (void)
{
+ unsigned i, size;
int cpu;
#ifdef CONFIG_XENO_OPT_ISHIELD
@@ -1878,6 +1988,17 @@
rthal_catch_losyscall(&losyscall_event);
rthal_catch_hisyscall(&hisyscall_event);
+ size = sizeof(xnqueue_t) * XNPPD_HASH_SIZE;
+ xnppd_hash = (xnqueue_t *) xnarch_sysalloc(size);
+ if (!xnppd_hash)
+ {
+ xnshadow_cleanup();
+ printk(KERN_WARNING "Xenomai: cannot allocate PPD hash table.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < XNPPD_HASH_SIZE; i++)
+ initq(&xnppd_hash[i]);
return 0;
}
@@ -1886,6 +2007,9 @@
{
int cpu;
+ if (xnppd_hash)
+ xnarch_sysfree(xnppd_hash, sizeof(xnqueue_t) * XNPPD_HASH_SIZE);
+
rthal_catch_losyscall(NULL);
rthal_catch_hisyscall(NULL);
@@ -1919,3 +2043,4 @@
EXPORT_SYMBOL(xnshadow_suspend);
EXPORT_SYMBOL(nkthrptd);
EXPORT_SYMBOL(nkerrptd);
+EXPORT_SYMBOL(xnppd_get);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-07 23:04 ` Gilles Chanteperdrix
2006-05-08 10:18 ` Dmitry Adamushko
@ 2006-05-08 13:05 ` Jan Kiszka
1 sibling, 0 replies; 15+ messages in thread
From: Jan Kiszka @ 2006-05-08 13:05 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
[-- Attachment #1: Type: text/plain, Size: 1910 bytes --]
Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> > Likely I did not yet get the full picture: What prevents using another
> > adeos per-task key for this?
>
> We would need a per-task key for every skin that needs a per-process
> data,
Not necessarily, we could attach a chain of per-skin data objects to the
key pointer.
> but more importantly, we would need to track the clone syscalls
> (that would be another adeos event) in order to propagate the per-task
> data to each thread of the process. Or maybe ptds are inherited upon
> clone ?
Ok, I see the problem, no hook to save here.
>
> And why is it required to establish a new
> > termination hook? Are there scenarios where the existing
> > task-termination hook is not suited for the planned cleanup work?
>
> Because the existing hook is called once for every thread exit, whereas
> the pexit event get triggered when the last thread of a process exits,
> this is the only moment we are sure we can destroy per-process data.
>
> Using the existing hook, we would need to decrement a reference counter
> in the hook, but then we would (again) need to track the clone syscalls
> in order to increment the reference counter.
>
> Both implementations require to add an adeos event, the one I chose, if
> it works, avoid reference counting.
>
My motivation for suggesting the keys were avoiding the
hash-table-lookup for mm structs. If we maintain some pointer on a
per-thread basis, we would only have to walk over all skins, not all
colliding elements in a hash chain.
I cannot show any code to compare both approaches w/ complexity and
efficiency. Maybe your approach is actually leaner, but my feeling is
that something based on per-task pointers might have advantages as well.
Moreover, having a clone hook may open further doors: establishing hooks
to clone shadow threads...
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-08 12:51 ` Gilles Chanteperdrix
@ 2006-05-08 13:14 ` Gilles Chanteperdrix
2006-05-08 13:51 ` Philippe Gerum
1 sibling, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-08 13:14 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 286 bytes --]
Gilles Chanteperdrix wrote:
> Gilles Chanteperdrix wrote:
> > These patches are not ready for inclusion, they are not tested
> > yet.
>
> The attached versions are tested.
...but the kernel patch is buggy. Here are the corrected versions.
--
Gilles Chanteperdrix.
[-- Attachment #2: adeos-process-exit-event.2.diff --]
[-- Type: text/plain, Size: 1782 bytes --]
--- ./include/asm-i386/ipipe.h~ 2006-05-07 16:00:37.000000000 +0200
+++ ./include/asm-i386/ipipe.h 2006-05-07 19:00:34.000000000 +0200
@@ -135,7 +135,8 @@ do { \
#define IPIPE_EVENT_SIGWAKE (IPIPE_FIRST_EVENT + 2)
#define IPIPE_EVENT_SETSCHED (IPIPE_FIRST_EVENT + 3)
#define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 4)
-#define IPIPE_LAST_EVENT IPIPE_EVENT_EXIT
+#define IPIPE_EVENT_PEXIT (IPIPE_FIRST_EVENT + 5)
+#define IPIPE_LAST_EVENT IPIPE_EVENT_PEXIT
#define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1)
struct ipipe_domain;
--- ./include/linux/ipipe.h~ 2006-05-07 16:00:36.000000000 +0200
+++ ./include/linux/ipipe.h 2006-05-07 19:01:01.000000000 +0200
@@ -439,6 +439,12 @@ static inline void ipipe_exit_notify(str
__ipipe_dispatch_event(IPIPE_EVENT_EXIT,p);
}
+static inline void ipipe_pexit_notify(struct mm_struct *m)
+{
+ if (__ipipe_event_pipelined_p(IPIPE_EVENT_PEXIT))
+ __ipipe_dispatch_event(IPIPE_EVENT_PEXIT,m);
+}
+
static inline int ipipe_trap_notify(int ex, struct pt_regs *regs)
{
return __ipipe_event_pipelined_p(ex) ? __ipipe_dispatch_event(ex,regs) : 0;
@@ -633,6 +639,7 @@ void fastcall *ipipe_get_ptd(int key);
#define ipipe_sigwake_notify(p) do { } while(0)
#define ipipe_setsched_notify(p) do { } while(0)
#define ipipe_exit_notify(p) do { } while(0)
+#define ipipe_pexit_notify(m) do { } while(0)
#define ipipe_init_proc() do { } while(0)
#define ipipe_trap_notify(t,r) 0
--- ./kernel/fork.c~ 2006-05-07 16:00:36.000000000 +0200
+++ ./kernel/fork.c 2006-05-07 19:00:02.000000000 +0200
@@ -368,6 +368,7 @@ void fastcall __mmdrop(struct mm_struct
void mmput(struct mm_struct *mm)
{
if (atomic_dec_and_test(&mm->mm_users)) {
+ ipipe_pexit_notify(mm);
exit_aio(mm);
exit_mmap(mm);
if (!list_empty(&mm->mmlist)) {
[-- Attachment #3: xenomai-ppd.2.diff --]
[-- Type: text/plain, Size: 8083 bytes --]
Index: include/asm-generic/hal.h
===================================================================
--- include/asm-generic/hal.h (revision 1029)
+++ include/asm-generic/hal.h (working copy)
@@ -236,6 +236,14 @@
return RTHAL_EVENT_PROPAGATE; \
}
+#define RTHAL_DECLARE_PEXIT_EVENT(hdlr) \
+static int hdlr (unsigned event, struct ipipe_domain *ipd, void *data) \
+{ \
+ struct mm_struct *mm = (struct mm_struct *)data; \
+ do_##hdlr(mm); \
+ return RTHAL_EVENT_PROPAGATE; \
+}
+
#ifndef IPIPE_EVENT_SELF
/* Some early I-pipe versions don't have this. */
#define IPIPE_EVENT_SELF 0
@@ -255,6 +263,8 @@
#define IPIPE_WIRED_MASK 0
#endif /* !IPIPE_WIRED_MASK */
+#define rthal_catch_pexit(hdlr) \
+ ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_PEXIT,hdlr)
#define rthal_catch_taskexit(hdlr) \
ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_EXIT,hdlr)
#define rthal_catch_sigwake(hdlr) \
--- /dev/null 2006-05-08 00:21:12.004363750 +0200
+++ include/nucleus/ppd.h 2006-05-07 18:42:46.000000000 +0200
@@ -0,0 +1,22 @@
+#ifndef PPD_H
+#define PPD_H
+
+#include <nucleus/queue.h>
+
+struct mm_struct;
+
+typedef struct xnppd_key {
+ unsigned long skin_magic;
+ struct mm_struct *mm;
+} xnppd_key_t;
+
+typedef struct xnppd_holder {
+ xnppd_key_t key;
+ xnholder_t link;
+#define link2ppd(laddr) \
+ (xnppd_holder_t *)((char *)(laddr) - offsetof(xnppd_holder_t, link))
+} xnppd_holder_t;
+
+xnppd_holder_t *xnppd_get(unsigned skin_magic);
+
+#endif /* PPD_H */
Index: include/nucleus/shadow.h
===================================================================
--- include/nucleus/shadow.h (revision 1029)
+++ include/nucleus/shadow.h (working copy)
@@ -48,7 +48,7 @@
unsigned magic;
int nrcalls;
atomic_counter_t refcnt;
- int (*eventcb)(int);
+ void *(*eventcb)(int, void *);
xnsysent_t *systab;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
@@ -89,7 +89,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int event));
+ void *(*eventcb)(int event, void *data));
int xnshadow_unregister_interface(int muxid);
Index: ksrc/nucleus/shadow.c
===================================================================
--- ksrc/nucleus/shadow.c (revision 1029)
+++ ksrc/nucleus/shadow.c (working copy)
@@ -48,6 +48,8 @@
#include <nucleus/shadow.h>
#include <nucleus/core.h>
#include <nucleus/ltt.h>
+#include <nucleus/jhash.h>
+#include <nucleus/ppd.h>
#include <asm/xenomai/features.h>
int nkthrptd;
@@ -95,10 +97,65 @@
static struct task_struct *switch_lock_owner[XNARCH_NR_CPUS];
+static xnqueue_t *xnppd_hash;
+#define XNPPD_HASH_SIZE 13
+
void xnpod_declare_iface_proc(struct xnskentry *iface);
void xnpod_discard_iface_proc(struct xnskentry *iface);
+static inline unsigned
+xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
+{
+ unsigned bucket = jhash2((uint32_t *)key, sizeof(*key)/sizeof(uint32_t), 0);
+ xnholder_t *holder;
+
+ *pq = &xnppd_hash[bucket % XNPPD_HASH_SIZE];
+ for (holder = getheadq(*pq); holder; holder = nextq(*pq, holder))
+ {
+ xnppd_holder_t *ppd = link2ppd(holder);
+
+ if (ppd->key.skin_magic == key->skin_magic && ppd->key.mm == key->mm)
+ {
+ *pholder = ppd;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void xnppd_insert(xnppd_holder_t *holder)
+{
+ xnppd_holder_t *ignored;
+ xnqueue_t *q;
+ unsigned found = xnppd_lookup_inner(&q, &ignored, &holder->key);
+ BUG_ON(found);
+ inith(&holder->link);
+ appendq(q, &holder->link);
+}
+
+static inline struct xnppd_holder *
+xnppd_lookup(unsigned skin_magic, struct mm_struct *mm, unsigned remove)
+{
+ xnppd_holder_t *holder;
+ xnppd_key_t key;
+ unsigned found;
+ xnqueue_t *q;
+
+ key.skin_magic = skin_magic;
+ key.mm = mm;
+ found = xnppd_lookup_inner(&q, &holder, &key);
+
+ if (!found)
+ return NULL;
+
+ if (remove)
+ removeq(q, &holder->link);
+
+ return holder;
+}
+
static inline void request_syscall_restart (xnthread_t *thread, struct pt_regs *regs)
{
@@ -1024,19 +1081,37 @@
if (muxtable[muxid].eventcb)
{
- int err = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH);
+ xnppd_holder_t *ppd;
- if (err)
- {
- xnarch_atomic_dec(&muxtable[muxid].refcnt);
- return err;
- }
- }
+ ppd = xnppd_lookup(muxtable[muxid].magic, curr->mm, 0);
+ /* protect from the same process binding several time. */
+ if (!ppd)
+ {
+ ppd = (xnppd_holder_t *)
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH, curr);
+
+ if (IS_ERR(ppd))
+ {
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
+ return PTR_ERR(ppd);
+ }
+
+ ppd->key.skin_magic = muxtable[muxid].magic;
+ ppd->key.mm = curr->mm;
+ xnppd_insert(ppd);
+ }
+ }
+
if (!nkpod || testbits(nkpod->status,XNPIDLE))
/* Ok mate, but you really ought to create some pod in a way
or another if you want me to be of some help here... */
+ {
+ if (muxtable[muxid].eventcb)
+ xnppd_lookup(muxtable[muxid].magic, curr->mm, 1);
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
return -ENOSYS;
+ }
return ++muxid;
}
@@ -1733,6 +1808,29 @@
RTHAL_DECLARE_SETSCHED_EVENT(setsched_event);
+static inline void do_pexit_event (struct mm_struct *mm)
+{
+ unsigned muxid;
+ spl_t s;
+
+ for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++)
+ {
+ xnlock_get_irqsave(&nklock, s);
+ if (muxtable[muxid].systab && muxtable[muxid].eventcb)
+ {
+ struct xnppd_holder *ppd;
+
+ ppd = xnppd_lookup(muxtable[muxid].magic, mm, 1);
+
+ if (ppd)
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
+ }
+ xnlock_put_irqrestore(&nklock, s);
+ }
+}
+
+RTHAL_DECLARE_PEXIT_EVENT(pexit_event);
+
/*
* xnshadow_register_interface() -- Register a new skin/interface.
* NOTE: an interface can be registered without its pod being
@@ -1745,7 +1843,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int))
+ void *(*eventcb)(int, void *))
{
int muxid;
spl_t s;
@@ -1819,6 +1917,15 @@
return err;
}
+/* Call with nklock locked irqs off. */
+xnppd_holder_t *xnppd_get(unsigned skin_magic)
+{
+ if (xnpod_userspace_p())
+ return xnppd_lookup(skin_magic, current->mm, 0);
+
+ return NULL;
+}
+
void xnshadow_grab_events (void)
{
@@ -1826,6 +1933,7 @@
rthal_catch_sigwake(&sigwake_event);
rthal_catch_schedule(&schedule_event);
rthal_catch_setsched(&setsched_event);
+ rthal_catch_pexit(&pexit_event);
}
void xnshadow_release_events (void)
@@ -1835,11 +1943,13 @@
rthal_catch_sigwake(NULL);
rthal_catch_schedule(NULL);
rthal_catch_setsched(NULL);
+ rthal_catch_pexit(NULL);
}
int xnshadow_mount (void)
{
+ unsigned i, size;
int cpu;
#ifdef CONFIG_XENO_OPT_ISHIELD
@@ -1878,6 +1988,17 @@
rthal_catch_losyscall(&losyscall_event);
rthal_catch_hisyscall(&hisyscall_event);
+ size = sizeof(xnqueue_t) * XNPPD_HASH_SIZE;
+ xnppd_hash = (xnqueue_t *) xnarch_sysalloc(size);
+ if (!xnppd_hash)
+ {
+ xnshadow_cleanup();
+ printk(KERN_WARNING "Xenomai: cannot allocate PPD hash table.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < XNPPD_HASH_SIZE; i++)
+ initq(&xnppd_hash[i]);
return 0;
}
@@ -1886,6 +2007,9 @@
{
int cpu;
+ if (xnppd_hash)
+ xnarch_sysfree(xnppd_hash, sizeof(xnqueue_t) * XNPPD_HASH_SIZE);
+
rthal_catch_losyscall(NULL);
rthal_catch_hisyscall(NULL);
@@ -1919,3 +2043,4 @@
EXPORT_SYMBOL(xnshadow_suspend);
EXPORT_SYMBOL(nkthrptd);
EXPORT_SYMBOL(nkerrptd);
+EXPORT_SYMBOL(xnppd_get);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-08 12:51 ` Gilles Chanteperdrix
2006-05-08 13:14 ` Gilles Chanteperdrix
@ 2006-05-08 13:51 ` Philippe Gerum
2006-05-09 17:49 ` Gilles Chanteperdrix
1 sibling, 1 reply; 15+ messages in thread
From: Philippe Gerum @ 2006-05-08 13:51 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
Gilles Chanteperdrix wrote:
> Gilles Chanteperdrix wrote:
> > These patches are not ready for inclusion, they are not tested
> > yet.
>
> The attached versions are tested. I still wonder if handling this in
> shadow.c is the right solution, or if there should be an xnppd_set call
> that could be called from within the skins event callbacks.
>
That would likely be better, since some skin might not want any cleanup
code to be called, and in the current implementation, every skin needs
to provide some ppd info when returning from the event callback, even if
only the CLIENT_ATTACH event is to be monitored. On the other hand, we
could argue that registering an event callback requires to implement all
requests, including CLIENT_DETACH, possibly by returning a no-op value,
so that no ppd registration would be done from bind_to_interface().
Actually, I think the latter would be the better option.
>
>
> ------------------------------------------------------------------------
>
> --- ./include/asm-i386/ipipe.h~ 2006-05-07 16:00:37.000000000 +0200
> +++ ./include/asm-i386/ipipe.h 2006-05-07 19:00:34.000000000 +0200
> @@ -135,7 +135,8 @@ do { \
> #define IPIPE_EVENT_SIGWAKE (IPIPE_FIRST_EVENT + 2)
> #define IPIPE_EVENT_SETSCHED (IPIPE_FIRST_EVENT + 3)
> #define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 4)
> -#define IPIPE_LAST_EVENT IPIPE_EVENT_EXIT
> +#define IPIPE_EVENT_PEXIT (IPIPE_FIRST_EVENT + 5)
> +#define IPIPE_LAST_EVENT IPIPE_EVENT_PEXIT
> #define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1)
>
I've merged such support for process cleanup event notification in the
Adeos codebase, it will be available with the next patches to come. I've
named it IPIPE_EVENT_CLEANUP instead of PEXIT though, since that's what
it is about, and EXIT/PEXIT might be confusing.
+}
> +
> +static inline struct xnppd_holder *
> +xnppd_lookup(unsigned skin_magic, struct mm_struct *mm, unsigned remove)
> +{
Let's separate the lookup and removal ops here, making the latter return
the removed element. All-in-one stuff may save a few lines but is a pain
for readability.
>
> +static inline void do_pexit_event (struct mm_struct *mm)
> +{
> + unsigned muxid;
> + spl_t s;
> +
> + for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++)
> + {
> + xnlock_get_irqsave(&nklock, s);
> + if (muxtable[muxid].systab && muxtable[muxid].eventcb)
> + {
> + struct xnppd_holder *ppd;
> +
> + ppd = xnppd_lookup(muxtable[muxid].magic, mm, 1);
> +
> + if (ppd)
> + muxtable[muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
> + }
> + xnlock_put_irqrestore(&nklock, s);
> + }
> +}
> +
Maybe a better approach would be to simply hash holders referring to
busy muxtable entries on mm struct pointers? This way, we would only
have to scan a list handling one element per attached skin per
terminating process, which will be most of the time a matter of walking
through a 1/2 element queue.
i.e. indexing table entries on mm pointers from bind_to_interface() to
ask for the CLIENT_DETACH event to be fired upon process cleanup:
(key: curr->mm) ->
(holder: &muxtable[muxid1]) ->
(holder: &muxtable[muxid2]) ->
(holder: &muxtable[muxid3])
then, scanning the list hashed on the terminating process's mm struct,
in order to fire the appropriate event callbacks.
Btw, on 2.4 at least, the global Linux mm_lock is held before firing the
process cleanup notification at Adeos level, so one has to be careful
about what's actually done in those per-skin cleanup handlers.
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-08 13:51 ` Philippe Gerum
@ 2006-05-09 17:49 ` Gilles Chanteperdrix
2006-05-09 22:09 ` Philippe Gerum
0 siblings, 1 reply; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-09 17:49 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai
[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 2737 bytes --]
Philippe Gerum wrote:
> Gilles Chanteperdrix wrote:
> > Gilles Chanteperdrix wrote:
> > > These patches are not ready for inclusion, they are not tested
> > > yet.
> >
> > The attached versions are tested. I still wonder if handling this in
> > shadow.c is the right solution, or if there should be an xnppd_set call
> > that could be called from within the skins event callbacks.
> >
>
> That would likely be better, since some skin might not want any cleanup
> code to be called, and in the current implementation, every skin needs
> to provide some ppd info when returning from the event callback, even if
> only the CLIENT_ATTACH event is to be monitored. On the other hand, we
> could argue that registering an event callback requires to implement all
> requests, including CLIENT_DETACH, possibly by returning a no-op value,
> so that no ppd registration would be done from bind_to_interface().
> Actually, I think the latter would be the better option.
If we want CLIENT_DETACH to be called even if CLIENT_ATTACH returned the
no-op value, we have to allocate and store a ppd holder
nevertheless. So, the ppd became opaque void * pointers, returned by
CLIENT_ATTACH and passed back to CLIENT_DETACH. The holder allocation is
no longer the event callbacks responsibility.
> Maybe a better approach would be to simply hash holders referring to
> busy muxtable entries on mm struct pointers? This way, we would only
> have to scan a list handling one element per attached skin per
> terminating process, which will be most of the time a matter of walking
> through a 1/2 element queue.
>
> i.e. indexing table entries on mm pointers from bind_to_interface() to
> ask for the CLIENT_DETACH event to be fired upon process cleanup:
>
> (key: curr->mm) ->
> (holder: &muxtable[muxid1]) ->
> (holder: &muxtable[muxid2]) ->
> (holder: &muxtable[muxid3])
>
I have kept a hash table, but hashed only on the mm pointer, so that
data for different skins but the same mm end up contiguously in the same
bucket and can conveniently be destroyed all at once by an ad-hoc
function. If you find this unreadable/too baroque, I will switch to the
two-staged structure you suggest.
> then, scanning the list hashed on the terminating process's mm struct,
> in order to fire the appropriate event callbacks.
>
> Btw, on 2.4 at least, the global Linux mm_lock is held before firing the
> process cleanup notification at Adeos level, so one has to be careful
> about what's actually done in those per-skin cleanup handlers.
POSIX skin will call xnheap_destroy_mapped for shared memory heaps that
were not unmapped by the process, will this work ?
--
Gilles Chanteperdrix.
[-- Attachment #2: xenomai-ppd.3.diff --]
[-- Type: text/plain, Size: 10600 bytes --]
Index: include/asm-generic/hal.h
===================================================================
--- include/asm-generic/hal.h (revision 1058)
+++ include/asm-generic/hal.h (working copy)
@@ -236,6 +236,14 @@
return RTHAL_EVENT_PROPAGATE; \
}
+#define RTHAL_DECLARE_CLEANUP_EVENT(hdlr) \
+static int hdlr (unsigned event, struct ipipe_domain *ipd, void *data) \
+{ \
+ struct mm_struct *mm = (struct mm_struct *)data; \
+ do_##hdlr(mm); \
+ return RTHAL_EVENT_PROPAGATE; \
+}
+
#ifndef IPIPE_EVENT_SELF
/* Some early I-pipe versions don't have this. */
#define IPIPE_EVENT_SELF 0
@@ -255,6 +263,8 @@
#define IPIPE_WIRED_MASK 0
#endif /* !IPIPE_WIRED_MASK */
+#define rthal_catch_cleanup(hdlr) \
+ ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_CLEANUP,hdlr)
#define rthal_catch_taskexit(hdlr) \
ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_EXIT,hdlr)
#define rthal_catch_sigwake(hdlr) \
Index: include/nucleus/shadow.h
===================================================================
--- include/nucleus/shadow.h (revision 1058)
+++ include/nucleus/shadow.h (working copy)
@@ -48,7 +48,7 @@
unsigned magic;
int nrcalls;
atomic_counter_t refcnt;
- int (*eventcb)(int);
+ void *(*eventcb)(int, void *);
xnsysent_t *systab;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
@@ -89,7 +89,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int event));
+ void *(*eventcb)(int event, void *data));
int xnshadow_unregister_interface(int muxid);
@@ -109,6 +109,8 @@
int sig,
int specific);
+void *xnshadow_get_ppd(unsigned skin_muxid);
+
extern struct xnskentry muxtable[];
#ifdef __cplusplus
Index: ksrc/nucleus/shadow.c
===================================================================
--- ksrc/nucleus/shadow.c (revision 1058)
+++ ksrc/nucleus/shadow.c (working copy)
@@ -48,8 +48,22 @@
#include <nucleus/shadow.h>
#include <nucleus/core.h>
#include <nucleus/ltt.h>
+#include <nucleus/jhash.h>
#include <asm/xenomai/features.h>
+typedef struct xnppd_key {
+ unsigned long skin_muxid;
+ struct mm_struct *mm;
+} xnppd_key_t;
+
+typedef struct xnppd_holder {
+ xnppd_key_t key;
+ void *data;
+ xnholder_t link;
+#define link2ppd(laddr) \
+ (xnppd_holder_t *)((char *)(laddr) - offsetof(xnppd_holder_t, link))
+} xnppd_holder_t;
+
int nkthrptd;
int nkerrptd;
@@ -95,10 +109,124 @@
static struct task_struct *switch_lock_owner[XNARCH_NR_CPUS];
+static xnqueue_t *xnppd_hash;
+#define XNPPD_HASH_SIZE 13
+
void xnpod_declare_iface_proc(struct xnskentry *iface);
void xnpod_discard_iface_proc(struct xnskentry *iface);
+/* ppd holder with the same mm collide and are stored contiguously in the same
+ bucket, so that they can all be destroyed with only one hash lookup by
+ xnppd_remove_mm. */
+static unsigned
+xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
+{
+ unsigned bucket = jhash2((uint32_t *)&key->mm,
+ sizeof(key->mm)/sizeof(uint32_t), 0);
+ xnppd_holder_t *ppd;
+ xnholder_t *holder;
+
+ *pq = &xnppd_hash[bucket % XNPPD_HASH_SIZE];
+ holder = getheadq(*pq);
+
+ if (!holder)
+ {
+ *pholder = NULL;
+ return 0;
+ }
+
+ do
+ {
+ ppd = link2ppd(holder);
+ holder = nextq(*pq, holder);
+ }
+ while (holder &&
+ (ppd->key.mm < key->mm ||
+ (ppd->key.mm == key->mm && ppd->key.skin_muxid < key->skin_muxid)));
+
+ if (ppd->key.mm == key->mm && ppd->key.skin_muxid == key->skin_muxid)
+ {
+ /* found it, return it. */
+ *pholder = ppd;
+ return 1;
+ }
+
+ /* not found, return successor for insertion. */
+ if (ppd->key.mm < key->mm ||
+ (ppd->key.mm == key->mm && ppd->key.skin_muxid < key->skin_muxid))
+ *pholder = holder ? link2ppd(holder) : NULL;
+ else
+ *pholder = ppd;
+
+ return 0;
+}
+
+static void xnppd_insert(xnppd_holder_t *holder)
+{
+ xnppd_holder_t *next;
+ xnqueue_t *q;
+ unsigned found = xnppd_lookup_inner(&q, &next, &holder->key);
+ BUG_ON(found);
+ inith(&holder->link);
+ if (next)
+ insertq(q, &next->link, &holder->link);
+ else
+ appendq(q, &holder->link);
+}
+
+static struct xnppd_holder *xnppd_lookup(unsigned skin_muxid,
+ struct mm_struct *mm)
+{
+ xnppd_holder_t *holder;
+ xnppd_key_t key;
+ unsigned found;
+ xnqueue_t *q;
+
+ key.skin_muxid = skin_muxid;
+ key.mm = mm;
+ found = xnppd_lookup_inner(&q, &holder, &key);
+
+ if (!found)
+ return NULL;
+
+ return holder;
+}
+
+static void xnppd_remove(xnppd_holder_t *holder)
+{
+ unsigned found;
+ xnqueue_t *q;
+
+ found = xnppd_lookup_inner(&q, &holder, &holder->key);
+
+ if (!found)
+ return;
+
+ removeq(q, &holder->link);
+}
+
+static inline void xnppd_remove_mm(struct mm_struct *mm,
+ void (*callback)(xnppd_holder_t *))
+{
+ xnppd_holder_t *ppd;
+ xnholder_t *holder;
+ xnppd_key_t key;
+ xnqueue_t *q;
+
+ key.skin_muxid = 0;
+ key.mm = mm;
+ xnppd_lookup_inner(&q, &ppd, &key);
+
+ while (ppd && ppd->key.mm == mm)
+ {
+ holder = nextq(q, &ppd->link);
+ removeq(q, &ppd->link);
+ callback(ppd);
+ ppd = holder ? link2ppd(holder) : NULL;
+ }
+}
+
static inline void request_syscall_restart(xnthread_t *thread,
struct pt_regs *regs)
{
@@ -916,6 +1044,7 @@
unsigned magic,
u_long featdep, u_long abirev, u_long infarg)
{
+ xnppd_holder_t *holder = NULL;
xnfeatinfo_t finfo;
u_long featmis;
int muxid;
@@ -980,20 +1109,49 @@
earlier than that, do not refer to nkpod until the latter had a
chance to call xnpod_init(). */
- if (muxtable[muxid].eventcb) {
- int err = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH);
+ if (muxtable[muxid].eventcb)
+ {
+ holder = xnppd_lookup(muxid, curr->mm);
- if (err) {
- xnarch_atomic_dec(&muxtable[muxid].refcnt);
- return err;
+ /* protect from the same process binding several time. */
+ if (!holder)
+ {
+ void *ppd = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH, curr);
+ if (IS_ERR(ppd))
+ {
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
+ return PTR_ERR(holder->data);
+ }
+
+ holder = xnarch_sysalloc(sizeof(*holder));
+ if (!holder)
+ {
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
+ return -ENOMEM;
+ }
+
+ holder->key.skin_muxid = muxid;
+ holder->key.mm = curr->mm;
+ holder->data = ppd;
+ xnppd_insert(holder);
+ }
}
- }
- if (!nkpod || testbits(nkpod->status, XNPIDLE))
- /* Ok mate, but you really ought to create some pod in a way
- or another if you want me to be of some help here... */
- return -ENOSYS;
+ if (!nkpod || testbits(nkpod->status,XNPIDLE))
+ /* Ok mate, but you really ought to create some pod in a way
+ or another if you want me to be of some help here... */
+ {
+ if (muxtable[muxid].eventcb && holder)
+ {
+ xnppd_remove(holder);
+ xnarch_sysfree(holder, sizeof(*holder));
+ }
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
+ return -ENOSYS;
+ }
+
return ++muxid;
}
@@ -1640,6 +1798,20 @@
RTHAL_DECLARE_SETSCHED_EVENT(setsched_event);
+static void detach_ppd_holder(xnppd_holder_t *holder)
+{
+ muxtable[holder->key.skin_muxid].eventcb(XNSHADOW_CLIENT_DETACH,
+ holder->data);
+ xnarch_sysfree(holder, sizeof(*holder));
+}
+
+static inline void do_cleanup_event (struct mm_struct *mm)
+{
+ xnppd_remove_mm(mm, detach_ppd_holder);
+}
+
+RTHAL_DECLARE_CLEANUP_EVENT(cleanup_event);
+
/*
* xnshadow_register_interface() -- Register a new skin/interface.
* NOTE: an interface can be registered without its pod being
@@ -1649,9 +1821,10 @@
*/
int xnshadow_register_interface(const char *name,
- unsigned magic,
- int nrcalls,
- xnsysent_t *systab, int (*eventcb) (int))
+ unsigned magic,
+ int nrcalls,
+ xnsysent_t *systab,
+ void *(*eventcb)(int, void *))
{
int muxid;
spl_t s;
@@ -1720,12 +1893,22 @@
return err;
}
+/* Call with nklock locked irqs off. */
+void *xnshadow_get_ppd(unsigned skin_muxid)
+{
+ if (xnpod_userspace_p())
+ return xnppd_lookup(skin_muxid - 1, current->mm)->data;
+
+ return NULL;
+}
+
void xnshadow_grab_events(void)
{
rthal_catch_taskexit(&taskexit_event);
rthal_catch_sigwake(&sigwake_event);
rthal_catch_schedule(&schedule_event);
rthal_catch_setsched(&setsched_event);
+ rthal_catch_cleanup(&cleanup_event);
}
void xnshadow_release_events(void)
@@ -1734,10 +1917,12 @@
rthal_catch_sigwake(NULL);
rthal_catch_schedule(NULL);
rthal_catch_setsched(NULL);
+ rthal_catch_cleanup(NULL);
}
int xnshadow_mount(void)
{
+ unsigned i, size;
int cpu;
#ifdef CONFIG_XENO_OPT_ISHIELD
@@ -1775,6 +1960,17 @@
rthal_catch_losyscall(&losyscall_event);
rthal_catch_hisyscall(&hisyscall_event);
+ size = sizeof(xnqueue_t) * XNPPD_HASH_SIZE;
+ xnppd_hash = (xnqueue_t *) xnarch_sysalloc(size);
+ if (!xnppd_hash)
+ {
+ xnshadow_cleanup();
+ printk(KERN_WARNING "Xenomai: cannot allocate PPD hash table.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < XNPPD_HASH_SIZE; i++)
+ initq(&xnppd_hash[i]);
return 0;
}
@@ -1782,6 +1978,9 @@
{
int cpu;
+ if (xnppd_hash)
+ xnarch_sysfree(xnppd_hash, sizeof(xnqueue_t) * XNPPD_HASH_SIZE);
+
rthal_catch_losyscall(NULL);
rthal_catch_hisyscall(NULL);
@@ -1813,5 +2012,6 @@
EXPORT_SYMBOL(xnshadow_unregister_interface);
EXPORT_SYMBOL(xnshadow_wait_barrier);
EXPORT_SYMBOL(xnshadow_suspend);
+EXPORT_SYMBOL(xnshadow_get_ppd);
EXPORT_SYMBOL(nkthrptd);
EXPORT_SYMBOL(nkerrptd);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-09 17:49 ` Gilles Chanteperdrix
@ 2006-05-09 22:09 ` Philippe Gerum
2006-05-10 13:03 ` Gilles Chanteperdrix
0 siblings, 1 reply; 15+ messages in thread
From: Philippe Gerum @ 2006-05-09 22:09 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
Gilles Chanteperdrix wrote:
> Philippe Gerum wrote:
> > Gilles Chanteperdrix wrote:
> > > Gilles Chanteperdrix wrote:
> > > > These patches are not ready for inclusion, they are not tested
> > > > yet.
> > >
> > > The attached versions are tested. I still wonder if handling this in
> > > shadow.c is the right solution, or if there should be an xnppd_set call
> > > that could be called from within the skins event callbacks.
> > >
> >
> > That would likely be better, since some skin might not want any cleanup
> > code to be called, and in the current implementation, every skin needs
> > to provide some ppd info when returning from the event callback, even if
> > only the CLIENT_ATTACH event is to be monitored. On the other hand, we
> > could argue that registering an event callback requires to implement all
> > requests, including CLIENT_DETACH, possibly by returning a no-op value,
> > so that no ppd registration would be done from bind_to_interface().
> > Actually, I think the latter would be the better option.
>
> If we want CLIENT_DETACH to be called even if CLIENT_ATTACH returned the
> no-op value,
No, we want CLIENT_DETACH to be avoided if CLIENT_ATTACH returned a
no-op value.
we have to allocate and store a ppd holder
> nevertheless. So, the ppd became opaque void * pointers, returned by
> CLIENT_ATTACH and passed back to CLIENT_DETACH. The holder allocation is
> no longer the event callbacks responsibility.
>
>
> > Maybe a better approach would be to simply hash holders referring to
> > busy muxtable entries on mm struct pointers? This way, we would only
> > have to scan a list handling one element per attached skin per
> > terminating process, which will be most of the time a matter of walking
> > through a 1/2 element queue.
> >
> > i.e. indexing table entries on mm pointers from bind_to_interface() to
> > ask for the CLIENT_DETACH event to be fired upon process cleanup:
> >
> > (key: curr->mm) ->
> > (holder: &muxtable[muxid1]) ->
> > (holder: &muxtable[muxid2]) ->
> > (holder: &muxtable[muxid3])
> >
>
> I have kept a hash table, but hashed only on the mm pointer, so that
> data for different skins but the same mm end up contiguously in the same
> bucket and can conveniently be destroyed all at once by an ad-hoc
> function. If you find this unreadable/too baroque, I will switch to the
> two-staged structure you suggest.
>
The point was to avoid scanning the entire muxtable[] for all registered
skins during the cleanup sequence, but rather have a short list of
registered skins indexed on the mm struct key.
> > then, scanning the list hashed on the terminating process's mm struct,
> > in order to fire the appropriate event callbacks.
> >
> > Btw, on 2.4 at least, the global Linux mm_lock is held before firing the
> > process cleanup notification at Adeos level, so one has to be careful
> > about what's actually done in those per-skin cleanup handlers.
>
> POSIX skin will call xnheap_destroy_mapped for shared memory heaps that
> were not unmapped by the process, will this work ?
>
Unsafe on 2.4/SMP (x86 basically), and I'm not sure we could rewrite the
dec_and_lock sequence used in mmput without introducing a bug. This
needs more thought. 2.6 looks ok though.
>
>
> ------------------------------------------------------------------------
>
> Index: include/asm-generic/hal.h
> ===================================================================
> --- include/asm-generic/hal.h (revision 1058)
> +++ include/asm-generic/hal.h (working copy)
> @@ -236,6 +236,14 @@
> return RTHAL_EVENT_PROPAGATE; \
> }
>
> +#define RTHAL_DECLARE_CLEANUP_EVENT(hdlr) \
> +static int hdlr (unsigned event, struct ipipe_domain *ipd, void *data) \
> +{ \
> + struct mm_struct *mm = (struct mm_struct *)data; \
> + do_##hdlr(mm); \
> + return RTHAL_EVENT_PROPAGATE; \
> +}
> +
> #ifndef IPIPE_EVENT_SELF
> /* Some early I-pipe versions don't have this. */
> #define IPIPE_EVENT_SELF 0
> @@ -255,6 +263,8 @@
> #define IPIPE_WIRED_MASK 0
> #endif /* !IPIPE_WIRED_MASK */
>
> +#define rthal_catch_cleanup(hdlr) \
> + ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_CLEANUP,hdlr)
> #define rthal_catch_taskexit(hdlr) \
> ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_EXIT,hdlr)
> #define rthal_catch_sigwake(hdlr) \
> Index: include/nucleus/shadow.h
> ===================================================================
> --- include/nucleus/shadow.h (revision 1058)
> +++ include/nucleus/shadow.h (working copy)
> @@ -48,7 +48,7 @@
> unsigned magic;
> int nrcalls;
> atomic_counter_t refcnt;
> - int (*eventcb)(int);
> + void *(*eventcb)(int, void *);
> xnsysent_t *systab;
> #ifdef CONFIG_PROC_FS
> struct proc_dir_entry *proc;
> @@ -89,7 +89,7 @@
> unsigned magic,
> int nrcalls,
> xnsysent_t *systab,
> - int (*eventcb)(int event));
> + void *(*eventcb)(int event, void *data));
>
> int xnshadow_unregister_interface(int muxid);
>
> @@ -109,6 +109,8 @@
> int sig,
> int specific);
>
> +void *xnshadow_get_ppd(unsigned skin_muxid);
> +
> extern struct xnskentry muxtable[];
>
> #ifdef __cplusplus
> Index: ksrc/nucleus/shadow.c
> ===================================================================
> --- ksrc/nucleus/shadow.c (revision 1058)
> +++ ksrc/nucleus/shadow.c (working copy)
> @@ -48,8 +48,22 @@
> #include <nucleus/shadow.h>
> #include <nucleus/core.h>
> #include <nucleus/ltt.h>
> +#include <nucleus/jhash.h>
> #include <asm/xenomai/features.h>
>
> +typedef struct xnppd_key {
> + unsigned long skin_muxid;
> + struct mm_struct *mm;
> +} xnppd_key_t;
> +
> +typedef struct xnppd_holder {
> + xnppd_key_t key;
> + void *data;
> + xnholder_t link;
> +#define link2ppd(laddr) \
> + (xnppd_holder_t *)((char *)(laddr) - offsetof(xnppd_holder_t, link))
> +} xnppd_holder_t;
> +
> int nkthrptd;
>
> int nkerrptd;
> @@ -95,10 +109,124 @@
>
> static struct task_struct *switch_lock_owner[XNARCH_NR_CPUS];
>
> +static xnqueue_t *xnppd_hash;
> +#define XNPPD_HASH_SIZE 13
> +
> void xnpod_declare_iface_proc(struct xnskentry *iface);
>
> void xnpod_discard_iface_proc(struct xnskentry *iface);
>
> +/* ppd holder with the same mm collide and are stored contiguously in the same
> + bucket, so that they can all be destroyed with only one hash lookup by
> + xnppd_remove_mm. */
> +static unsigned
> +xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
> +{
> + unsigned bucket = jhash2((uint32_t *)&key->mm,
> + sizeof(key->mm)/sizeof(uint32_t), 0);
> + xnppd_holder_t *ppd;
> + xnholder_t *holder;
> +
> + *pq = &xnppd_hash[bucket % XNPPD_HASH_SIZE];
> + holder = getheadq(*pq);
> +
> + if (!holder)
> + {
> + *pholder = NULL;
> + return 0;
> + }
> +
> + do
> + {
> + ppd = link2ppd(holder);
> + holder = nextq(*pq, holder);
> + }
> + while (holder &&
> + (ppd->key.mm < key->mm ||
> + (ppd->key.mm == key->mm && ppd->key.skin_muxid < key->skin_muxid)));
> +
> + if (ppd->key.mm == key->mm && ppd->key.skin_muxid == key->skin_muxid)
> + {
> + /* found it, return it. */
> + *pholder = ppd;
> + return 1;
> + }
> +
> + /* not found, return successor for insertion. */
> + if (ppd->key.mm < key->mm ||
> + (ppd->key.mm == key->mm && ppd->key.skin_muxid < key->skin_muxid))
> + *pholder = holder ? link2ppd(holder) : NULL;
> + else
> + *pholder = ppd;
> +
> + return 0;
> +}
> +
> +static void xnppd_insert(xnppd_holder_t *holder)
> +{
> + xnppd_holder_t *next;
> + xnqueue_t *q;
> + unsigned found = xnppd_lookup_inner(&q, &next, &holder->key);
> + BUG_ON(found);
> + inith(&holder->link);
> + if (next)
> + insertq(q, &next->link, &holder->link);
> + else
> + appendq(q, &holder->link);
> +}
> +
> +static struct xnppd_holder *xnppd_lookup(unsigned skin_muxid,
> + struct mm_struct *mm)
> +{
> + xnppd_holder_t *holder;
> + xnppd_key_t key;
> + unsigned found;
> + xnqueue_t *q;
> +
> + key.skin_muxid = skin_muxid;
> + key.mm = mm;
> + found = xnppd_lookup_inner(&q, &holder, &key);
> +
> + if (!found)
> + return NULL;
> +
> + return holder;
> +}
> +
> +static void xnppd_remove(xnppd_holder_t *holder)
> +{
> + unsigned found;
> + xnqueue_t *q;
> +
> + found = xnppd_lookup_inner(&q, &holder, &holder->key);
> +
> + if (!found)
> + return;
> +
> + removeq(q, &holder->link);
> +}
> +
> +static inline void xnppd_remove_mm(struct mm_struct *mm,
> + void (*callback)(xnppd_holder_t *))
> +{
> + xnppd_holder_t *ppd;
> + xnholder_t *holder;
> + xnppd_key_t key;
> + xnqueue_t *q;
> +
> + key.skin_muxid = 0;
> + key.mm = mm;
> + xnppd_lookup_inner(&q, &ppd, &key);
> +
> + while (ppd && ppd->key.mm == mm)
> + {
> + holder = nextq(q, &ppd->link);
> + removeq(q, &ppd->link);
> + callback(ppd);
> + ppd = holder ? link2ppd(holder) : NULL;
> + }
> +}
> +
> static inline void request_syscall_restart(xnthread_t *thread,
> struct pt_regs *regs)
> {
> @@ -916,6 +1044,7 @@
> unsigned magic,
> u_long featdep, u_long abirev, u_long infarg)
> {
> + xnppd_holder_t *holder = NULL;
> xnfeatinfo_t finfo;
> u_long featmis;
> int muxid;
> @@ -980,20 +1109,49 @@
> earlier than that, do not refer to nkpod until the latter had a
> chance to call xnpod_init(). */
>
> - if (muxtable[muxid].eventcb) {
> - int err = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH);
> + if (muxtable[muxid].eventcb)
> + {
> + holder = xnppd_lookup(muxid, curr->mm);
>
> - if (err) {
> - xnarch_atomic_dec(&muxtable[muxid].refcnt);
> - return err;
> + /* protect from the same process binding several time. */
> + if (!holder)
> + {
> + void *ppd = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH, curr);
> + if (IS_ERR(ppd))
> + {
> + xnarch_atomic_dec(&muxtable[muxid].refcnt);
> + return PTR_ERR(holder->data);
> + }
> +
> + holder = xnarch_sysalloc(sizeof(*holder));
> + if (!holder)
> + {
> + muxtable[muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
> + xnarch_atomic_dec(&muxtable[muxid].refcnt);
> + return -ENOMEM;
> + }
> +
> + holder->key.skin_muxid = muxid;
> + holder->key.mm = curr->mm;
> + holder->data = ppd;
> + xnppd_insert(holder);
> + }
> }
> - }
>
> - if (!nkpod || testbits(nkpod->status, XNPIDLE))
> - /* Ok mate, but you really ought to create some pod in a way
> - or another if you want me to be of some help here... */
> - return -ENOSYS;
> + if (!nkpod || testbits(nkpod->status,XNPIDLE))
> + /* Ok mate, but you really ought to create some pod in a way
> + or another if you want me to be of some help here... */
> + {
> + if (muxtable[muxid].eventcb && holder)
> + {
> + xnppd_remove(holder);
> + xnarch_sysfree(holder, sizeof(*holder));
> + }
>
> + xnarch_atomic_dec(&muxtable[muxid].refcnt);
> + return -ENOSYS;
> + }
> +
> return ++muxid;
> }
>
> @@ -1640,6 +1798,20 @@
>
> RTHAL_DECLARE_SETSCHED_EVENT(setsched_event);
>
> +static void detach_ppd_holder(xnppd_holder_t *holder)
> +{
> + muxtable[holder->key.skin_muxid].eventcb(XNSHADOW_CLIENT_DETACH,
> + holder->data);
> + xnarch_sysfree(holder, sizeof(*holder));
> +}
> +
> +static inline void do_cleanup_event (struct mm_struct *mm)
> +{
> + xnppd_remove_mm(mm, detach_ppd_holder);
> +}
> +
> +RTHAL_DECLARE_CLEANUP_EVENT(cleanup_event);
> +
> /*
> * xnshadow_register_interface() -- Register a new skin/interface.
> * NOTE: an interface can be registered without its pod being
> @@ -1649,9 +1821,10 @@
> */
>
> int xnshadow_register_interface(const char *name,
> - unsigned magic,
> - int nrcalls,
> - xnsysent_t *systab, int (*eventcb) (int))
> + unsigned magic,
> + int nrcalls,
> + xnsysent_t *systab,
> + void *(*eventcb)(int, void *))
> {
> int muxid;
> spl_t s;
> @@ -1720,12 +1893,22 @@
> return err;
> }
>
> +/* Call with nklock locked irqs off. */
> +void *xnshadow_get_ppd(unsigned skin_muxid)
> +{
> + if (xnpod_userspace_p())
> + return xnppd_lookup(skin_muxid - 1, current->mm)->data;
> +
> + return NULL;
> +}
> +
> void xnshadow_grab_events(void)
> {
> rthal_catch_taskexit(&taskexit_event);
> rthal_catch_sigwake(&sigwake_event);
> rthal_catch_schedule(&schedule_event);
> rthal_catch_setsched(&setsched_event);
> + rthal_catch_cleanup(&cleanup_event);
> }
>
> void xnshadow_release_events(void)
> @@ -1734,10 +1917,12 @@
> rthal_catch_sigwake(NULL);
> rthal_catch_schedule(NULL);
> rthal_catch_setsched(NULL);
> + rthal_catch_cleanup(NULL);
> }
>
> int xnshadow_mount(void)
> {
> + unsigned i, size;
> int cpu;
>
> #ifdef CONFIG_XENO_OPT_ISHIELD
> @@ -1775,6 +1960,17 @@
> rthal_catch_losyscall(&losyscall_event);
> rthal_catch_hisyscall(&hisyscall_event);
>
> + size = sizeof(xnqueue_t) * XNPPD_HASH_SIZE;
> + xnppd_hash = (xnqueue_t *) xnarch_sysalloc(size);
> + if (!xnppd_hash)
> + {
> + xnshadow_cleanup();
> + printk(KERN_WARNING "Xenomai: cannot allocate PPD hash table.\n");
> + return -ENOMEM;
> + }
> +
> + for (i = 0; i < XNPPD_HASH_SIZE; i++)
> + initq(&xnppd_hash[i]);
> return 0;
> }
>
> @@ -1782,6 +1978,9 @@
> {
> int cpu;
>
> + if (xnppd_hash)
> + xnarch_sysfree(xnppd_hash, sizeof(xnqueue_t) * XNPPD_HASH_SIZE);
> +
> rthal_catch_losyscall(NULL);
> rthal_catch_hisyscall(NULL);
>
> @@ -1813,5 +2012,6 @@
> EXPORT_SYMBOL(xnshadow_unregister_interface);
> EXPORT_SYMBOL(xnshadow_wait_barrier);
> EXPORT_SYMBOL(xnshadow_suspend);
> +EXPORT_SYMBOL(xnshadow_get_ppd);
> EXPORT_SYMBOL(nkthrptd);
> EXPORT_SYMBOL(nkerrptd);
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-09 22:09 ` Philippe Gerum
@ 2006-05-10 13:03 ` Gilles Chanteperdrix
2006-05-11 12:53 ` Philippe Gerum
0 siblings, 1 reply; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-10 13:03 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai
[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 1417 bytes --]
Philippe Gerum wrote:
> Gilles Chanteperdrix wrote:
> > Philippe Gerum wrote:
> > > Gilles Chanteperdrix wrote:
> > > > Gilles Chanteperdrix wrote:
> > > > > These patches are not ready for inclusion, they are not tested
> > > > > yet.
> > > >
> > > > The attached versions are tested. I still wonder if handling this in
> > > > shadow.c is the right solution, or if there should be an xnppd_set call
> > > > that could be called from within the skins event callbacks.
> > > >
> > >
> > > That would likely be better, since some skin might not want any cleanup
> > > code to be called, and in the current implementation, every skin needs
> > > to provide some ppd info when returning from the event callback, even if
> > > only the CLIENT_ATTACH event is to be monitored. On the other hand, we
> > > could argue that registering an event callback requires to implement all
> > > requests, including CLIENT_DETACH, possibly by returning a no-op value,
> > > so that no ppd registration would be done from bind_to_interface().
> > > Actually, I think the latter would be the better option.
> >
> > If we want CLIENT_DETACH to be called even if CLIENT_ATTACH returned the
> > no-op value,
>
> No, we want CLIENT_DETACH to be avoided if CLIENT_ATTACH returned a
> no-op value.
>
The attached version of the patch do that.
--
Gilles Chanteperdrix.
[-- Attachment #2: xenomai-ppd.4.diff --]
[-- Type: text/plain, Size: 10589 bytes --]
Index: include/asm-generic/hal.h
===================================================================
--- include/asm-generic/hal.h (revision 1058)
+++ include/asm-generic/hal.h (working copy)
@@ -236,6 +236,14 @@
return RTHAL_EVENT_PROPAGATE; \
}
+#define RTHAL_DECLARE_CLEANUP_EVENT(hdlr) \
+static int hdlr (unsigned event, struct ipipe_domain *ipd, void *data) \
+{ \
+ struct mm_struct *mm = (struct mm_struct *)data; \
+ do_##hdlr(mm); \
+ return RTHAL_EVENT_PROPAGATE; \
+}
+
#ifndef IPIPE_EVENT_SELF
/* Some early I-pipe versions don't have this. */
#define IPIPE_EVENT_SELF 0
@@ -255,6 +263,8 @@
#define IPIPE_WIRED_MASK 0
#endif /* !IPIPE_WIRED_MASK */
+#define rthal_catch_cleanup(hdlr) \
+ ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_CLEANUP,hdlr)
#define rthal_catch_taskexit(hdlr) \
ipipe_catch_event(ipipe_root_domain,IPIPE_EVENT_EXIT,hdlr)
#define rthal_catch_sigwake(hdlr) \
--- /dev/null 2006-05-10 02:46:08.416452000 +0200
+++ include/nucleus/ppd.h 2006-05-10 14:27:11.000000000 +0200
@@ -0,0 +1,26 @@
+#ifndef PPD_H
+#define PPD_H
+
+#include <nucleus/queue.h>
+
+struct mm_struct;
+
+typedef struct xnppd_key {
+ unsigned long muxid;
+ struct mm_struct *mm;
+} xnppd_key_t;
+
+typedef struct xnppd_holder {
+ xnppd_key_t key;
+ xnholder_t link;
+#define link2ppd(laddr) \
+ (xnppd_holder_t *)((char *)(laddr) - offsetof(xnppd_holder_t, link))
+} xnppd_holder_t;
+
+#define xnppd_muxid(ppd) ((ppd)->key.muxid)
+
+#define xnppd_mm(ppd) ((ppd)->key.mm)
+
+xnppd_holder_t *xnppd_get(unsigned muxid);
+
+#endif /* PPD_H */
Index: include/nucleus/shadow.h
===================================================================
--- include/nucleus/shadow.h (revision 1058)
+++ include/nucleus/shadow.h (working copy)
@@ -48,7 +48,7 @@
unsigned magic;
int nrcalls;
atomic_counter_t refcnt;
- int (*eventcb)(int);
+ void *(*eventcb)(int, void *);
xnsysent_t *systab;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
@@ -89,7 +89,7 @@
unsigned magic,
int nrcalls,
xnsysent_t *systab,
- int (*eventcb)(int event));
+ void *(*eventcb)(int event, void *data));
int xnshadow_unregister_interface(int muxid);
Index: ksrc/nucleus/shadow.c
===================================================================
--- ksrc/nucleus/shadow.c (revision 1058)
+++ ksrc/nucleus/shadow.c (working copy)
@@ -48,6 +48,8 @@
#include <nucleus/shadow.h>
#include <nucleus/core.h>
#include <nucleus/ltt.h>
+#include <nucleus/jhash.h>
+#include <nucleus/ppd.h>
#include <asm/xenomai/features.h>
int nkthrptd;
@@ -95,10 +97,141 @@
static struct task_struct *switch_lock_owner[XNARCH_NR_CPUS];
+static xnqueue_t *xnppd_hash;
+#define XNPPD_HASH_SIZE 13
+
void xnpod_declare_iface_proc(struct xnskentry *iface);
void xnpod_discard_iface_proc(struct xnskentry *iface);
+/* ppd holder with the same mm collide and are stored contiguously in the same
+ bucket, so that they can all be destroyed with only one hash lookup by
+ xnppd_remove_mm. */
+static unsigned
+xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
+{
+ unsigned bucket = jhash2((uint32_t *)&key->mm,
+ sizeof(key->mm)/sizeof(uint32_t), 0);
+ xnppd_holder_t *ppd;
+ xnholder_t *holder;
+
+ *pq = &xnppd_hash[bucket % XNPPD_HASH_SIZE];
+ holder = getheadq(*pq);
+
+ if (!holder)
+ {
+ *pholder = NULL;
+ return 0;
+ }
+
+ do
+ {
+ ppd = link2ppd(holder);
+ holder = nextq(*pq, holder);
+ }
+ while (holder &&
+ (ppd->key.mm < key->mm ||
+ (ppd->key.mm == key->mm && ppd->key.muxid < key->muxid)));
+
+ if (ppd->key.mm == key->mm && ppd->key.muxid == key->muxid)
+ {
+ /* found it, return it. */
+ *pholder = ppd;
+ return 1;
+ }
+
+ /* not found, return successor for insertion. */
+ if (ppd->key.mm < key->mm ||
+ (ppd->key.mm == key->mm && ppd->key.muxid < key->muxid))
+ *pholder = holder ? link2ppd(holder) : NULL;
+ else
+ *pholder = ppd;
+
+ return 0;
+}
+
+static void xnppd_insert(xnppd_holder_t *holder)
+{
+ xnppd_holder_t *next;
+ xnqueue_t *q;
+ unsigned found;
+ spl_t s;
+
+ xnlock_get_irqsave(&nklock, s);
+ found = xnppd_lookup_inner(&q, &next, &holder->key);
+ BUG_ON(found);
+ inith(&holder->link);
+ if (next)
+ insertq(q, &next->link, &holder->link);
+ else
+ appendq(q, &holder->link);
+ xnlock_put_irqrestore(&nklock, s);
+}
+
+/* will be called by skin code, nklock locked irqs off. */
+static struct xnppd_holder *xnppd_lookup(unsigned muxid,
+ struct mm_struct *mm)
+{
+ xnppd_holder_t *holder;
+ xnppd_key_t key;
+ unsigned found;
+ xnqueue_t *q;
+
+ key.muxid = muxid;
+ key.mm = mm;
+ found = xnppd_lookup_inner(&q, &holder, &key);
+
+ if (!found)
+ return NULL;
+
+ return holder;
+}
+
+static void xnppd_remove(xnppd_holder_t *holder)
+{
+ unsigned found;
+ xnqueue_t *q;
+ spl_t s;
+
+ xnlock_get_irqsave(&nklock, s);
+ found = xnppd_lookup_inner(&q, &holder, &holder->key);
+
+ if (found)
+ removeq(q, &holder->link);
+
+ xnlock_put_irqrestore(&nklock, s);
+}
+
+static inline void xnppd_remove_mm(struct mm_struct *mm,
+ void (*destructor)(xnppd_holder_t *))
+{
+ xnppd_holder_t *ppd;
+ xnholder_t *holder;
+ xnppd_key_t key;
+ xnqueue_t *q;
+ spl_t s;
+
+ key.muxid = 0;
+ key.mm = mm;
+ xnlock_get_irqsave(&nklock, s);
+ xnppd_lookup_inner(&q, &ppd, &key);
+
+ while (ppd && ppd->key.mm == mm)
+ {
+ holder = nextq(q, &ppd->link);
+ removeq(q, &ppd->link);
+ xnlock_put_irqrestore(&nklock, s);
+ /* releasing nklock is safe here, if we assume that no insertion for the
+ same mm will take place while we are running xnpod_remove_mm. */
+ destructor(ppd);
+
+ ppd = holder ? link2ppd(holder) : NULL;
+ xnlock_get_irqsave(&nklock, s);
+ }
+
+ xnlock_put_irqrestore(&nklock, s);
+}
+
static inline void request_syscall_restart(xnthread_t *thread,
struct pt_regs *regs)
{
@@ -916,6 +1049,7 @@
unsigned magic,
u_long featdep, u_long abirev, u_long infarg)
{
+ xnppd_holder_t *ppd = NULL;
xnfeatinfo_t finfo;
u_long featmis;
int muxid;
@@ -981,18 +1115,39 @@
chance to call xnpod_init(). */
if (muxtable[muxid].eventcb) {
- int err = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH);
+ xnlock_get_irqsave(&nklock, s);
+ ppd = xnppd_lookup(muxid, curr->mm);
+ xnlock_put_irqrestore(&nklocks, s);
- if (err) {
- xnarch_atomic_dec(&muxtable[muxid].refcnt);
- return err;
+ /* protect from the same process binding several time. */
+ if (!ppd) {
+ ppd = (xnppd_holder_t *)
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH, curr);
+
+ if (IS_ERR(ppd)) {
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
+ return PTR_ERR(ppd);
+ }
+
+ if (ppd) {
+ ppd->key.muxid = muxid;
+ ppd->key.mm = curr->mm;
+ xnppd_insert(ppd);
+ }
}
}
- if (!nkpod || testbits(nkpod->status, XNPIDLE))
+ if (!nkpod || testbits(nkpod->status, XNPIDLE)) {
/* Ok mate, but you really ought to create some pod in a way
or another if you want me to be of some help here... */
+ if (muxtable[muxid].eventcb && ppd) {
+ xnppd_remove(ppd);
+ muxtable[muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
+ }
+
+ xnarch_atomic_dec(&muxtable[muxid].refcnt);
return -ENOSYS;
+ }
return ++muxid;
}
@@ -1640,6 +1795,18 @@
RTHAL_DECLARE_SETSCHED_EVENT(setsched_event);
+static void detach_ppd(xnppd_holder_t *ppd)
+{
+ muxtable[holder->key.muxid].eventcb(XNSHADOW_CLIENT_DETACH, ppd);
+}
+
+static inline void do_cleanup_event (struct mm_struct *mm)
+{
+ xnppd_remove_mm(mm, &detach_ppd);
+}
+
+RTHAL_DECLARE_CLEANUP_EVENT(cleanup_event);
+
/*
* xnshadow_register_interface() -- Register a new skin/interface.
* NOTE: an interface can be registered without its pod being
@@ -1651,7 +1818,8 @@
int xnshadow_register_interface(const char *name,
unsigned magic,
int nrcalls,
- xnsysent_t *systab, int (*eventcb) (int))
+ xnsysent_t *systab,
+ void *(*eventcb)(int, void *))
{
int muxid;
spl_t s;
@@ -1720,12 +1888,22 @@
return err;
}
+/* Call with nklock locked irqs off. */
+xnppd_holder_t *xnppd_get(unsigned muxid)
+{
+ if (xnpod_userspace_p())
+ return xnppd_lookup(muxid - 1, current->mm);
+
+ return NULL;
+}
+
void xnshadow_grab_events(void)
{
rthal_catch_taskexit(&taskexit_event);
rthal_catch_sigwake(&sigwake_event);
rthal_catch_schedule(&schedule_event);
rthal_catch_setsched(&setsched_event);
+ rthal_catch_cleanup(&cleanup_event);
}
void xnshadow_release_events(void)
@@ -1734,10 +1912,12 @@
rthal_catch_sigwake(NULL);
rthal_catch_schedule(NULL);
rthal_catch_setsched(NULL);
+ rthal_catch_cleanup(NULL);
}
int xnshadow_mount(void)
{
+ unsigned i, size;
int cpu;
#ifdef CONFIG_XENO_OPT_ISHIELD
@@ -1775,6 +1955,17 @@
rthal_catch_losyscall(&losyscall_event);
rthal_catch_hisyscall(&hisyscall_event);
+ size = sizeof(xnqueue_t) * XNPPD_HASH_SIZE;
+ xnppd_hash = (xnqueue_t *) xnarch_sysalloc(size);
+ if (!xnppd_hash)
+ {
+ xnshadow_cleanup();
+ printk(KERN_WARNING "Xenomai: cannot allocate PPD hash table.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < XNPPD_HASH_SIZE; i++)
+ initq(&xnppd_hash[i]);
return 0;
}
@@ -1782,6 +1973,9 @@
{
int cpu;
+ if (xnppd_hash)
+ xnarch_sysfree(xnppd_hash, sizeof(xnqueue_t) * XNPPD_HASH_SIZE);
+
rthal_catch_losyscall(NULL);
rthal_catch_hisyscall(NULL);
@@ -1815,3 +2009,4 @@
EXPORT_SYMBOL(xnshadow_suspend);
EXPORT_SYMBOL(nkthrptd);
EXPORT_SYMBOL(nkerrptd);
+EXPORT_SYMBOL(xnppd_get);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-10 13:03 ` Gilles Chanteperdrix
@ 2006-05-11 12:53 ` Philippe Gerum
2006-05-11 14:03 ` Gilles Chanteperdrix
0 siblings, 1 reply; 15+ messages in thread
From: Philippe Gerum @ 2006-05-11 12:53 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
Gilles Chanteperdrix wrote:
> The attached version of the patch do that.
Fine with me, please merge as you see fit. Details follow:
> +++ include/nucleus/ppd.h 2006-05-10 14:27:11.000000000 +0200
> @@ -0,0 +1,26 @@
> +#ifndef PPD_H
> +#define PPD_H
> +
Given that ppds are shadow-specific, I would move ppd.h's contents to
shadow.h directly.
> +static unsigned
> +xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
> +{
> + unsigned bucket = jhash2((uint32_t *)&key->mm,
> + sizeof(key->mm)/sizeof(uint32_t), 0);
GCC is likely going to wine on 64-bit archs for attempting to forge a
type-punned pointer.
> + xnppd_holder_t *ppd = NULL;
> xnfeatinfo_t finfo;
> u_long featmis;
> int muxid;
> @@ -981,18 +1115,39 @@
> chance to call xnpod_init(). */
>
> if (muxtable[muxid].eventcb) {
> - int err = muxtable[muxid].eventcb(XNSHADOW_CLIENT_ATTACH);
> + xnlock_get_irqsave(&nklock, s);
> + ppd = xnppd_lookup(muxid, curr->mm);
> + xnlock_put_irqrestore(&nklocks, s);
>
Looks racy to release the nucleus lock that early before actually using
the found value, if another thread from the same process manages to
preempt the caller and interleave a binding request on its own (would be
stupid, I agree, but hey, most of our day-to-day job is to implement
LARTs pretending that we are "innovating" somehow, so...)
>
> +/* Call with nklock locked irqs off. */
> +xnppd_holder_t *xnppd_get(unsigned muxid)
> +{
> + if (xnpod_userspace_p())
> + return xnppd_lookup(muxid - 1, current->mm);
> +
> + return NULL;
> +}
Same remark than previously regarding shadow.h, all the xnppd_* services
are truely shadow-related services, so calling them
xnshadow_ppd*something() would be more accurate.
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-11 12:53 ` Philippe Gerum
@ 2006-05-11 14:03 ` Gilles Chanteperdrix
2006-05-11 14:12 ` Philippe Gerum
0 siblings, 1 reply; 15+ messages in thread
From: Gilles Chanteperdrix @ 2006-05-11 14:03 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai
Philippe Gerum wrote:
> Gilles Chanteperdrix wrote:
> > The attached version of the patch do that.
>
> Fine with me, please merge as you see fit. Details follow:
>
> > +++ include/nucleus/ppd.h 2006-05-10 14:27:11.000000000 +0200
> > @@ -0,0 +1,26 @@
> > +#ifndef PPD_H
> > +#define PPD_H
> > +
>
> Given that ppds are shadow-specific, I would move ppd.h's contents to
> shadow.h directly.
I tried, but it is not possible, shadow.h is included in asm/system.h
and thus can not include nucleus/queue.h.
>
> > +static unsigned
> > +xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
> > +{
> > + unsigned bucket = jhash2((uint32_t *)&key->mm,
> > + sizeof(key->mm)/sizeof(uint32_t), 0);
>
> GCC is likely going to wine on 64-bit archs for attempting to forge a
> type-punned pointer.
How do I write this then ? It is a copy of some code in posix/syscall.c
--
Gilles Chanteperdrix.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Xenomai-core] [RFC][patch] per-process data.
2006-05-11 14:03 ` Gilles Chanteperdrix
@ 2006-05-11 14:12 ` Philippe Gerum
0 siblings, 0 replies; 15+ messages in thread
From: Philippe Gerum @ 2006-05-11 14:12 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
Gilles Chanteperdrix wrote:
> Philippe Gerum wrote:
> > Gilles Chanteperdrix wrote:
> > > The attached version of the patch do that.
> >
> > Fine with me, please merge as you see fit. Details follow:
> >
> > > +++ include/nucleus/ppd.h 2006-05-10 14:27:11.000000000 +0200
> > > @@ -0,0 +1,26 @@
> > > +#ifndef PPD_H
> > > +#define PPD_H
> > > +
> >
> > Given that ppds are shadow-specific, I would move ppd.h's contents to
> > shadow.h directly.
>
> I tried, but it is not possible, shadow.h is included in asm/system.h
> and thus can not include nucleus/queue.h.
>
Grumble. Ok, we're toast. Let's go for ppd.h.
> >
> > > +static unsigned
> > > +xnppd_lookup_inner(xnqueue_t **pq, xnppd_holder_t **pholder, xnppd_key_t *key)
> > > +{
> > > + unsigned bucket = jhash2((uint32_t *)&key->mm,
> > > + sizeof(key->mm)/sizeof(uint32_t), 0);
> >
> > GCC is likely going to wine on 64-bit archs for attempting to forge a
> > type-punned pointer.
>
> How do I write this then ? It is a copy of some code in posix/syscall.c
>
vrtx/mb.c would do.
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2006-05-11 14:12 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-07 18:00 [Xenomai-core] [RFC][patch] per-process data Gilles Chanteperdrix
2006-05-07 21:15 ` Jan Kiszka
2006-05-07 23:04 ` Gilles Chanteperdrix
2006-05-08 10:18 ` Dmitry Adamushko
2006-05-08 12:47 ` Gilles Chanteperdrix
2006-05-08 13:05 ` Jan Kiszka
2006-05-08 12:51 ` Gilles Chanteperdrix
2006-05-08 13:14 ` Gilles Chanteperdrix
2006-05-08 13:51 ` Philippe Gerum
2006-05-09 17:49 ` Gilles Chanteperdrix
2006-05-09 22:09 ` Philippe Gerum
2006-05-10 13:03 ` Gilles Chanteperdrix
2006-05-11 12:53 ` Philippe Gerum
2006-05-11 14:03 ` Gilles Chanteperdrix
2006-05-11 14:12 ` 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.