“Nnamdi Kohn” <nnamdi.kohn@tu-bs.de> wrote in message
news:bkuhu6$mfq$1@inn.qnx.com…
Hello,
I’d like to signal condition changes in an other way as it is described in
the “Getting Started” book from Rob Krten. In the book he uses the
following
order for the “producer” and the “consumer” of data:
consumer / producer:
while(1)
{
pthread_mutex_lock( &mutex );
while( !condition ) // while( condition )
{
pthread_cond_wait( &condvar, &mutex );
}
…
condition = 1; // condition = 0;
pthread_cond_signal( &condvar );
pthread_mutex_unlock( &mutex );
}
I’d like to use the following producer and consumer (you will notice the
missing pthread_mutex_lock and pthread_mutex_unlock and pthread_cond_wait
functions in the producer and the missing pthread_cond_signal in the
consumer):
producer (INTERRUPT called by hardware when new data present):
{
…
condition = 1;
pthread_cond_signal( &condvar );
}
Not sure what are you trying to achieve, but this is unsafe way to use
condvars. Your producer can signal the condvar when the consumer is not in
the position to receive it (that is, not sitting in the
pthread_condvar_wait). Such signal (note the word ‘signal’ here refers to
the specific meaning related to condvars, NOT to the Unix signals) will be
lost. If this is your deliberate choice, you might be ok, otherwise your
code might deadlock. This is the reason why you need to pass a mutex into
pthread_condvar_wait() and why you need to lock the mutex before signaling a
condvar - that way the call to pthread_condvar_signal() will block until the
mutex is unlocked (by entering into pthread_condvar_wait in another thread)
so you are not going to miss any signals.
consumer:
while(1)
{
pthread_mutex_lock( &mutex );
while( !condition )
{
pthread_cond_wait( &condvar, &mutex );
}
…
condition = 0;
pthread_mutex_unlock( &mutex );
}
Since you have removed the signaling part from the consumer, you do not need
mutex lock/unlock inside the loop - they are serving no purpose. The mutex
needs to be locked before you enter the loop. It will be unlocked implicitly
every time you enter into pthread_cond_wait() and locked implicitly again
just before you return from it.
You also need to check for the return code in the inner loop - the reason
why there is an inner loop at all is that pthread_condvar_wait (like most
other blocking functions) may be interrupted by an asynchronous Unix signal
(note the different meaning of the word ‘signal’ here) resulting in a
spurious wakeup. So if the errno is EINTR you should stay in the loop,
otherwise you are better off baling out with error - if the code failed with
a different errno it is likely to keep failing and you will have a runaway
thread.
When I run the system like this, QNX sometimes hangs. Do I always have to
use the full set of functions? Are there some restrictions that exclude
this
type of usage of these functions?
It is hard to say what exactly you need unless you say what you’re trying to
achieve. If you really have a producer passing some data to a consumer, you
need to synchronize them both ways - the consumer needs to know when there’s
new piece of data to consume (assuming the data is in some global buffer)
and the producer needs to know when it can put a new piece of data into that
buffer (i.e., whether or not the consumer has already consumed the previous
piece). That is why both producer and consumer signal each other. I am
speculating, but with code like that you could be failing to actually
syncrhonize read and write access to the buffer and that could incidentally
cause your system to hang (by stuffing the resulting garbage into some
sensitive place). It is even more likely that your code will hang (and if it
runs on high priority that will look like a system hang).
Some good book explaining POSIX synchronisation concepts would help a lot.
– igor