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@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to