Module: xenomai-forge
Branch: master
Commit: 014898add6a697e1a0d69f9e20b910ade74f1940
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=014898add6a697e1a0d69f9e20b910ade74f1940

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun Apr 14 18:59:29 2013 +0200

lib/cobalt: fix atfork handling

The TLS-based "current" key must be cleared upon fork in the child
context, so that assertion code checking the current mode does not
spuriously reuse the parent u_window.

In addition, the calling sequence of atfork handlers is fixed, so that
such handler installed by the deferred print support does not call
into assert_nrt() checks from a freshly forked child before the
"current" key is cleared.

---

 lib/cobalt/assert_context.c |    5 +++--
 lib/cobalt/current.c        |   35 +++++++++++++++++++++--------------
 lib/cobalt/init.c           |    4 ++--
 lib/cobalt/internal.h       |    4 ++++
 lib/cobalt/printf.c         |    9 ++++++---
 lib/cobalt/sem_heap.c       |    1 +
 6 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/lib/cobalt/assert_context.c b/lib/cobalt/assert_context.c
index 9a864fc..6125355 100644
--- a/lib/cobalt/assert_context.c
+++ b/lib/cobalt/assert_context.c
@@ -23,6 +23,7 @@
 #include <nucleus/thread.h>
 #include <asm-generic/syscall.h>
 #include <asm-generic/current.h>
+#include <unistd.h>
 
 static void assert_nrt_inner(void)
 {
@@ -32,8 +33,8 @@ static void assert_nrt_inner(void)
        err = XENOMAI_SYSCALL1(sc_nucleus_current_info, &info);
 
        if (err) {
-               fprintf(stderr, "sc_nucleus_current_info failed: %s\n",
-                       strerror(-err));
+               fprintf(stderr, "sc_nucleus_current_info failed: %s, window=%p, 
state=%lx, pid=%d\n",
+                       strerror(-err), xeno_current_window, 
xeno_current_window->state, getpid());
                return;
        }
 
diff --git a/lib/cobalt/current.c b/lib/cobalt/current.c
index 1822703..5b7ed19 100644
--- a/lib/cobalt/current.c
+++ b/lib/cobalt/current.c
@@ -12,9 +12,13 @@
 
 extern unsigned long xeno_sem_heap[2];
 
+static void child_fork_handler(void);
+
 #ifdef HAVE_TLS
+
 __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
 xnhandle_t xeno_current = XN_NO_HANDLE;
+
 __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
 struct xnthread_user_window *xeno_current_window;
 
@@ -23,8 +27,9 @@ static inline void __xeno_set_current(xnhandle_t current)
        xeno_current = current;
 }
 
-void xeno_init_current_keys(void)
+static void init_current_keys(void)
 {
+       pthread_atfork(NULL, NULL, &child_fork_handler);
 }
 
 void xeno_set_current_window(unsigned long offset)
@@ -33,6 +38,7 @@ void xeno_set_current_window(unsigned long offset)
                (xeno_sem_heap[0] + offset);
        __cobalt_prefault(xeno_current_window);
 }
+
 #else /* !HAVE_TLS */
 
 pthread_key_t xeno_current_window_key;
@@ -44,19 +50,13 @@ static inline void __xeno_set_current(xnhandle_t current)
        pthread_setspecific(xeno_current_key, (void *)current);
 }
 
-static void xeno_current_fork_handler(void)
-{
-       if (xeno_get_current() != XN_NO_HANDLE)
-               __xeno_set_current(XN_NO_HANDLE);
-}
-
 static void init_current_keys(void)
 {
        int err = pthread_key_create(&xeno_current_key, NULL);
        if (err)
                goto error_exit;
 
-       pthread_atfork(NULL, NULL, &xeno_current_fork_handler);
+       pthread_atfork(NULL, NULL, &child_fork_handler);
 
        err = pthread_key_create(&xeno_current_window_key, NULL);
        if (err) {
@@ -67,12 +67,6 @@ static void init_current_keys(void)
        }
 }
 
-void xeno_init_current_keys(void)
-{
-       static pthread_once_t xeno_init_current_keys_once = PTHREAD_ONCE_INIT;
-       pthread_once(&xeno_init_current_keys_once, init_current_keys);
-}
-
 void xeno_set_current_window(unsigned long offset)
 {
        struct xnthread_user_window *window;
@@ -81,8 +75,15 @@ void xeno_set_current_window(unsigned long offset)
        pthread_setspecific(xeno_current_window_key, window);
        __cobalt_prefault(window);
 }
+
 #endif /* !HAVE_TLS */
 
+static void child_fork_handler(void)
+{
+       if (xeno_get_current() != XN_NO_HANDLE)
+               __xeno_set_current(XN_NO_HANDLE);
+}
+
 xnhandle_t xeno_slow_get_current(void)
 {
        xnhandle_t current;
@@ -106,3 +107,9 @@ void xeno_set_current(void)
        }
        __xeno_set_current(current);
 }
+
+void xeno_init_current_keys(void)
+{
+       static pthread_once_t xeno_init_current_keys_once = PTHREAD_ONCE_INIT;
+       pthread_once(&xeno_init_current_keys_once, init_current_keys);
+}
diff --git a/lib/cobalt/init.c b/lib/cobalt/init.c
index 6743a06..d3e8e9f 100644
--- a/lib/cobalt/init.c
+++ b/lib/cobalt/init.c
@@ -154,8 +154,6 @@ void __init_cobalt_interface(void)
        struct sigaction sa;
        const char *p;
 
-       rt_print_auto_init(1);
-
        muxid = bind_interface();
        if (muxid < 0) {
                report_error("interface unavailable");
@@ -223,4 +221,6 @@ no_shadow:
                             (int) sizeof(struct __shadow_mutex));
                exit(EXIT_FAILURE);
        }
+
+       cobalt_print_init();
 }
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index 6324622..a939a2b 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -71,4 +71,8 @@ int cobalt_event_inquire(cobalt_event_t *event,
 
 int cobalt_event_destroy(cobalt_event_t *event);
 
+void cobalt_print_init(void);
+
+void cobalt_print_exit(void);
+
 #endif /* XENO_COBALT_INTERNAL_H */
diff --git a/lib/cobalt/printf.c b/lib/cobalt/printf.c
index f9f2ecb..c4e524f 100644
--- a/lib/cobalt/printf.c
+++ b/lib/cobalt/printf.c
@@ -32,6 +32,7 @@
 #include <asm/xenomai/atomic.h>        /* For atomic_cmpxchg */
 #include <asm-generic/stack.h>
 #include <asm-generic/current.h>
+#include "internal.h"
 
 #define RT_PRINT_BUFFER_ENV            "RT_PRINT_BUFFER"
 #define RT_PRINT_DEFAULT_BUFFER                16*1024
@@ -666,7 +667,7 @@ static void forked_child_init(void)
        spawn_printer_thread();
 }
 
-static __attribute__ ((constructor)) void __rt_print_init(void)
+void cobalt_print_init(void)
 {
        const char *value_str;
        unsigned long long period;
@@ -740,7 +741,7 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
                        xnarch_atomic_set(&pool_bitmap[i], ~0UL);
                if (buffers_count % BITS_PER_LONG)
                        xnarch_atomic_set(&pool_bitmap[i],
-                                         (1UL << (buffers_count % 
BITS_PER_LONG))                                        - 1);
+                                         (1UL << (buffers_count % 
BITS_PER_LONG)) - 1);
 
                for (i = 0; i < buffers_count; i++) {
                        struct print_buffer *buffer =
@@ -761,9 +762,11 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
 
        spawn_printer_thread();
        pthread_atfork(NULL, NULL, forked_child_init);
+
+       rt_print_auto_init(1);
 }
 
-static __attribute__ ((destructor)) void __rt_print_exit(void)
+void cobalt_print_exit(void)
 {
        if (buffers) {
                /* Flush the buffers. Do not call print_buffers here
diff --git a/lib/cobalt/sem_heap.c b/lib/cobalt/sem_heap.c
index 5916732..3315387 100644
--- a/lib/cobalt/sem_heap.c
+++ b/lib/cobalt/sem_heap.c
@@ -14,6 +14,7 @@
 #include <asm/xenomai/syscall.h>
 #include <asm-generic/sem_heap.h>
 #include <asm-generic/current.h>
+#include "internal.h"
 
 #define PRIVATE 0
 #define SHARED 1


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to