[Xenomai-git] Philippe Gerum : cobalt/thread: rework thread cancellation handling

2013-11-05 Thread git repository hosting
Module: xenomai-forge
Branch: master
Commit: 42eb9298e88e422fbd124c3c5288d0aae25cce0a
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=42eb9298e88e422fbd124c3c5288d0aae25cce0a

Author: Philippe Gerum 
Date:   Fri Sep 13 18:52:34 2013 +0200

cobalt/thread: rework thread cancellation handling

With the rebasing of Xenomai kernel threads over the regular Linux
kthreads, we just can't guarantee synchronous deletion with
xnthread_thread_cancel() anymore. The killed thread will have to reach
a cancellation point later for the request to be actually fulfilled,
so that it may wrap up and exit gracefully linux-wise.

This is actually safer, because kernel threads may associate data to
the wait context before suspending, and certainly don't want to be
wiped out, without being allowed to do the wrap up, thus potentially
leaving stale data.

e.g. we should allow this:

list_add(&myself, &some_q);
xnthread_sleep_on()
list_del(&myself);
...
xnthread_test_cancel();

To this end, this patch removes all cancellation points from
xnthread_suspend(), expecting the Xenomai kernel threads to check for
pending termination requests via a call to xnthread_test_cancel(),
from within their work loop.

In addition, the xnthread_prepare/finish_wait() calls have been
replaced by the xnthread_prepare/complete_wait() pattern, to be used
as follows:

consumer:
xnthread_prepare_wait(&wc);
info = xnsynch_sleep_on(&sync, ...);
if (info) {
   /* process XNRMID, XNBREAK, XNTIMEO as usual. */
} else {
 /*
  * Resource obtained. In addition,
  * xnthread_wait_complete_p(&wc) may be called to make
  * sure xnthread_complete_wait(wc) was issued for the
  * wait context, assuming forced unblocks may happen,
  * independently of XNRMID|XNBREAK|XNTIMEO
  * (not recommended though).
  */
}

producer:
thread = xnsynch_wakeup_one_sleeper(&synch);
wc = xnthread_get_wait_context(thread);
/* Post resource. */
xnthread_complete_wait(wc);
xnsched_run();

---

 include/cobalt/kernel/shadow.h  |2 -
 include/cobalt/kernel/synch.h   |1 +
 include/cobalt/kernel/thread.h  |   24 --
 kernel/cobalt/posix/event.c |2 -
 kernel/cobalt/posix/mqueue.c|   15 +---
 kernel/cobalt/posix/signal.c|2 +-
 kernel/cobalt/posix/thread.c|   26 +-
 kernel/cobalt/posix/thread.h|2 -
 kernel/cobalt/sched.c   |   13 ++-
 kernel/cobalt/shadow.c  |   50 +--
 kernel/cobalt/thread.c  |  156 ++-
 kernel/drivers/ipc/bufp.c   |   20 -
 kernel/drivers/ipc/internal.h   |1 -
 kernel/drivers/testing/switchtest.c |7 +-
 14 files changed, 181 insertions(+), 140 deletions(-)

diff --git a/include/cobalt/kernel/shadow.h b/include/cobalt/kernel/shadow.h
index 4fdc221..6423332 100644
--- a/include/cobalt/kernel/shadow.h
+++ b/include/cobalt/kernel/shadow.h
@@ -55,8 +55,6 @@ static inline struct xnthread *xnshadow_current(void)
return ipipe_current_threadinfo()->thread;
 }
 
-#define xnshadow_current_p(thread) (xnshadow_current() == (thread))
-
 static inline struct xnthread *xnshadow_thread(struct task_struct *p)
 {
return ipipe_task_threadinfo(p)->thread;
diff --git a/include/cobalt/kernel/synch.h b/include/cobalt/kernel/synch.h
index ea93129..181e053 100644
--- a/include/cobalt/kernel/synch.h
+++ b/include/cobalt/kernel/synch.h
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define XNSYNCH_CLAIMED 0x10   /* Claimed by other thread(s) w/ PIP */
 
diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h
index feb4da2..3434536 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -28,8 +28,8 @@
 #include 
 #include 
 #include 
+#include 
 #include 
-#include 
 #include 
 #include 
 
@@ -37,7 +37,6 @@
 #define XNTHREAD_MODE_BITS(XNLOCK|XNRRB|XNTRAPSW)
 
 struct xnthread;
-struct xnsynch;
 struct xnsched;
 struct xnselector;
 struct xnsched_class;
@@ -58,7 +57,7 @@ struct xnthread_start_attr {
 };
 
 struct xnthread_wait_context {
-   /* anchor object */
+   int posted;
 };
 
 typedef struct xnthread {
@@ -169,6 +168,8 @@ typedef struct xnthread {
const char *exe_path;   /* Executable path */
u32 proghash;   /* Hash value for exe_path */
 #endif
+   /** Exit event for joining the thread. */
+   struct xnsynch join_synch;
 } xnthread_t;
 
 #define xnthread_name(thread)   ((thread)->name)
@@ -344,6 +345,18 @@ static inline void xnthread_test_cancel(void)
__xnthread_test_cancel(curr);
 }
 
+static inline
+void xnthread_complete_wait(struct xnthread_wait_context *wc)
+{
+   wc->posted = 1;
+}
+
+static inline
+int xnthread_wait_complete_p(struct xnthread_wait_context *wc)
+{
+  

[Xenomai-git] Philippe Gerum : cobalt/thread: rework thread cancellation handling

2013-10-03 Thread git repository hosting
Module: xenomai-forge
Branch: next
Commit: 42eb9298e88e422fbd124c3c5288d0aae25cce0a
URL:
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=42eb9298e88e422fbd124c3c5288d0aae25cce0a

Author: Philippe Gerum 
Date:   Fri Sep 13 18:52:34 2013 +0200

cobalt/thread: rework thread cancellation handling

With the rebasing of Xenomai kernel threads over the regular Linux
kthreads, we just can't guarantee synchronous deletion with
xnthread_thread_cancel() anymore. The killed thread will have to reach
a cancellation point later for the request to be actually fulfilled,
so that it may wrap up and exit gracefully linux-wise.

This is actually safer, because kernel threads may associate data to
the wait context before suspending, and certainly don't want to be
wiped out, without being allowed to do the wrap up, thus potentially
leaving stale data.

e.g. we should allow this:

list_add(&myself, &some_q);
xnthread_sleep_on()
list_del(&myself);
...
xnthread_test_cancel();

To this end, this patch removes all cancellation points from
xnthread_suspend(), expecting the Xenomai kernel threads to check for
pending termination requests via a call to xnthread_test_cancel(),
from within their work loop.

In addition, the xnthread_prepare/finish_wait() calls have been
replaced by the xnthread_prepare/complete_wait() pattern, to be used
as follows:

consumer:
xnthread_prepare_wait(&wc);
info = xnsynch_sleep_on(&sync, ...);
if (info) {
   /* process XNRMID, XNBREAK, XNTIMEO as usual. */
} else {
 /*
  * Resource obtained. In addition,
  * xnthread_wait_complete_p(&wc) may be called to make
  * sure xnthread_complete_wait(wc) was issued for the
  * wait context, assuming forced unblocks may happen,
  * independently of XNRMID|XNBREAK|XNTIMEO
  * (not recommended though).
  */
}

producer:
thread = xnsynch_wakeup_one_sleeper(&synch);
wc = xnthread_get_wait_context(thread);
/* Post resource. */
xnthread_complete_wait(wc);
xnsched_run();

---

 include/cobalt/kernel/shadow.h  |2 -
 include/cobalt/kernel/synch.h   |1 +
 include/cobalt/kernel/thread.h  |   24 --
 kernel/cobalt/posix/event.c |2 -
 kernel/cobalt/posix/mqueue.c|   15 +---
 kernel/cobalt/posix/signal.c|2 +-
 kernel/cobalt/posix/thread.c|   26 +-
 kernel/cobalt/posix/thread.h|2 -
 kernel/cobalt/sched.c   |   13 +++-
 kernel/cobalt/shadow.c  |   50 +--
 kernel/cobalt/thread.c  |  156 ++-
 kernel/drivers/ipc/bufp.c   |   20 -
 kernel/drivers/ipc/internal.h   |1 -
 kernel/drivers/testing/switchtest.c |7 +-
 14 files changed, 181 insertions(+), 140 deletions(-)

diff --git a/include/cobalt/kernel/shadow.h b/include/cobalt/kernel/shadow.h
index 4fdc221..6423332 100644
--- a/include/cobalt/kernel/shadow.h
+++ b/include/cobalt/kernel/shadow.h
@@ -55,8 +55,6 @@ static inline struct xnthread *xnshadow_current(void)
return ipipe_current_threadinfo()->thread;
 }
 
-#define xnshadow_current_p(thread) (xnshadow_current() == (thread))
-
 static inline struct xnthread *xnshadow_thread(struct task_struct *p)
 {
return ipipe_task_threadinfo(p)->thread;
diff --git a/include/cobalt/kernel/synch.h b/include/cobalt/kernel/synch.h
index ea93129..181e053 100644
--- a/include/cobalt/kernel/synch.h
+++ b/include/cobalt/kernel/synch.h
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define XNSYNCH_CLAIMED 0x10   /* Claimed by other thread(s) w/ PIP */
 
diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h
index feb4da2..3434536 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -28,8 +28,8 @@
 #include 
 #include 
 #include 
+#include 
 #include 
-#include 
 #include 
 #include 
 
@@ -37,7 +37,6 @@
 #define XNTHREAD_MODE_BITS(XNLOCK|XNRRB|XNTRAPSW)
 
 struct xnthread;
-struct xnsynch;
 struct xnsched;
 struct xnselector;
 struct xnsched_class;
@@ -58,7 +57,7 @@ struct xnthread_start_attr {
 };
 
 struct xnthread_wait_context {
-   /* anchor object */
+   int posted;
 };
 
 typedef struct xnthread {
@@ -169,6 +168,8 @@ typedef struct xnthread {
const char *exe_path;   /* Executable path */
u32 proghash;   /* Hash value for exe_path */
 #endif
+   /** Exit event for joining the thread. */
+   struct xnsynch join_synch;
 } xnthread_t;
 
 #define xnthread_name(thread)   ((thread)->name)
@@ -344,6 +345,18 @@ static inline void xnthread_test_cancel(void)
__xnthread_test_cancel(curr);
 }
 
+static inline
+void xnthread_complete_wait(struct xnthread_wait_context *wc)
+{
+   wc->posted = 1;
+}
+
+static inline
+int xnthread_wait_complete_p(struct xnthread_wait_context *wc)
+{
+