“David Gibbs” wrote:
There is no priority inversion…
“Rennie Allen” wrote:
You don’t have deadlock (at least not that I can see from the
data you provided).
:: SIGH :: I think I’m failing to get my point across due to imprecise
usage of terms. Here’s what I don’t understand… with the kbhit()
calls in place, I wind up with this after several minutes:
45067 1 sbin/devc-pty 10o RECEIVE 1
.
.
23605283 1 Test/Unix/sntest 63f RECEIVE 1
23605283 2 Test/Unix/sntest 62f REPLY 45067
23605283 3 Test/Unix/sntest 11f REPLY 45067
23605283 4 Test/Unix/sntest 11f REPLY 45067
23605283 5 Test/Unix/sntest 11f REPLY 45067
23605283 6 Test/Unix/sntest 11f CONDVAR 8092d90
23605283 7 Test/Unix/sntest 10f CONDVAR 8092d28
23605283 8 Test/Unix/sntest 10f CONDVAR 8092df8
My 63f thread (the dispatcher) is still running just fine, as are all
the threads blocked on the CONDVAR that the dispatcher signals. But the
threads where I have a kbhit() call (complete code for which is appended
below) are blocked waiting for devc-pty to reply to them.
I tried to ensure that my kbhit() routine would be non-blocking by
putting the terminal in non-canonical mode and setting c_cc[VTIME] to 0,
a trick I’ve used successfully with monolithic kernels; however, my 62f
thread is somehow managing to block on devc-pty, anyway. And the 10f
threads–and one of the 11f threads–are still iterating normally.
This, to me, is a ‘priority inversion’, because the 10/11f threads are
allowed to run while the 62f thread sits blocked, even though all it did
was a (supposedly) non-blocking read from stdin. It is also a
‘deadlock’ because the situation never resolves itself; all the threads
that are REPLY-blocked on devc-pty remain blocked forever.
Since this problem goes away completely if I refrain from calling my
kbhit() function from multiple threads, I feel there must be a very
simple explanation for this behavior. The kind responses from this
newsgroup have helped me figure out how to eliminate the problem, and
I’m very grateful for that!
But I’m still unsure of the real root
cause… why do these threads block forever on devc-pty?
I understand that the ‘read( STDIN_FILENO, &ch, 1 )’ line in kbhit()
must send a message to devc-pty, but I thought that QNX automatically
bumped a resource manager’s priority to that of the sender; thus, while
servicing the request from my 62f thread, devc-pty’s priority should be
62(??) How, then, does it come to have a priority of 10 when the app
locks up?
\
/* $Id: kbhit.c,v 1.2 2002/11/12 05:25:54 dwolfe Exp $ */
/*********************************************************************
** kbhit.c **
** Fallback implementation of the DOS kbhit() and getch() functions**
*********************************************************************/
#include <stdio.h>
#include <termios.h>
#include <term.h>
#include <unistd.h>
#include “kbhit.h”
static struct termios initial_settings, new_settings;
static int peek_character = -1;
/*********************************************************************
** init_terminal() - Must be called once to set terminal in non- **
** canonical mode… **
/
void init_terminal( void )
{
tcgetattr( 0, &initial_settings );
memcpy( &new_settings, &initial_settings, sizeof( new_settings ) );
new_settings.c_lflag &= ~ICANON;
new_settings.c_lflag &= ~ECHO;
new_settings.c_lflag &= ~ISIG;
new_settings.c_cc[VMIN] = 1;
new_settings.c_cc[VTIME] = 0;
tcsetattr( 0, TCSANOW, &new_settings );
}
/
** reset_terminal() - Called during teardown to return terminal to **
** its previous state **
*/
void reset_terminal( void )
{
tcsetattr( 0, TCSANOW, &initial_settings );
}
/
** kbhit() - Detects keypresses; returns 1 if a key has been **
** pressed, 0 otherwise… **
**********************************************************************/
int kbhit( void )
{
char ch;
int nread;
if ( peek_character != -1 )
return 1;
new_settings.c_cc[VMIN] = 0;
tcsetattr( 0, TCSANOW, &new_settings );
nread = read( STDIN_FILENO, &ch, 1 );
new_settings.c_cc[VMIN] = 1;
tcsetattr( 0, TCSANOW, &new_settings );
if ( nread == 1 ) {
peek_character = ch;
return 1;
}
return 0;
}
/*********************************************************************
** getch() - Gets a character from standard input; most often used **
** after kbhit() has detected a keypress… **
*********************************************************************/
int getch( void )
{
char ch;
if ( peek_character != -1 ) {
ch = peek_character;
peek_character = -1;
return ch;
}
read( STDIN_FILENO, &ch, 1 );
return ch;
}