POSIX scheduling and priority question

Gempeler Stefan Stefan.Gempeler at nanotronic.ch
Tue Apr 22 12:53:57 UTC 2014


Hi 

 

I have a problem which has already been discussed here, but I couldn't
find an answer or solution for it.

We have a time critical process which has to respond in very little time
(<50us). A hardware interrupt will post only a semaphore which has to
start the waiting processing code. 

But during this time, some time consuming but not time critical
functions can run (compression etc.).

I expected that giving the correct priorities to the threads should take
care of it, but the result looks exactly as if it would run on a
cooperatively scheduled system:

No interruption of the low priority tasks after the semaphore has been
posted.

 

Below there's a small test program which demonstrates the effect. BUT:
when the line 1) is uncommented, usleep(1) it works.

 

System: Running on a virtex4 PowerPC, RTEMS Version 4.10.99.0, commit
39a6e4ea690d265233a68efe993cb107d1d864ca

Configured with:

CPU=powerpc

BSP=virtex

configure --target=${CPU}-rtems4.11 --enable-rtemsbsp=${BSP} \

                  --prefix=/mnt/extended/ppc_rtems/bsp-install \

                  --disable-cxx --enable-posix --disable-networking
--disable-tests ...

 

Test program:

 

************************************************************************
************

//----------------------------------------------------------------------
---------------------------------------------

// minimal system for testing

//----------------------------------------------------------------------
---------------------------------------------

/* configuration information */

#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER

#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER

#define CONFIGURE_MICROSECONDS_PER_TICK
1000

#define CONFIGURE_TICKS_PER_TIMESLICE                    5

 

#define CONFIGURE_MAXIMUM_POSIX_THREADS
3

#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES
1

 

#define CONFIGURE_POSIX_INIT_THREAD_TABLE

#define CONFIGURE_INIT

 

#include <rtems/confdefs.h>

 

//----------------------------------------------------------------------
---------------------------------------------

#include <bsp.h>

#include <assert.h>

#include <semaphore.h>

 

 

void* test_full_thread( void* arg );

void* test_wait_thread( void* arg );

 

#include <pthread.h>

 

sem_t   test_semaphore;

 

//----------------------------------------------------------------------
---------------------------------------------

void* test_full_thread( void* arg )

{

                int          i=0;

                int counter = 0;

 

                printk( "-> Full busy thread started\n" );

                while(1)

                {

                               if( i>4000000 )

                               {

                                               // posting the semaphore
for sys_scheduler_test_wait_task()

                                               printk( "\nFULL posting
%d...", counter );

                                               counter++;

                                               sem_post( &test_semaphore
);

                                               i=0;

//                                           usleep(1);
// 1) when usleep is called, the task switch works

                               }

                               i++;

                }

                return 0;

}

 

//----------------------------------------------------------------------
---------------------------------------------

void* test_wait_thread( void* arg )

{

                int          counter=0;

 

                printk( "-> Wait thread started\n" );

                while(1)

                {

                               // waits for
sys_scheduler_test_full_task() posting the semaphore

                               sem_wait( &test_semaphore );

                               printk( "WAIT received %d  ", counter );

                               counter++;

                }

                return 0;

}

 

//----------------------------------------------------------------------
---------------------------------------------

// Main startup routine

void *POSIX_Init( void *argument )

{

#define SCHEDULER_POLICY                     (SCHED_RR)

 

                pthread_t           thread_full;

                pthread_t           thread_wait;

 

                pthread_attr_t                test_attr;

                struct sched_param       test_param;

 

                assert( sem_init( &test_semaphore, 0, 0 )==0 );

 

                // get default attributes

                pthread_attr_init( &test_attr );

 

                // store parameters

                pthread_attr_getschedparam( &test_attr, &test_param );

 

                // set policy

                pthread_attr_setschedpolicy( &test_attr,
SCHEDULER_POLICY );

 

                printk( "\n\n========= STARTING ============  \n" );

 

                // start the waiting task, highest priority

                test_param.sched_priority = sched_get_priority_max(
SCHEDULER_POLICY );

                assert( pthread_attr_setschedparam( &test_attr,
&test_param )==0 );

                pthread_create( &thread_wait,              &test_attr,
test_wait_thread,          0 );

 

                // start the full running task, lowest priority

                test_param.sched_priority = sched_get_priority_min(
SCHEDULER_POLICY );

                assert( pthread_attr_setschedparam( &test_attr,
&test_param )==0 );

                pthread_create( &thread_full, &test_attr,
test_full_thread,            0 );

 

                while(1)

                {

                               sleep( 1 );

                }

                exit( 0 );

}

 

//----------------------------------------------------------------------
---------------------------------------------

//----------------------------------------------------------------------
---------------------------------------------

 

************************************************************************
************

Output without usleep (the higher priority thread has never been
called):

 

========= STARTING ============

-> Wait thread started

-> Full busy thread started

FULL posting 0...

FULL posting 1...

FULL posting 2...

FULL posting 3... 

 

************************************************************************
************

Output with usleep (works as expected):

 

========= STARTING ============ 

-> Wait thread started

-> Full busy thread started

FULL posting 0...WAIT received 0  

FULL posting 1...WAIT received 1  

FULL posting 2...WAIT received 2  

FULL posting 3...WAIT received 3  

 

************************************************************************
************

 

Compiling and running exactly the same code in an Ubuntu 32-bit system
works perfectly.

I also tried different settings (SCHED_FIFO, different priorities etc.),
but nothing helped.

 

Distributing usleeps in the time consuming code is not an option ;-)

 

Or would it be better to use the RTEMS task system? At the moment we use
POSIX for compatibility reasons, but it can be changed.

Not to handle the time critical interrupts in time is a show stopper for
our application.

 

Now my question: what am I doing wrong? 

 

Thank you!!

 

Kind regards

Stefan Gempeler

 

 

 

 

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/users/attachments/20140422/a0bf3d5a/attachment.html>


More information about the users mailing list