Index: include/asm-ia64/system.h
===================================================================
--- include/asm-ia64/system.h	(revision 3786)
+++ include/asm-ia64/system.h	(working copy)
@@ -32,6 +32,8 @@
 #define XNARCH_THREAD_STACKSZ  KERNEL_STACK_SIZE

 #define xnarch_stack_size(tcb)  ((tcb)->stacksize)
+#define xnarch_stack_base(tcb)	((tcb)->stackbase)
+#define xnarch_stack_end(tcb)	((caddr_t)(tcb)->stackbase - (tcb)->stacksize)
 #define xnarch_user_task(tcb)   ((tcb)->user_task)
 #define xnarch_user_pid(tcb)    ((tcb)->user_task->pid)

Index: include/vxworks/syscall.h
===================================================================
--- include/vxworks/syscall.h	(revision 3786)
+++ include/vxworks/syscall.h	(working copy)
@@ -69,12 +69,14 @@
 #define __vxworks_wd_cancel        43
 #define __vxworks_wd_wait          44
 #define __vxworks_int_context      45
+#define __vxworks_taskinfo_get     46

 struct wind_arg_bulk {

     u_long a1;
     u_long a2;
     u_long a3;
+    u_long a4;
 };

 #ifdef __KERNEL__
Index: include/vxworks/vxworks.h
===================================================================
--- include/vxworks/vxworks.h	(revision 3786)
+++ include/vxworks/vxworks.h	(working copy)
@@ -127,6 +127,32 @@
     TASK_ID handle;
 } WIND_TCB_PLACEHOLDER;

+#define WIND_READY	0x0
+#define WIND_SUSPEND	0x1
+#define WIND_PEND	0x2
+#define WIND_DELAY	0x4
+#define WIND_DEAD	0x8
+#define WIND_STOP	0x10	/* Never reported. */
+
+typedef struct _TASK_DESC {
+
+	TASK_ID td_tid;
+	char    td_name[XNOBJECT_NAME_LEN];
+	int	td_priority;
+	int	td_status;
+	int	td_flags;
+	FUNCPTR	td_entry;
+	int	td_stacksize;
+	char	*td_pStackBase;
+	char	*td_pStackEnd;
+	char	*td_pExcStackBase;
+	char	*td_pExcStackEnd;
+	int	td_errorStatus;
+
+	unsigned long td_opaque;
+
+} TASK_DESC;
+
 typedef void (*wind_timer_t)(long);

 typedef struct wind_wd_utarget {
@@ -156,6 +182,9 @@
     int status;
     int prio;
     FUNCPTR entry;
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+    unsigned long ptid;
+#endif

     /* Xenomai specific: used by taskLib */

@@ -345,6 +374,9 @@

 BOOL taskIsSuspended (TASK_ID task_id);

+STATUS taskInfoGet(TASK_ID task_id,
+		   TASK_DESC *desc);
+
 STATUS semGive(SEM_ID sem_id);

 STATUS semTake(SEM_ID sem_id,
Index: include/asm-blackfin/system.h
===================================================================
--- include/asm-blackfin/system.h	(revision 3786)
+++ include/asm-blackfin/system.h	(working copy)
@@ -30,6 +30,8 @@
 #define XNARCH_THREAD_STACKSZ   8192

 #define xnarch_stack_size(tcb)  ((tcb)->stacksize)
+#define xnarch_stack_base(tcb)	((tcb)->stackbase)
+#define xnarch_stack_end(tcb)	((caddr_t)(tcb)->stackbase - (tcb)->stacksize)
 #define xnarch_user_task(tcb)   ((tcb)->user_task)
 #define xnarch_user_pid(tcb)    ((tcb)->user_task->pid)

Index: include/asm-powerpc/system.h
===================================================================
--- include/asm-powerpc/system.h	(revision 3786)
+++ include/asm-powerpc/system.h	(working copy)
@@ -35,6 +35,8 @@
 #endif

 #define xnarch_stack_size(tcb)  ((tcb)->stacksize)
+#define xnarch_stack_base(tcb)	((tcb)->stackbase)
+#define xnarch_stack_end(tcb)	((caddr_t)(tcb)->stackbase - (tcb)->stacksize)
 #define xnarch_user_task(tcb)   ((tcb)->user_task)
 #define xnarch_user_pid(tcb)    ((tcb)->user_task->pid)

Index: include/asm-arm/system.h
===================================================================
--- include/asm-arm/system.h	(revision 3786)
+++ include/asm-arm/system.h	(working copy)
@@ -32,6 +32,8 @@
 #define XNARCH_THREAD_STACKSZ   4096

 #define xnarch_stack_size(tcb)  ((tcb)->stacksize)
+#define xnarch_stack_base(tcb)	((tcb)->stackbase)
+#define xnarch_stack_end(tcb)	((caddr_t)(tcb)->stackbase - (tcb)->stacksize)
 #define xnarch_user_task(tcb)   ((tcb)->user_task)
 #define xnarch_user_pid(tcb)    ((tcb)->user_task->pid)

Index: include/asm-x86/system_64.h
===================================================================
--- include/asm-x86/system_64.h	(revision 3786)
+++ include/asm-x86/system_64.h	(working copy)
@@ -31,6 +31,8 @@
 #define XNARCH_THREAD_STACKSZ	4096

 #define xnarch_stack_size(tcb)  ((tcb)->stacksize)
+#define xnarch_stack_base(tcb)	((tcb)->stackbase)
+#define xnarch_stack_end(tcb)	((caddr_t)(tcb)->stackbase - (tcb)->stacksize)
 #define xnarch_fpu_ptr(tcb)     ((tcb)->fpup)
 #define xnarch_user_task(tcb)   ((tcb)->user_task)
 #define xnarch_user_pid(tcb)    ((tcb)->user_task->pid)
Index: include/asm-x86/system_32.h
===================================================================
--- include/asm-x86/system_32.h	(revision 3786)
+++ include/asm-x86/system_32.h	(working copy)
@@ -31,6 +31,8 @@
 #define XNARCH_THREAD_STACKSZ 4096

 #define xnarch_stack_size(tcb)  ((tcb)->stacksize)
+#define xnarch_stack_base(tcb)	((tcb)->stackbase)
+#define xnarch_stack_end(tcb)	((caddr_t)(tcb)->stackbase - (tcb)->stacksize)
 #define xnarch_fpu_ptr(tcb)     ((tcb)->fpup)
 #define xnarch_user_task(tcb)   ((tcb)->user_task)
 #define xnarch_user_pid(tcb)    ((tcb)->user_task->pid)
Index: include/asm-sim/system.h
===================================================================
--- include/asm-sim/system.h	(revision 3786)
+++ include/asm-sim/system.h	(working copy)
@@ -186,8 +186,10 @@
 }

 #define xnarch_stack_size(tcb)    0
-#define xnarch_fpu_ptr(tcb)       (NULL)
-#define xnarch_user_task(tcb)     (NULL)
+#define xnarch_stack_base(tcb)	  NULL
+#define xnarch_stack_end(tcb)	  NULL
+#define xnarch_fpu_ptr(tcb)       NULL
+#define xnarch_user_task(tcb)     NULL
 #define xnarch_user_pid(tcb)      0

 /* Under the MVM, preemption only occurs at the C-source line level,
Index: include/nucleus/thread.h
===================================================================
--- include/nucleus/thread.h	(revision 3786)
+++ include/nucleus/thread.h	(working copy)
@@ -277,6 +277,8 @@
 #define xnthread_pending_signals(thread)  ((thread)->signals)
 #define xnthread_timeout(thread)           xntimer_get_timeout(&(thread)->rtimer)
 #define xnthread_stack_size(thread)        xnarch_stack_size(xnthread_archtcb(thread))
+#define xnthread_stack_base(thread)        xnarch_stack_base(xnthread_archtcb(thread))
+#define xnthread_stack_end(thread)         xnarch_stack_end(xnthread_archtcb(thread))
 #define xnthread_handle(thread)            ((thread)->registry.handle)
 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
 #define xnthread_time_base(thread)         ((thread)->rtimer.base)
Index: src/skins/vxworks/taskInfo.c
===================================================================
--- src/skins/vxworks/taskInfo.c	(revision 3786)
+++ src/skins/vxworks/taskInfo.c	(working copy)
@@ -18,6 +18,7 @@

 #include <stdlib.h>
 #include <errno.h>
+#include <pthread.h>
 #include <nucleus/thread.h>	/* For status bits. */
 #include <vxworks/vxworks.h>

@@ -72,3 +73,40 @@

 	return !!(status & XNSUSP);
 }
+
+STATUS taskInfoGet(TASK_ID task_id, TASK_DESC *desc)
+{
+	pthread_attr_t attr;
+	int probe1, probe2;
+	size_t stacksize;
+	void *stackbase;
+	int err;
+
+	err = XENOMAI_SKINCALL2(__vxworks_muxid,
+				__vxworks_taskinfo_get, task_id, desc);
+	if (err) {
+		errno = abs(err);
+		return ERROR;
+	}
+
+	if (pthread_getattr_np((pthread_t)desc->td_opaque, &attr)) {
+		errno = S_objLib_OBJ_ID_ERROR;
+		return ERROR;
+	}
+
+	pthread_attr_getstack(&attr, &stackbase, &stacksize);
+	desc->td_stacksize = stacksize;
+	desc->td_pStackBase = stackbase;
+
+	if (&probe1 < &probe2)
+		/* Stack grows upward. */
+		desc->td_pStackEnd = (caddr_t)stackbase + stacksize;
+	else
+		/* Stack grows downward. */
+		desc->td_pStackEnd = (caddr_t)stackbase - stacksize;
+
+	desc->td_pExcStackBase = desc->td_pStackBase;
+	desc->td_pExcStackEnd = desc->td_pStackEnd;
+
+	return OK;
+}
Index: src/skins/vxworks/taskLib.c
===================================================================
--- src/skins/vxworks/taskLib.c	(revision 3786)
+++ src/skins/vxworks/taskLib.c	(working copy)
@@ -108,6 +108,7 @@
 	bulk.a1 = (u_long)iargs->name;
 	bulk.a2 = (u_long)iargs->prio;
 	bulk.a3 = (u_long)iargs->flags;
+	bulk.a4 = (u_long)pthread_self();

 	err = XENOMAI_SKINCALL3(__vxworks_muxid,
 				__vxworks_task_init,
Index: ksrc/skins/vxworks/syscall.c
===================================================================
--- ksrc/skins/vxworks/syscall.c	(revision 3786)
+++ ksrc/skins/vxworks/syscall.c	(working copy)
@@ -60,6 +60,7 @@
  * a1: const char *name;
  * a2: int prio;
  * a3: int flags;
+ * a4: pthread_self();
  * }
  */

@@ -120,6 +121,7 @@
 		     0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == OK) {
 		/* Let the skin discard the TCB memory upon exit. */
 		task->auto_delete = 1;
+		task->ptid = bulk.a4;
 		/* Copy back the registry handle to the ph struct. */
 		ph.handle = xnthread_handle(&task->threadbase);
 		__xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &ph,
@@ -693,6 +695,34 @@
 }

 /*
+ * int __wind_taskinfo_get(TASK_ID task_id, TASK_DESC *desc)
+ */
+static int __wind_taskinfo_get(struct task_struct *curr, struct pt_regs *regs)
+{
+	xnhandle_t handle = __xn_reg_arg1(regs);
+	TASK_DESC desc;
+	WIND_TCB *pTcb;
+	int err;
+
+	if (!__xn_access_ok
+	    (curr, VERIFY_WRITE, __xn_reg_arg2(regs), sizeof(desc)))
+		return -EFAULT;
+
+	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+
+	if (!pTcb)
+		return S_objLib_OBJ_ID_ERROR;
+
+	err = taskInfoGet((TASK_ID)pTcb, &desc);
+
+	if (!err)
+		__xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &desc,
+				  sizeof(desc));
+
+	return err;
+}
+
+/*
  * int __wind_errno_taskset(TASK_ID task_id, int errcode)
  */

@@ -1305,6 +1335,7 @@
 	[__vxworks_taskinfo_name] = {&__wind_taskinfo_name, __xn_exec_any},
 	[__vxworks_taskinfo_iddfl] = {&__wind_taskinfo_iddfl, __xn_exec_any},
 	[__vxworks_taskinfo_status] = {&__wind_taskinfo_status, __xn_exec_any},
+	[__vxworks_taskinfo_get] = {&__wind_taskinfo_get, __xn_exec_any},
 	[__vxworks_errno_taskset] = {&__wind_errno_taskset, __xn_exec_primary},
 	[__vxworks_errno_taskget] = {&__wind_errno_taskget, __xn_exec_primary},
 	[__vxworks_kernel_timeslice] =
Index: ksrc/skins/vxworks/taskInfo.c
===================================================================
--- ksrc/skins/vxworks/taskInfo.c	(revision 3786)
+++ ksrc/skins/vxworks/taskInfo.c	(working copy)
@@ -70,3 +70,63 @@

 	return testbits(xnthread_state_flags(&task->threadbase), XNSUSP);
 }
+
+STATUS taskInfoGet(TASK_ID task_id, TASK_DESC *desc)
+{
+	wind_task_t *task;
+	xnflags_t status;
+	spl_t s;
+
+	memset(desc, 0, sizeof(*desc));
+
+	xnlock_get_irqsave(&nklock, s);
+
+	check_OBJ_ID_ERROR(task_id, wind_task_t, task, WIND_TASK_MAGIC,
+			   goto error);
+
+	desc->td_tid = task_id;
+	xnobject_copy_name(desc->td_name, task->name);
+	desc->td_priority = wind_denormalized_prio(xnthread_current_priority
+						(&task->threadbase));
+
+	status = xnthread_state_flags(&task->threadbase);
+
+	if (xnpod_current_thread() == &task->threadbase || (status & XNREADY))
+		desc->td_status |= WIND_READY;
+	else if (status & XNDORMANT)
+		desc->td_status |= WIND_DEAD;
+	else {
+		if (status & XNSUSP)
+			desc->td_status |= WIND_SUSPEND;
+		if (status & XNPEND)
+			desc->td_status |= WIND_PEND;
+		if (status & XNDELAY)
+			desc->td_status |= WIND_DELAY;
+	}
+
+	desc->td_flags = task->flags;
+	desc->td_entry = task->entry;
+	desc->td_errorStatus = errnoOfTaskGet(task_id);
+
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+	if (status & XNSHADOW)
+		desc->td_opaque = task->ptid;
+		/* Userland should fill in the stack information. */
+	else
+#endif
+	{
+		desc->td_stacksize = xnthread_stack_size(&task->threadbase);
+		desc->td_pStackBase = (char *)xnthread_stack_base(&task->threadbase);
+		desc->td_pStackEnd = (char *)xnthread_stack_end(&task->threadbase);
+		desc->td_pExcStackBase = desc->td_pStackBase;
+		desc->td_pExcStackEnd = desc->td_pStackEnd;
+	}
+
+	xnlock_put_irqrestore(&nklock, s);
+
+	return OK;
+
+      error:
+	xnlock_put_irqrestore(&nklock, s);
+	return ERROR;
+}
Index: ksrc/skins/vxworks/module.c
===================================================================
--- ksrc/skins/vxworks/module.c	(revision 3786)
+++ ksrc/skins/vxworks/module.c	(working copy)
@@ -180,3 +180,4 @@
 EXPORT_SYMBOL(tickSet);
 EXPORT_SYMBOL(kernelTimeSlice);
 EXPORT_SYMBOL(kernelVersion);
+EXPORT_SYMBOL(taskInfoGet);
Index: ksrc/skins/vxworks/taskLib.c
===================================================================
--- ksrc/skins/vxworks/taskLib.c	(revision 3786)
+++ ksrc/skins/vxworks/taskLib.c	(working copy)
@@ -104,6 +104,8 @@
 	   neither. */

 #ifdef CONFIG_XENO_OPT_PERVASIVE
+ 	/* Caller should fill in this field whenever applicable. */
+ 	pTcb->ptid = 0;
 	if (flags & VX_SHADOW)
 		bflags |= XNSHADOW;
 #else /* !CONFIG_XENO_OPT_PERVASIVE */