HELP: Deadlocks in semaphore-based thread dispatcher

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 */

}

}_

Who, me, talk to myself? :wink:

“David Wolfe” <da5id@LUVSPAMwolfe.name> wrote in message
news:anfdds$ki9$1@inn.qnx.com

I created a small test app to exercise the logic behind a task
scheduler I’m trying to build under QNX…

The test prog works, but the same approach is prone to deadlocks
in the ‘real’ application. I’m trying to figure out why…

And I’m still very curious. But I did discover that if I alter the
program to use pulses instead of signals, it does not hang and do:

sin

Out of memory.

Can someone explain this behavior?

The invitation is still open. Any takers? :wink: The original and modified
programs–omitted due to length–are at:
http://da5id.dyndns.org/schedlr.c.
http://da5id.dyndns.org/schedlr_pulse.c.

Note that schedlr_pulse.c still uses semaphores for dispatching the
threads; I only changed the notification mechanism for the timer. I’m
suddenly nervous about using semaphores in my application. I don’t feel
that the test app (schedlr.c) should have behaved the way it did. It
makes me wonder if I’m going to be sorry later if I don’t use
MsgSend/Receive instead of semaphores, which (like signals) aren’t the
‘native QNX’ way of doing things.

Any advice/anecdotes appreciated…