With this patch applied, the Xenomai skin libraries are able to obtain
the execution mode the current thread without issuing a syscall. The
kernel-user interface looks as follows:
- On thread creation (which triggers xnshadow_map), user space passes a
pointer to an unsigned long.
- Before going primary and after completing the switch to secondary
mode, the nucleus writes 0 or XNRELAX to that unsigned long. The mode
updates use __xn_put_user, so they are fail-safe (write errors are
ignored, only an initial access_wok check is reported back).
- User space can check its state by calling xeno_get_current_mode().
An optional light-weight version based on __thread is also provided.
Signed-off-by: Jan Kiszka <[EMAIL PROTECTED]>
---
include/asm-generic/bits/bind.h| 29 +
include/asm-generic/bits/current.h | 20
include/native/syscall.h |1 +
include/nucleus/shadow.h |3 ++-
include/nucleus/thread.h |4
include/psos+/syscall.h|8
include/vrtx/syscall.h |1 +
include/vxworks/syscall.h |1 +
ksrc/nucleus/shadow.c | 22 --
ksrc/skins/native/syscall.c|3 ++-
ksrc/skins/posix/syscall.c | 14 +-
ksrc/skins/psos+/syscall.c | 34 +-
ksrc/skins/uitron/syscall.c|8 ++--
ksrc/skins/vrtx/syscall.c |4 +++-
ksrc/skins/vxworks/syscall.c |4 +++-
src/skins/native/task.c| 10 ++
src/skins/posix/thread.c | 33 +++--
src/skins/psos+/task.c | 16 +---
src/skins/uitron/task.c| 11 +--
src/skins/vrtx/task.c |6 ++
src/skins/vxworks/taskLib.c|6 ++
21 files changed, 201 insertions(+), 37 deletions(-)
Index: b/include/native/syscall.h
===
--- a/include/native/syscall.h
+++ b/include/native/syscall.h
@@ -134,6 +134,7 @@ struct rt_arg_bulk {
u_long a3;
u_long a4;
u_long a5;
+ u_long a6;
};
#ifdef __KERNEL__
Index: b/include/nucleus/shadow.h
===
--- a/include/nucleus/shadow.h
+++ b/include/nucleus/shadow.h
@@ -69,7 +69,8 @@ void xnshadow_grab_events(void);
void xnshadow_release_events(void);
int xnshadow_map(struct xnthread *thread,
-xncompletion_t __user *u_completion);
+xncompletion_t __user *u_completion,
+unsigned long __user *u_mode);
void xnshadow_unmap(struct xnthread *thread);
Index: b/include/nucleus/thread.h
===
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -248,6 +248,10 @@ typedef struct xnthread {
void *cookie; /* Cookie to pass to the entry routine */
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+ unsigned long __user *u_mode; /* Thread mode variable in userland. */
+#endif /* CONFIG_XENO_OPT_PERVASIVE */
+
XNARCH_DECL_DISPLAY_CONTEXT();
} xnthread_t;
Index: b/ksrc/nucleus/shadow.c
===
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1079,6 +1079,8 @@ redo:
/* Grab the request token. */
return -ERESTARTSYS;
+ __xn_put_user(0, thread->u_mode);
+
preempt_disable();
/* Assume that we might have been migrated while waiting for
@@ -1250,6 +1252,8 @@ void xnshadow_relax(int notify)
/* "current" is now running into the Linux domain on behalf of the
root thread. */
+ __xn_put_user(XNRELAX, thread->u_mode);
+
trace_mark(xn_nucleus_shadow_relaxed,
"thread %p thread_name %s comm %s",
thread, xnthread_name(thread), current->comm);
@@ -1264,7 +1268,9 @@ void xnshadow_exit(void)
}
/*!
- * \fn int xnshadow_map(xnthread_t *thread, xncompletion_t __user
*u_completion)
+ * \fn int xnshadow_map(xnthread_t *thread,
+ * xncompletion_t __user *u_completion,
+ * unsigned long __user *u_mode)
* @internal
* \brief Create a shadow thread context.
*
@@ -1288,6 +1294,11 @@ void xnshadow_exit(void)
* immediately started and "current" immediately resumes in the Xenomai
* domain from this service.
*
+ * @param: u_mode is the address of a mode variable in user space that
+ * will reflect the current thread mode (primary or secondary). The
+ * nucleus will try to update the variable before switching to secondary
+ * or after switching from primary mode.
+ *
* @return 0 is returned on success. Otherwise:
*
* - -ERESTARTSYS is returned if the current Linux task has received a
@@ -1313,7 +1324,8 @@ void xn