I have two threads, a producer and a consumer. The producer thread recives data from another program through a named pipe at different rates, and forwards it to a consumer thread through a queue. The scheduler policy is RR and the producer thread has higher priority than the consumer thread. I want the producer to signal that there is new data on the queue, and have the consumer wait until the producer blocks, which will happen when there is no data to read from the named pipe.
The main thread sets the priorities:
policy = SCHED_FIFO;
pthread_attr_init(&tattr);
pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setschedpolicy(&tattr, policy);
param.sched_priority = sched_get_priority_max(policy);
pthread_attr_setschedparam(&tattr, ¶m);
pthread_create(&tid[0], &tattr, producer, fifo);
param.sched_priority = sched_get_priority_min(policy);
pthread_attr_setschedparam(&tattr, ¶m);
pthread_create(&tid[1], &tattr, consumer, fifo);
The producer does this:
fd = open(pipe, O_RDONLY);
while((read(fd, buf, 1024))!=0){
val = atoi(buf);
if(val > SOMETHING){
do_something();
} else {
pthread_mutex_lock (fifo->mut);
while (fifo->full) {
pthread_cond_wait (fifo->notFull, fifo->mut);
}
queueAdd (fifo, val);
pthread_mutex_unlock (fifo->mut);
pthread_cond_signal (fifo->notEmpty);
}
}
The consumer:
while(TRUE){
pthread_mutex_lock (fifo->mut);
while (fifo->empty) {
pthread_cond_wait (fifo->notEmpty, fifo->mut);
}
queueDel (fifo, &d);
do_something_else(d);
pthread_mutex_unlock (fifo->mut);
pthread_cond_signal (fifo->notFull);
}
After the signaling, the lower priority thread takes over. What am I doing wrong?
Thanks in advance!
EDIT: Changed the names of the threads. I had changed the names when posting it here, because my code is in spanish and the function names are something other than producer consumer, and made a mistake. But unluckily it's not that simple.
What I mean by 'takes over' is that the consumer continues execution. What I want is for it to start if and only if the producer thread blocks or exits.
Try to compile your project with optimizations DISABLED, because if you have them enabled right now and the variables fifo->empty and fifo->full are NOT declared volatile, then there is a big possibility that compiler optimizes some parts of your code in a way that you wouldn't like - the value is tested only once, and if it is true your code falls into an endless loop (the one with
pthread_cond_wait()
) that it will not leave no matter what, because compiler cannot see howpthread_cond_wait()
could alter it.If that's not it, then the behavior you describe is still not clear to me... Your example should work in the following way:
read()
) and puts one item into the queue (that's the whole free space), then blocks,How is the behavior you see different from what you expect? How can consumer "take over" when there's no data in the queue? It should stop "taking over" after the first (which is also the last) element taken from the queue and wait for producer to add anything.