While loop synchronization - c

I am working on a project with a user defined number of threads I am using 7 at the moment. I have a while loop that runs in each thread but I need all of the threads to wait for each other at the end of the while loop. The tricky thing is that some of the threads do not all end on the same number of times through the loop.
void *entryFunc(void *param)
{
int *i = (int *)param;
int nextPrime;
int p = latestPrime;
while(latestPrime < testLim)
{
sem_wait(&sem);
nextPrime = findNextPrime(latestPrime);
if(nextPrime != -1)
{
latestPrime = nextPrime;
p = latestPrime;
}
else
{
sem_post(&sem);
break;
}
sem_post(&sem);
if(p < 46341)
{
incrementNotPrimes(p);
}
/*
sem_wait(&sem2);
doneCount++;
sem_post(&sem2);
while(go != 1);
sem_wait(&sem2);
doneCount--;
//sem_post(&sem3);
sem_post(&sem2);
*/
}
return NULL;
}
where the chunk of code is commented out is part of my last attempt at solving this problem. That is where the functions all need to wait for each other. I have a feeling I am missing something simple.

If your problem is that on each thread, the while loop has a different numbers of iterations and some threads never reach the synchronization point after exiting the loop, you could use a barrier. Check here for an example.
However you need to decrease the number of threads at the barrier after you exit each thread. Waiting at the barrier will end after count number of threads reached that point.
So you need to update the barrier object each time a thread finishes. And make sure you do this atomically.

As I mentioned in the comments, you should use a barrier instead of a semaphore for this kind of situation, as it should be simpler to implement (barriers have been designed exactly to solve that problem). However, you may still use a semaphore with a little bit of arithmetic
arithmetic: your goal is to have all thread execute the same code path, but somehow the last thread to finish its task should wake all the other threads up. One way to achieve that is to have at the end of the function an atomic counter which each thread would decrement, and if the counter reaches 0, the thread simply calls as many time sem_post as necessary to release all the waiting threads, instead of issuing a sem_wait as the others.
A second method, this time using only a semaphore, is also possible. Since we cannot differentiate the last thread for the others, all the threads must do the same operations with the semaphore, ie try to release everyone, but also wait for the last one. So the idea is to initialize the semaphore to (1-n)*(n+1), so that each of the n-1 first threads would fail at waking up their friends with n+1 calls to sem_post, but still work toward getting the semaphore at exactly 0. Then the last thread would do the same, pushing the semaphore value to n+1, thus releasing the locked threads, and leaving room for it to also perform its sem_wait and be released immediately.
void *entryFunc(void *param)
{
int *i = (int *)param;
int nextPrime;
int p = latestPrime, j;
while(latestPrime < testLim){
nextPrime = findNextPrime(latestPrime);
if(nextPrime != -1)
{
latestPrime = nextPrime;
p = latestPrime;
}
if(p < 46341)
{
incrementNotPrimes(p);
}
}
for (j=0;j<=THREAD_COUNT;j++)
sem_post(&sem);
sem_wait(&sem);
return NULL;
}
The problem with this approach is that it doesn't deal with how the semaphore should be reset in between uses (if your program needs to repeat this mechanism, it will need to reset the semaphore value, since it will end up being 1 after this code has been executed successfully).

Related

to interrupt a sleeping thread when main thread is to exit

I have a main thread which create child threads to do various task. There is a child thread which is tasked to report on the status every 100s
My current mechanism of stopping the thread is to observe a global boolean. Somewhat like this
Child thread
void* ReportThread(bool* operation)
{
while(*operation)
{
// do its reporting task
// ........
int counter = 0;
while( counter < 100 && operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
sleepCounter += 1;
}
}
}
Parent (Main) Thread:
bool operation = false;
int main(){
pthread_t tid;
err = pthread_create(&tid), NULL, &ReportThread, &operation);
printf("Please input esc to end operation \n");
while ((ch = getchar()) != 27);
operation =true;
pthread_join(tid,NULL);
return 0;
}
The problem:
It seem that using sleep(n). The number of seconds seem very inconsistent. When the program is stopped, this thread takes a while maybe 10 second to actually stop
Is there a way to interrupt a thread to sleep? I heard you could use signal. I am coding in linux
Can I just simply just use a pthread_cancel(tid) instead of pthread_join(tid)?
Regards
This part
while( counter < 100 || operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
sleepCounter += 1;
}
is wrong.
First I assume that sleepCounter += 1; is really a typo and that it should be:
while( counter < 100 || operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
counter += 1;
}
Then the problem is that even if operation is set to false by some other thread, the while will not finish until counter reach 100.
The code should be
while( counter < 100 && operation )
{
// let it sleep for 1 seconds and wake up to check
sleep(1);
counter += 1;
}
Further, in main you never set operation to false. Another typo?
You don't need two while loops. And if you want to set a timer, use time functions for it, because sleep is a cancellation point and it is not guaranteed that sleep actually sleeps that amount of time.
Example:
void* ReportThread(void *args)
{
time_t start = time(NULL);
time_t now;
bool *operation = (bool*) args;
while (*operation) { //while active
now = time(NULL); //get current time
if (now - start >= 100) { //if the threshold is exceeded
start = now; //reset timer
//and probably do other stuff
}
sleep(1); //sleep for one second
}
return NULL;
}
The example above has a max lag of one second, that means if you set operation to false right at that moment when the thread entered the sleep state, you have to wait until sleep returns, only then it will recognize the modified state. The example also has the advantage, that you can easily modify the threshold value (since it depends on the 'real' time, instead of a counter and a non accurate sleep time).
Btw. the variable operation should be either an atomic boolean or protected by a mutex (since it is accessed from different threads).
To answer the questions of your problem:
should be answered by the example above
since i mentioned it before, sleep is a cancellation point, that means it gets interrupted if the process handles a signal (see man pthreads - section Cancellation points).
see man pthread_cancel - section Notes
On Linux, cancellation is implemented using signals. Under the NPTL threading implementation, the first real-time signal (i.e., signal 32) is used for this purpose. On LinuxThreads, the second real-time signal is used, if real-time signals are available, otherwise SIGUSR2 is used.
You cannot use pthread_cancel over pthread_join! You have to use pthread_join in either case (described in detail in the man page).
I don't know if this will fix all your problems, but it's a bit too much for a comment. One problem, your ReportThread function signature is wrong. It should be:
void* ReportThread(void* args);
And then in that function you need to do something like:
void* ReportThread(void* args)
{
bool* operation = (bool*)args;
while(*operation)
{
...
}
}
I'm not sure how it's working right now, but your compiler should at least be issuing a warning trying to convert a bool* type to a bool.
Also be aware of race conditions on operation

C - How to terminate all threads after one of them signals the main thread with a condition variable?

In my program the main thread starts multiple child threads, locks a mutex for a counter and then sleeps until the counter reaches N.
In an infinite for loop, the other threads do some work and they increase the counter in each iteration alternately. Once the counter == N one of them has to signal the main thread and all of the child threads have to end.
My problem is that I'm not sure when I should lock the counter mutex and make a signal in the thread function, because once the counter becomes N I managed to wake up the main thread and exit one of the child threads, but the other threads will keep on trying to work when they should all be terminating.
My question is, how can I check if counter == N but send a signal by only one of the threads, and the others just return without any signalling?
Can this be done by only locking the mutex once in each iteration, for the time of checking its value (== N)? If yes, how?
void *thread_function(void *arg) {
int *id = (int *) arg;
for (;;) {
pthread_mutex_lock(&mutex_counter);
counter++;
if (counter == N) {
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex_counter);
return NULL;
}
if (counter > N) {
pthread_mutex_unlock(&mutex_counter);
return NULL;
}
pthread_mutex_unlock(&mutex_counter);
sleep(random());
// do some work here
// ...
// finish work
}
The problem with above code is that, despite all threads terminating, they execute the loop one less iteration than needed because the counter is increased before the if clause (so counter will be N, but there were no N loops of work done).
However, if I put the counter to the end of the function, the threads will do more work than needed which messes up my program.
why you lock counter-mutex in main thread? Why you need to send signal from other treads to main? If you have only one global counter and all threads increasing it, you can just start in main thread all threads, remember their thread ids and then wait using while(counter<N); instruction. After all, just kill all threads with pthread_cancel.

Trying to understand pthread_cond_lock and pthread_cond_signal

So I'm trying to understand exactly how pthread_mutex_lock works.
My current understanding is that it unlocks the mutex and puts whatever thread is going though it to sleep. Sleep meaning that the thread is inactive and consuming no resources.
It then waits for a signal to go from asleep to blocked, meaning that the thread can no longer change any variables.
thread 1:
pthread_mutex_lock(&mutex);
while (!condition){
printf("Thread wating.\n");
pthread_cond_wait(&cond, &mutex);
printf("Thread awakened.\n");
fflush(stdout);
}
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condVar);
pthread_mutex_unlock(&mutex);
So basically in the sample above, the loop runs and runs and each iteration pthread_cond_wait checks if the condition of the loop is true. If it is then the cond_signal is sent and the thread is blocked so it can't manipulate any more data.
I'm really having trouble wrapping my head around this, I'd appreciate some input and feedback about how this works and whether or not I am beginning to understand this based on what I have above.
I've gone over this post but am still having trouble
First, a summary:
pthread_mutex_lock(&mutex):
If mutex is free, then this thread grabs it immediately.
If mutex is grabbed, then this thread waits until the mutex becomes free, and then grabs it.
pthread_mutex_trylock(&mutex):
If mutex is free, then this thread grabs it.
If mutex is grabbed, then the call returns immediately with EBUSY.
pthread_mutex_unlock(&mutex):
Releases mutex.
pthread_cond_signal(&cond):
Wake up one thread waiting on the condition variable cond.
pthread_cond_broadcast(&cond):
Wake up all threads waiting on the condition variable cond.
pthread_cond_wait(&cond, &mutex):
This must be called with mutex grabbed.
The calling thread will temporarily release mutex and wait on cond.
When cond is broadcast on, or signaled on and this thread happens to be the one woken up, then the calling thread will first re-grab the mutex, and then return from the call.
It is important to note that at all times, the calling thread either has mutex grabbed, or is waiting on cond. There is no interval in between.
Let's look at a practical, running example code. We'll create it along the lines of OP's code.
First, we'll use a structure to hold the parameters for each worker function. Since we'll want the mutex and the condition variable to be shared between threads, we'll use pointers.
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <pthread.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
/* Worker function work. */
struct work {
pthread_t thread_id;
pthread_mutex_t *lock; /* Pointer to the mutex to use */
pthread_cond_t *wait; /* Pointer to the condition variable to use */
volatile int *done; /* Pointer to the flag to check */
FILE *out; /* Stream to output to */
long id; /* Identity of this thread */
unsigned long count; /* Number of times this thread iterated. */
};
The thread worker function receives a pointer to the above structure. Each thread iterates the loop once, then waits on the condition variable. When woken up, if the done flag is still zero, the thread iterates the loop. Otherwise, the thread exits.
/* Example worker function. */
void *worker(void *workptr)
{
struct work *const work = workptr;
pthread_mutex_lock(work->lock);
/* Loop as long as *done == 0: */
while (!*(work->done)) {
/* *(work->lock) is ours at this point. */
/* This is a new iteration. */
work->count++;
/* Do the work. */
fprintf(work->out, "Thread %ld iteration %lu\n", work->id, work->count);
fflush(work->out);
/* Wait for wakeup. */
pthread_cond_wait(work->wait, work->lock);
}
/* *(work->lock) is still ours, but we've been told that all work is done already. */
/* Release the mutex and be done. */
pthread_mutex_unlock(work->lock);
return NULL;
}
To run the above, we'll need a main() as well:
#ifndef THREADS
#define THREADS 4
#endif
int main(void)
{
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t wait = PTHREAD_COND_INITIALIZER;
volatile int done = 0;
struct work w[THREADS];
char *line = NULL, *p;
size_t size = 0;
ssize_t len = 0;
unsigned long total;
pthread_attr_t attrs;
int i, err;
/* The worker functions require very little stack, but the default stack
size is huge. Limit that, to reduce the (virtual) memory use. */
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 2 * PTHREAD_STACK_MIN);
/* Grab the mutex so the threads will have to wait to grab it. */
pthread_mutex_lock(&lock);
/* Create THREADS worker threads. */
for (i = 0; i < THREADS; i++) {
/* All threads use the same mutex, condition variable, and done flag. */
w[i].lock = &lock;
w[i].wait = &wait;
w[i].done = &done;
/* All threads output to standard output. */
w[i].out = stdout;
/* The rest of the fields are thread-specific. */
w[i].id = i + 1;
w[i].count = 0;
err = pthread_create(&(w[i].thread_id), &attrs, worker, (void *)&(w[i]));
if (err) {
fprintf(stderr, "Cannot create thread %d of %d: %s.\n", i+1, THREADS, strerror(errno));
exit(EXIT_FAILURE); /* Exits the entire process, killing any other threads as well. */
}
}
fprintf(stderr, "The first character on each line controls the type of event:\n");
fprintf(stderr, " e, q exit\n");
fprintf(stderr, " s signal\n");
fprintf(stderr, " b broadcast\n");
fflush(stderr);
/* Let each thread grab the mutex now. */
pthread_mutex_unlock(&lock);
while (1) {
len = getline(&line, &size, stdin);
if (len < 1)
break;
/* Find the first character on the line, ignoring leading whitespace. */
p = line;
while ((p < line + len) && (*p == '\0' || *p == '\t' || *p == '\n' ||
*p == '\v' || *p == '\f' || *p == '\r' || *p == ' '))
p++;
/* Do the operation mentioned */
if (*p == 'e' || *p == 'E' || *p == 'q' || *p == 'Q')
break;
else
if (*p == 's' || *p == 'S')
pthread_cond_signal(&wait);
else
if (*p == 'b' || *p == 'B')
pthread_cond_broadcast(&wait);
}
/* It is time for the worker threads to be done. */
pthread_mutex_lock(&lock);
done = 1;
pthread_mutex_unlock(&lock);
/* To ensure all threads see the state of that flag,
we wake up all threads by broadcasting on the condition variable. */
pthread_cond_broadcast(&wait);
/* Reap all threds. */
for (i = 0; i < THREADS; i++)
pthread_join(w[i].thread_id, NULL);
/* Output the thread statistics. */
total = 0;
for (i = 0; i < THREADS; i++) {
total += w[i].count;
fprintf(stderr, "Thread %ld: %lu events.\n", w[i].id, w[i].count);
}
fprintf(stderr, "Total: %lu events.\n", total);
return EXIT_SUCCESS;
}
If you save the above as example.c, you can compile it to example using e.g. gcc -Wall -O2 example.c -lpthread -o example.
To get the correct intuitive grasp of the operations, run the example in a terminal, with the source code in a window next to it, and see how the execution progresses as you provide input.
You can even run commands like printf '%s\n' s s s b q | ./example to run a sequence of events in a quick succession, or printf 's\ns\ns\nb\nq\n' | ./example with even less time in between events.
After some experimentation, you'll hopefully find out that not all input events cause their respective action. This is because the exit event (q above) is not synchronous: it does not wait for all pending work to be done, but tells the threads to exit right then and there. That is why the number of events may vary even for the exact same input.
(Also, if you signal on the condition variable, and immediately broadcast on it, the threads tend to only get woken up once.)
You can mitigate that by delaying the exit, using e.g. (printf '%s\n' s s b s s s ; sleep 1 ; printf 'q\n' ) | ./example.
However, there are better ways. A condition variable is not suitable for countable events; it is really flag-like. A semaphore would work better, but then you should be careful to not overflow the semaphore; it can only be from 0 to SEM_VALUE_MAX, inclusive. (So, you could use a semaphore to represent the number of pending job, but probably not for the number of iterations done by each/all thread workers.) A queue for the work to do, in thread pool fashion, is the most common approach.
pthread_cond_wait() simply means that the current thread shall release the mutex and then waits on a condition. The trick here is that both happens atomically, so it cannot happen, that the thread has released the mutex and is not yet waiting on the condition or is already waiting on the condition and has not yet released the mutex. Either both has happened or none has happened.
pthread_cond_signal() simply wakes up any thread that is currently waiting on the signaled condition. The first thing the woken up thread will do is obtaining the mutex again, if it cannot obtain it (e.g. as the signaling thread is currently owning the mutex), it will block until it can. If multiple threads are waiting on the condition, pthread_cond_signal() just wakes up one of them, which one is not defined. If you want to wake up all the waiting threads, you must use pthread_cond_broadcast() instead; but of course they won't run at the same time as now each of them first requires to obtain the mutex and that will only be possible one after another.
pthread_cond_t has no state. If you signal a condition no thread is waiting for, then nothing will happen. It's not like this will set a flag internally and if later on some thread calls pthread_cond_wait(), it will be woken up immediately as there is a pending signal. pthread_cond_signal() only wakes up threads that are already waiting, that means these threads must have called pthread_cond_wait() prior to you calling pthread_cond_signal().
Here's some simple sample code. First a reader thread:
// === Thread 1 ===
// We want to process an item from a list.
// To make sure the list is not altered by one
// thread while another thread is accessing it,
// it is protected by a mutex.
pthread_mutex_lock(&listLock);
// Now nobody but us is allowed to access the list.
// But what if the list is empty?
while (list->count == 0) {
// As long as we hold the mutex, no other thread
// thread can add anything to the list. So we
// must release it. But we want to know as soon
// as another thread has changed it.
pthread_cond_wait(&listCondition, &listLock);
// When we get here, somebody has signaled the
// condition and we have the mutex again and
// thus are allowed to access the list. The list
// may however still be empty, as another thread
// may have already consumed the new item in case
// there are multiple readers and all are woken
// up, thus the while-loop. If the list is still
// empty, we just go back to sleep and wait again.
}
// If we get here, the list is not empty.
processListItem(list);
// Finally we release the mutex again.
pthread_mutex_unlock(&listLock);
And then a writer thread:
// === Thread 2 ===
// We want to add a new item to the list.
// To make sure that nobody is accessing the
// list while we do, we need to obtain the mutex.
pthread_mutex_lock(&listLock);
// Now nobody but us is allowed to access the list.
// Check if the list is empty.
bool listWasEmpty = (list->count == 0);
// We add our item.
addListItem(list, newItem);
// If the list was empty, one or even multiple
// threads may be waiting for us adding an item.
// So we should wake them up here.
if (listWasEmpty) {
// If any thread is waiting for that condition,
// wake it up as now there is an item to process.
pthread_cond_signal(&listCondition);
}
// Finally we must release the mutex again.
pthread_mutex_unlock(&listLock);
The code is written so that there can be any number of reader/writer threads. Signaling only if the list was empty (listWasEmpty) is just a performance optimization, the code would also work correctly if you always signal the condition after adding an item.

Reader/Writer implementation in C

I'm currently learning about concurrency at my University. In this context I have to implement the reader/writer problem in C, and I think I'm on the right track.
My thought on the problem is, that we need two locks rd_lock and wr_lock. When a writer thread wants to change our global variable, it tries to grab both locks, writes to the global and unlocks. When a reader wants to read the global, it checks if wr_lock is currently locked, and then reads the value, however one of the reader threads should grab the rd_lock, but the other readers should not care if rd_lock is locked.
I am not allowed to use the implementation already in the pthread library.
typedef struct counter_st {
int value;
} counter_t;
counter_t * counter;
pthread_t * threads;
int readers_tnum;
int writers_tnum;
pthread_mutex_t rd_lock;
pthread_mutex_t wr_lock;
void * reader_thread() {
while(true) {
pthread_mutex_lock(&rd_lock);
pthread_mutex_trylock(&wr_lock);
int value = counter->value;
printf("%d\n", value);
pthread_mutex_unlock(&rd_lock);
}
}
void * writer_thread() {
while(true) {
pthread_mutex_lock(&wr_lock);
pthread_mutex_lock(&rd_lock);
// TODO: increment value of counter->value here.
counter->value += 1;
pthread_mutex_unlock(&rd_lock);
pthread_mutex_unlock(&wr_lock);
}
}
int main(int argc, char **args) {
readers_tnum = atoi(args[1]);
writers_tnum = atoi(args[2]);
pthread_mutex_init(&rd_lock, 0);
pthread_mutex_init(&wr_lock, 0);
// Initialize our global variable
counter = malloc(sizeof(counter_t));
counter->value = 0;
pthread_t * threads = malloc((readers_tnum + writers_tnum) * sizeof(pthread_t));
int started_threads = 0;
// Spawn reader threads
for(int i = 0; i < readers_tnum; i++) {
int code = pthread_create(&threads[started_threads], NULL, reader_thread, NULL);
if (code != 0) {
printf("Could not spawn a thread.");
exit(-1);
} else {
started_threads++;
}
}
// Spawn writer threads
for(int i = 0; i < writers_tnum; i++) {
int code = pthread_create(&threads[started_threads], NULL, writer_thread, NULL);
if (code != 0) {
printf("Could not spawn a thread.");
exit(-1);
} else {
started_threads++;
}
}
}
Currently it just prints a lot of zeroes, when run with 1 reader and 1 writer, which means, that it never actually executes the code in the writer thread. I know that this is not going to work as intended with multiple readers, however I don't understand what is wrong, when running it with one of each.
Don't think of the locks as "reader lock" and "writer lock".
Because you need to allow multiple concurrent readers, readers cannot hold a mutex. (If they do, they are serialized; only one can hold a mutex at the same time.) They can take one for a short duration (before they begin the access, and after they end the access), to update state, but that's it.
Split the timeline for having a rwlock into three parts: "grab rwlock", "do work", "release rwlock".
For example, you could use one mutex, one condition variable, and a counter. The counter holds the number of active readers. The condition variable is signaled on by the last reader, and by writers just before they release the mutex, to wake up a waiting writer. The mutex protects both, and is held by writers for the whole duration of their write operation.
So, in pseudocode, you might have
Function rwlock_rdlock:
Take mutex
Increment counter
Release mutex
End Function
Function rwlock_rdunlock:
Take mutex
Decrement counter
If counter == 0, Then:
Signal_on cond
End If
Release mutex
End Function
Function rwlock_wrlock:
Take mutex
While counter > 0:
Wait_on cond
End Function
Function rwlock_unlock:
Signal_on cond
Release mutex
End Function
Remember that whenever you wait on a condition variable, the mutex is atomically released for the duration of the wait, and automatically grabbed when the thread wakes up. So, for waiting on a condition variable, a thread will have the mutex both before and after the wait, but not during the wait itself.
Now, the above approach is not the only one you might implement.
In particular, you might note that in the above scheme, there is a different "unlock" operation you must use, depending on whether you took a read or a write lock on the rwlock. In POSIX pthread_rwlock_t implementation, there is just one pthread_rwlock_unlock().
Whatever scheme you design, it is important to examine it whether it works right in all situations: a lone read-locker, a lone-write-locker, several read-lockers, several-write-lockers, a lone write-locker and one read-locker, a lone write-locker and several read-lockers, several write-lockers and a lone read-locker, and several read- and write-lockers.
For example, let's consider the case when there are several active readers, and a writer wants to write-lock the rwlock.
The writer grabs the mutex. It then notices that the counter is nonzero, so it starts waiting on the condition variable. When the last reader -- note how the order of the readers exiting does not matter, since a simple counter is used! -- unlocks its readlock on the rwlock, it signals on the condition variable, which wakes up the writer. The writer then grabs the mutex, sees the counter is zero, and proceeds to do its work. During that time, the mutex is held by the writer, so all new readers will block, until the writer releases the mutex. Because the writer will also signal on the condition variable when it releases the mutex, it is a race between other waiting writers and waiting readers, who gets to go next.

pthreads C program hangs at execution

I'm writing a program that performs gaussian elimination given an A and B matrix. I first grab divisor and multipliers, create pthreads which execute in gauss function which perform their operations on a single 'column'. Then I call main which generates new divisor and multipliers and passes back for another round of operations by the same threads. Using condition pthread vars to accomplish this.
The code hangs until I create a breakpoint which it then proceeds and finishes. Not sure what's holding it up. Could use some help.
#include <stdio.h>
#include <pthread.h>
//Need one mutex variable and two condition variables (one c var for
//communicating between threads, and one c var for communicating with main).
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t condM = PTHREAD_COND_INITIALIZER;
float arr[3][4] = {{2,-3,1, -22},{7,9,-3, 14},{6,7,2,91}};
float mults[3];
float divisor;
int num_items = 3;
void* gauss(void *mine)
{
int thread_count=0;
int x = *((int *)mine);
for(int i=0;i<num_items;i++)
{
/*do something*/
arr[i][x] = arr[i][x] / divisor;
for(int k=0;k<num_items;k++){
if(k!=i)
arr[k][x] -= mults[k] * arr[i][x];
}
/*lock || wait || signal*/
pthread_mutex_lock(&mut);
thread_count++;
if(thread_count < num_items)
pthread_cond_wait(&cond,&mut);
else
{
pthread_cond_signal(&condM);
pthread_cond_wait(&cond,&mut);
thread_count = 0;
}
pthread_mutex_unlock(&mut);
}
return NULL;
}
int main(int argc, const char * argv[]) {
int i, j;
pthread_t threadr[num_items+1]; /*thread id array */
int is[num_items+1];
printf("Test");
// /*input num items*/
// printf("input the number of items ");
// scanf("%d",&num_items);
//
// /*input A array*/
// printf("input A array\n");
// for(i=0;i<num_items;i++)
// for(j=0;j<num_items;j++)
// scanf("%f",&arr[i][j]);
//
// /*input B array*/
// printf("input B array\n");
// for(i=0;i<num_items;i++)
// scanf("%f",&arr[i][num_items]);
/*grab first divisor & multipliers*/
divisor = arr[0][0];
for(i=0;i<num_items;i++)
{
mults[i] = arr[i][0];
}
for(i=0;i<num_items+1;i++)
{
is[i]=i;
if(pthread_create(&threadr[i],NULL,gauss,(void *)&is[i]) != 0)
perror("Pthread_create fails");
}
for(i=1;i<num_items;i++)
{
pthread_mutex_lock(&mut);
pthread_cond_wait(&condM,&mut);
divisor = arr[i][i];
for(j=0;j<num_items;j++)
{
mults[j] = 1;
if(j != i)
mults[j] = arr[j][i];
}
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
}
printf("The X values are:\n");
for(i=0;i<num_items; i++) {
printf("%0.3f \n", arr[i][num_items]);
}
/*wait for all threads*/
for(i=0;i<num_items+1; i++)
if (pthread_join(threadr[i],NULL) != 0)
perror("Pthread_join fails");
return 0;
}
You have a race condition (at least one), and your code does not use its condition variables correctly. You can probably fix the former by fixing the latter. Also, I suspect that you intend gauss()'s local variable thread_count to be shared, but variables with no linkage are not shared.
First, the race condition. Consider the main thread: it starts the three other threads, and then locks the mutex and waits for condition variable condM to be signaled. But suppose the threads all manage to signal condM before the main thread starts waiting? Condition variable operations are immediate -- any signals to condM that occur before main() is waiting on it are lost.
Now let's shift gears to talk about condition variables. As the Linux manual for pthread_cond_wait() puts it:
When using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed. Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.
In other words, condition variables are used to suspend thread operations pending a given condition becoming true. In abstract terms, that condition is always "it's ok for this thread to proceed", but that's realized in context-specific terms. Most importantly, the fact that a thread wakes from its wait never inherently communicates that the condition is true; it merely indicates that the newly-woken thread should check whether the condition is true. Generally, the thread should also check before waiting for the first time, as the condition may already be true.
In pseudocode, that looks like this:
Thread 1:
lock mutex;
loop
if is_ok_to_proceed then exit loop;
wait on condition variable;
end loop
// ... maybe do mutex-protected work ...
unlock mutex
Thread 2:
lock mutex
// ... maybe do mutex-protected work ...
is_ok_to_proceed = true;
signal condition variable;
unlock mutex
Generally speaking, there is also (mutex-protected) code somewhere else that make the CV predicate false, so that sometimes the threads indeed do execute their waits.
Now consider how that applies to the race condition in main(). How does main() know whether to wait on condM()? There needs to be a shared variable somewhere that answers that for it, and its wait must be conditioned on the value of that variable. Any thread that means to allow the main thread to proceed must both set the appropriate value for the variable and signal condM. The main thread itself should set the variable, too, as needed, to indicate that it is not ready, at that time, to proceed.
Of course, your other CV usage suffers from the same kind of problem, too.

Resources