Reputation: 119
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 4
#define TCOUNT 5
#define COUNT_LIMIT 13
int done = 0;
int count = 0;
int thread_ids[4] = {0,1,2,3};
int thread_runtime[4] = {0,5,4,1};
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;
void *inc_count(void *t)
{
int i;
long my_id = (long)t;
long run_time = thread_runtime[my_id];
if (my_id==2 && done==0) {
for(i=0; i<5 ; i++) {
if (i==4) {
done = 1;
}
pthread_mutex_lock(&count_mutex);
count++;
if (count == COUNT_LIMIT) {
pthread_cond_signal(&count_threshold_cv);
printf("inc_count(): thread %ld, count = %d Threshold reached.\n",
my_id, count);
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id, count);
pthread_mutex_unlock(&count_mutex);
}
}
if (my_id==3 && done==1) {
for(i=0; i< 4 ; i++) {
if (i==3) {
done = 2;
}
pthread_mutex_lock(&count_mutex);
count++;
if (count == COUNT_LIMIT) {
pthread_cond_signal(&count_threshold_cv);
printf("inc_count(): thread %ld, count = %d Threshold reached.\n",
my_id, count);
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id, count);
pthread_mutex_unlock(&count_mutex);
}
}
if (my_id==4 && done==2) {
for(i=0; i<8; i++) {
pthread_mutex_lock(&count_mutex);
count++;
if (count == COUNT_LIMIT) {
pthread_cond_signal(&count_threshold_cv);
printf("inc_count(): thread %ld, count = %d Threshold reached.\n",
my_id, count);
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id, count);
pthread_mutex_unlock(&count_mutex);
}
}
pthread_exit(NULL);
}
void *watch_count(void *t)
{
long my_id = (long)t;
printf("Starting watch_count(): thread %ld\n", my_id);
pthread_mutex_lock(&count_mutex);
if (count<COUNT_LIMIT) {
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %ld Condition signal received.\n", my_id);
count += 125;
printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
int i, rc;
long t1=1, t2=2, t3=3, t4=4;
pthread_t threads[4];
pthread_attr_t attr;
pthread_mutex_init(&count_mutex, NULL);
pthread_cond_init (&count_threshold_cv, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, watch_count, (void *)t1);
pthread_create(&threads[1], &attr, inc_count, (void *)t2);
pthread_create(&threads[2], &attr, inc_count, (void *)t3);
pthread_create(&threads[3], &attr, inc_count, (void *)t4);
for (i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS);
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
pthread_exit(NULL);
}
So this code creates 4 threads. Thread 1 keeps track of the count value while the other 3 increment the count value. The run time is the number of times the thread will increment the count value. I have a done value that allows the first thread to increment the count value first until its run time is up.. so its like a First Come First Serve.
My question is: Is there a better way of implementing this? I have read about SCHED_FIFO or SCHED_RR. I guess I dont know how to implement them into this code or if it can be
Upvotes: 0
Views: 8066
Reputation: 84169
If I understand the question correctly you are trying to produce sort of a pipeline where the next thread picks up where the previous one stops. The cleanest solution in this case is to use binary semaphores.
Say you have four threads. Create four semaphores with initial values of {1, 0, 0, 0}
. Assign semaphore per thread and have each thread down
its semaphore upon start and up
the next semaphore (modulo number of threads) in the chain. Start all threads - the first acquires its semaphore immediately, does its work, other threads block on their semaphores. First thread finishes work, up
s the next semaphore, thus waking up the next thread, then loops to the beginning, etc. etc.
I think the real-time scheduling classes you mention have nothing to do with the problem at hand.
Some notes on your code:
done
here) have to be volatile
, so compiler does not optimize them out of the loops.pthread_cond_wait
in a loop where loop condition checks the thing you wait on. This is to avoid spurious wakeups.pthread_cond_signal
either outside of the lock, or as the very last thing before unlock. This is to avoid wasted wakeup/sleep cycles in the waiting threads - they wake up, find the mutex still locked, block (sleep) again.pthread
calls.Hope this helps.
Upvotes: 2
Reputation: 54325
SCHED_FIFO and SCHED_RR are real-time scheduling classes. They are not for use in ordinary code. You should be able to do most of anything you need using pthread mutexes.
Upvotes: 1