Module: xenomai-gch
Branch: for-head
Commit: 36247dec656766b6eebb481462c5019097892e05
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=36247dec656766b6eebb481462c5019097892e05

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    |   18 ++++++++++--
 ksrc/nucleus/pod.c       |    4 --
 ksrc/nucleus/select.c    |   69 ++++++++++++++++++++++++++++++++++++---------
 4 files changed, 75 insertions(+), 21 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 141276a..620ee9b 100644
--- a/ksrc/nucleus/module.c
+++ b/ksrc/nucleus/module.c
@@ -33,6 +33,7 @@
 #ifdef CONFIG_XENO_OPT_PIPE
 #include <nucleus/pipe.h>
 #endif /* CONFIG_XENO_OPT_PIPE */
+#include <nucleus/select.h>
 #include <asm/xenomai/bits/init.h>
 
 MODULE_DESCRIPTION("Xenomai nucleus");
@@ -115,10 +116,16 @@ int __init __xeno_sys_init(void)
                goto cleanup_proc;
 #endif /* CONFIG_XENO_OPT_PIPE */
 
+#ifdef CONFIG_XENO_OPT_SELECT
+       ret = xnselect_mount();
+       if (ret)
+               goto cleanup_pipe;
+#endif /* CONFIG_XENO_OPT_SELECT */
+
 #ifdef CONFIG_XENO_OPT_PERVASIVE
        ret = xnshadow_mount();
        if (ret)
-               goto cleanup_pipe;
+               goto cleanup_select;
 
        ret = xnheap_mount();
        if (ret)
@@ -151,10 +158,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 77c69fd..7daf0f7 100644
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -1190,8 +1190,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 */
@@ -1284,8 +1282,6 @@ void xnpod_abort_thread(xnthread_t *thread)
                                     XN_INFINITE, XN_RELATIVE, NULL);
        xnthread_set_info(thread, XNABORT);
        xnpod_delete_thread(thread);
-       /* FIXME: in case thread has a selector, the xnfree(selector)
-          happens with nklock locked. */
        xnlock_put_irqrestore(&nklock, s);
 }
 EXPORT_SYMBOL_GPL(xnpod_abort_thread);
diff --git a/ksrc/nucleus/select.c b/ksrc/nucleus/select.c
index 10355bf..fd56bfb 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,29 +391,67 @@ EXPORT_SYMBOL_GPL(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;
-               spl_t dummy;
+       appendq(&xnselectors, &selector->destroy_link);
+       xnlock_put_irqrestore(&nklock, s);
 
-               binding = link2binding(holder, slink);
-               fd = binding->fd;
-               removeq(&fd->bindings, &binding->link);
-               xnlock_clear_irqon(&nklock);
+       rthal_apc_schedule(xnselect_apc);
+}
+EXPORT_SYMBOL_GPL(xnselector_destroy);
 
-               xnfree(binding);
+static void xnselector_destroy_loop(void *cookie)
+{
+       struct xnselector *selector;
+       xnholder_t *holder;
+       int resched;
+       spl_t s;
 
-               xnlock_get_irqsave(&nklock, dummy);
+       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(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_GPL(xnselector_destroy);
 
 /*...@}*/


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

Reply via email to