Module: xenomai-gch
Branch: for-2.4
Commit: 3d4e22a501b33979f3be98d6ed2e3947f2361567
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=3d4e22a501b33979f3be98d6ed2e3947f2361567

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Thu Nov  5 23:49:43 2009 +0100

nucleus: defer selector block deletion to an APC.

Avoid creating reschedulings in the middle of xnpod_delete_thread.

---

 include/nucleus/select.h |    5 +++
 ksrc/nucleus/module.c    |   19 +++++++++++--
 ksrc/nucleus/pod.c       |    4 ---
 ksrc/nucleus/select.c    |   64 ++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 74 insertions(+), 18 deletions(-)

diff --git a/include/nucleus/select.h b/include/nucleus/select.h
index b098b63..20eefbe 100644
--- a/include/nucleus/select.h
+++ b/include/nucleus/select.h
@@ -41,6 +41,7 @@ struct xnselector {
                fd_set expected;
                fd_set pending;
        } fds [XNSELECT_MAX_TYPES];
+       xnholder_t destroy_link;
        xnqueue_t bindings; /* only used by xnselector_destroy */
 };
 
@@ -106,6 +107,10 @@ int xnselect(struct xnselector *selector,
 
 void xnselector_destroy(struct xnselector *selector);
 
+int xnselect_mount(void);
+
+int xnselect_umount(void);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/ksrc/nucleus/module.c b/ksrc/nucleus/module.c
index bc3bc59..cde32f9 100644
--- a/ksrc/nucleus/module.c
+++ b/ksrc/nucleus/module.c
@@ -34,6 +34,7 @@
 #ifdef CONFIG_XENO_OPT_PERVASIVE
 #include <nucleus/core.h>
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
+#include <nucleus/select.h>
 #include <asm/xenomai/bits/init.h>
 
 MODULE_DESCRIPTION("Xenomai nucleus");
@@ -1171,11 +1172,18 @@ int __init __xeno_sys_init(void)
                goto cleanup_arch;
 #endif /* CONFIG_XENO_OPT_PIPE */
 
+#ifdef CONFIG_XENO_OPT_SELECT
+       err = xnselect_mount();
+
+       if (err)
+               goto cleanup_pipe;
+#endif /* CONFIG_XENO_OPT_SELECT */
+
 #ifdef CONFIG_XENO_OPT_PERVASIVE
        err = xnshadow_mount();
 
        if (err)
-               goto cleanup_pipe;
+               goto cleanup_select;
 
        err = xnheap_mount();
 
@@ -1201,10 +1209,15 @@ int __init __xeno_sys_init(void)
 
        xnshadow_cleanup();
 
-      cleanup_pipe:
-
+      cleanup_select:
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
+#ifdef CONFIG_XENO_OPT_SELECT
+       xnselect_umount();
+       
+      cleanup_pipe:
+#endif /* CONFIG_XENO_OPT_SELECT */
+
 #ifdef CONFIG_XENO_OPT_PIPE
        xnpipe_umount();
 
diff --git a/ksrc/nucleus/pod.c b/ksrc/nucleus/pod.c
index bee6a04..386f86a 100644
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -1208,8 +1208,6 @@ void xnpod_delete_thread(xnthread_t *thread)
 #ifdef CONFIG_XENO_OPT_SELECT
        if (thread->selector) {
                xnselector_destroy(thread->selector);
-               xnheap_schedule_free(&kheap, thread->selector, 
-                                    (xnholder_t *)thread->selector);
                thread->selector = NULL;
        }
 #endif /* CONFIG_XENO_OPT_SELECT */
@@ -1293,8 +1291,6 @@ void xnpod_abort_thread(xnthread_t *thread)
        if (!xnpod_current_p(thread))
                xnpod_suspend_thread(thread, XNDORMANT, XN_INFINITE, 
XN_RELATIVE, NULL);
        xnpod_delete_thread(thread);
-       /* FIXME: in case thread has a selector, the xnfree(selector)
-          happens with nklock locked. */
        xnlock_put_irqrestore(&nklock, s);
 }
 
diff --git a/ksrc/nucleus/select.c b/ksrc/nucleus/select.c
index 502e7f6..d63503f 100644
--- a/ksrc/nucleus/select.c
+++ b/ksrc/nucleus/select.c
@@ -53,6 +53,9 @@
 #include <linux/types.h>
 #include <linux/bitops.h>      /* For hweight_long */
 
+static xnqueue_t xnselectors;
+static int xnselect_apc;
+
 #define link2binding(baddr, memb)                              \
        container_of(baddr, struct xnselect_binding, memb)
 
@@ -388,28 +391,67 @@ EXPORT_SYMBOL(xnselect);
  */
 void xnselector_destroy(struct xnselector *selector)
 {
-       xnholder_t *holder;
        spl_t s;
 
+       inith(&selector->destroy_link);
        xnlock_get_irqsave(&nklock, s);
-       while ((holder = getq(&selector->bindings))) {
-               struct xnselect_binding *binding;
-               struct xnselect *fd;
+       appendq(&xnselectors, &selector->destroy_link);
+       xnlock_put_irqrestore(&nklock, s);
+
+       rthal_apc_schedule(xnselect_apc);
+}
+EXPORT_SYMBOL_GPL(xnselector_destroy);
+
+static void xnselector_destroy_loop(void *cookie)
+{
+       struct xnselector *selector;
+       xnholder_t *holder;
+       int resched;
+       spl_t s;
 
-               binding = link2binding(holder, slink);
-               fd = binding->fd;
-               removeq(&fd->bindings, &binding->link);
+       xnlock_get_irqsave(&nklock, s);
+       while ((holder = getq(&xnselectors))) {
+               selector = container_of(holder, struct xnselector, 
destroy_link);
+               while ((holder = getq(&selector->bindings))) {
+                       struct xnselect_binding *binding;
+                       struct xnselect *fd;
+
+                       binding = link2binding(holder, slink);
+                       fd = binding->fd;
+                       removeq(&fd->bindings, &binding->link);
+                       xnlock_put_irqrestore(&nklock, s);
+
+                       xnfree(binding);
+
+                       xnlock_get_irqsave(&nklock, s);
+               }
+               resched = 
+                       xnsynch_destroy(&selector->synchbase) == 
XNSYNCH_RESCHED;
                xnlock_put_irqrestore(&nklock, s);
 
-               xnfree(binding);
+               xnfree(selector);
+               if (resched)
+                       xnpod_schedule();
 
                xnlock_get_irqsave(&nklock, s);
        }
        xnlock_put_irqrestore(&nklock, s);
+}
+
+int xnselect_mount(void)
+{
+       initq(&xnselectors);
+       xnselect_apc = rthal_apc_alloc("xnselectors_destroy", 
+                                      xnselector_destroy_loop, NULL);
+       if (xnselect_apc < 0)
+               return xnselect_apc;
 
-       if (xnsynch_destroy(&selector->synchbase) == XNSYNCH_RESCHED)
-               xnpod_schedule();
+       return 0;
+}
+
+int xnselect_umount(void)
+{
+       return rthal_apc_free(xnselect_apc);
 }
-EXPORT_SYMBOL(xnselector_destroy);
 
 /*...@}*/


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to