logo       

[RFC] shadow threads with prio 0 / SCHED_NORMAL: msg#00160

linux.real-time.xenomai.devel

Subject: [RFC] shadow threads with prio 0 / SCHED_NORMAL

Hi,

this is an experimental hack to open the non-rt priority levels of Linux
to Xenomai shadow threads, i.e. allow shadows to be scheduled under
SCHED_NORMAL when in secondary mode. The scenario are typical borderline
threads between RT and non-RT: they share a critical code path with RT
threads, maybe mutex protected, but they are mostly time-sharing threads
which do not need SCHED_FIFO for this.

The patch (be careful, quick-hack!) addresses the prio level 0 in the
ipipe patch, the nucleus/shadow subsystem, and the native skin. A quick
test with the attached demo showed the expected behaviour so far: no
lock-up during busy-waiting in secondary mode, prio-boost when holding
the lock (visible via /proc/xenomai/sched), no obvious side effects.

Any comments? Does this break other things in a subtle way?

Jan
Index: linux-2.6.15.3/kernel/sched.c
===================================================================
--- linux-2.6.15.3.orig/kernel/sched.c 2006-04-19 11:07:51.000000000 +0200
+++ linux-2.6.15.3/kernel/sched.c 2006-04-19 23:14:43.000000000 +0200
@@ -5779,7 +5779,7 @@ int ipipe_setscheduler_root (struct task
runqueue_t *rq;
int oldprio;

- if (prio < 1 || prio > MAX_RT_PRIO-1)
+ if (prio < 0 || prio > MAX_RT_PRIO-1)
return -EINVAL;

rq = task_rq_lock(p, &flags);
Index: include/nucleus/core.h
===================================================================
--- include/nucleus/core.h (Revision 956)
+++ include/nucleus/core.h (Arbeitskopie)
@@ -38,7 +38,7 @@
#define XNCORE_NR_PRIO (XNCORE_MAX_PRIO - XNCORE_MIN_PRIO + 2)

/* Priority sub-range used by core APIs. */
-#define XNCORE_LOW_PRIO 1
+#define XNCORE_LOW_PRIO 0
#define XNCORE_HIGH_PRIO 99

/* Priority of IRQ servers in user-space. */
Index: src/skins/native/task.c
===================================================================
--- src/skins/native/task.c (Revision 956)
+++ src/skins/native/task.c (Arbeitskopie)
@@ -56,8 +56,10 @@ static void *rt_task_trampoline (void *c
long err;

/* Ok, this looks like weird, but we need this. */
- param.sched_priority = sched_get_priority_max(SCHED_FIFO);
- pthread_setschedparam(pthread_self(),SCHED_FIFO,&param);
+ if (iargs->prio > 0) {
+ param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ pthread_setschedparam(pthread_self(),SCHED_FIFO,&param);
+ }

/* rt_task_delete requires asynchronous cancellation */
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
@@ -132,8 +134,10 @@ int rt_task_create (RT_TASK *task,
pthread_attr_setstacksize(&thattr,stksize);
if (!(mode & T_JOINABLE))
pthread_attr_setdetachstate(&thattr,PTHREAD_CREATE_DETACHED);
- pthread_attr_setschedpolicy(&thattr,SCHED_FIFO);
- param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ if (prio > 0) {
+ pthread_attr_setschedpolicy(&thattr,SCHED_FIFO);
+ param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ }
pthread_attr_setschedparam(&thattr,&param);

err = pthread_create(&thid,&thattr,&rt_task_trampoline,&iargs);
Index: ksrc/nucleus/shadow.c
===================================================================
--- ksrc/nucleus/shadow.c (Revision 956)
+++ ksrc/nucleus/shadow.c (Arbeitskopie)
@@ -120,7 +120,7 @@ static inline void request_syscall_resta
static inline void set_linux_task_priority (struct task_struct *p, int prio)

{
- if (rthal_setsched_root(p,SCHED_FIFO,prio) < 0)
+ if (rthal_setsched_root(p,prio ? SCHED_FIFO : SCHED_NORMAL,prio) < 0)
printk(KERN_WARNING "Xenomai: invalid Linux priority level: %d,
task=%s\n",prio,p->comm);
}

@@ -577,7 +577,7 @@ void xnshadow_relax (int notify)
xnthread_user_pid(thread));
#endif /* CONFIG_XENO_OPT_DEBUG */
cprio = thread->cprio < MAX_RT_PRIO ? thread->cprio : MAX_RT_PRIO-1;
- rthal_reenter_root(get_switch_lock_owner(),SCHED_FIFO,cprio ?: 1);
+ rthal_reenter_root(get_switch_lock_owner(),cprio ? SCHED_FIFO :
SCHED_NORMAL,cprio);

xnthread_inc_ssw(thread); /* Account for secondary mode switch. */

@@ -671,11 +671,13 @@ static int xnshadow_wait_completion (xnc
void xnshadow_exit (void)

{
-
rthal_reenter_root(get_switch_lock_owner(),SCHED_FIFO,current->rt_priority);
+ rthal_reenter_root(get_switch_lock_owner(),
+ current->rt_priority ? SCHED_FIFO : SCHED_NORMAL,
+ current->rt_priority);
do_exit(0);
}

-/*!
+/*!
* \fn int xnshadow_map(xnthread_t *thread, xncompletion_t __user
*u_completion)
* @internal
* \brief Create a shadow thread context.
@@ -762,7 +764,7 @@ int xnshadow_map (xnthread_t *thread,


xnarch_init_shadow_tcb(xnthread_archtcb(thread),thread,xnthread_name(thread));
prio = xnthread_base_priority(thread) < MAX_RT_PRIO ?
xnthread_base_priority(thread) : MAX_RT_PRIO-1;
- set_linux_task_priority(current,prio ?: 1);
+ set_linux_task_priority(current,prio);
xnshadow_thrptd(current) = thread;
xnpod_suspend_thread(thread,XNRELAX,XN_INFINITE,NULL);

@@ -919,7 +921,7 @@ void xnshadow_renice (xnthread_t *thread
range, since the core pod's priority scale is a superset of
Linux's priority scale. */
int prio = thread->cprio < MAX_RT_PRIO ? thread->cprio : MAX_RT_PRIO-1;
- schedule_linux_call(LO_RENICE_REQ,p,prio ?: 1);
+ schedule_linux_call(LO_RENICE_REQ,p,prio);
}

void xnshadow_suspend (xnthread_t *thread)
#include <native/task.h>
#include <native/mutex.h>
#include <native/timer.h>
#include <stdio.h>
#include <sys/mman.h>

RT_TASK task1, task2;
RT_MUTEX mutex;

void spin(long long time)
{
long long timeout = rt_timer_read() + time;

while (rt_timer_read() < timeout);
}

void func1(void *arg)
{
printf("switching to secondary\n");

spin(3000000000LL);

printf("back to primary\n");

rt_mutex_lock(&mutex, TM_INFINITE);
rt_task_sleep(3000000000LL);
spin(1000000000LL);

rt_mutex_unlock(&mutex);

printf("done with primary\n");

sleep(3);

spin(3000000000LL);
}

void func2(void *arg)
{
rt_task_sleep(3500000000LL);
rt_mutex_lock(&mutex, TM_INFINITE);
rt_mutex_unlock(&mutex);
}

int main()
{
mlockall(MCL_CURRENT|MCL_FUTURE);

rt_mutex_create(&mutex, NULL);

spin(3000000000LL);

printf("rt_task_spawn(task1) = %d\n",
rt_task_spawn(&task1, "mytask", 0, 0, T_JOINABLE, func1, NULL));
printf("rt_task_spawn(task2) = %d\n",
rt_task_spawn(&task2, "mytask2", 0, 10, T_JOINABLE, func2, NULL));

rt_task_join(&task1);
rt_task_join(&task2);
return 0;
}

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Xenomai-core mailing list
Xenomai-core@xxxxxxx
https://mail.gna.org/listinfo/xenomai-core
<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise