I created a small test app to exercise the logic behind a task
scheduler I’m trying to build under QNX. The paradigm I’m trying to
follow is:
-
Create a POSIX timer whose repeat interval is the
same as the rate of the fastest task -
Ensure that all the other tasks run at some integer multiple of
the fastest rate -
Spawn a thread for each task. Assign the fastest running task the
highest priority, the next-fastest task the next-highest priority,
etc. (i.e., make the priorities ‘rate monotonic’) -
Make the priority of the process that spawned the threads the maximum
the system will allow using sched_get_priority_max() and
sched_setparam() -
Arm the timer, then sit in a loop calling sigwaitinfo(), waiting
for the timer to go off -
When the timer does go off, call sem_post() to post a semaphore
shared between the ‘thread controller’ and each task thread that
needs to run
A short excerpt of the test code is appended to the end of this message.
The complete source can be found at http://da5id.dyndns.org/schedlr.c.
The test prog works, but the same approach is prone to deadlocks
in the ‘real’ application. I’m trying to figure out why. I can sort
of emulate the behavior of the real app by putting ‘usleep( 500000 )’
right after the sigwaitinfo() call. This causes the test prog to hang
and be unslayable. It also results in the following:
sin
Out of memory.
Can someone explain this behavior? I feel I must be doing something
wrong, but I can’t quite figure out what it is. (Note: the real app
doesn’t fail in exactly the same manner, but it’s very similar; I’m
hoping that understanding the test app will help me to fix the actual
app.)
TIA,
- Dave
.
.
/* 'thread controller loop */
frame_number = 0;
while( 1 ) {
/*
** Wait for the timer
*/
sigwaitinfo( &wait_for_these, &sinfo );
/* Uncomment to deadlock */
// usleep(500000);
/*
** Dispatch threads that need to run this tick
** (arbitrarily chose to have Thread1 run every frame, Thread2
** running every-other frame, Thread3 every third, etc.)
*/
for( i = 0; i < NUM_THREADS; ++i ) {
if( frame_number % (i+1) == 0 )
sem_post( &tdata_.synch );
}
if( ++frame_number >= NUM_THREADS ) frame_number = 0;
}
.
.
void* thread_code( void* arg )
{
thread_data_t* tdata = arg;
while( 1 ) {
sem_wait( &tdata.synch );
/* Do stuff */
…
}
}_