What I'm trying to do is have each thread copy information from a struct in main using a critical section before main changes the struct for other threads.
#include <iostream>
#include <pthread.h>
using namespace std;
struct foo
{
public:
int var;
int *turn;
int index;
pthread_mutex_t *bsem;
pthread_cond_t *waitTurn;
};
void *threadFunc(void *arg) {
int var;
foo *workingVar = (foo *)arg;
pthread_mutex_lock(workingVar->bsem);
while (*workingVar->turn != workingVar->index)
pthread_cond_wait(workingVar->waitTurn, workingVar->bsem);
var = workingVar->var;
*workingVar->turn++;
pthread_cond_broadcast(workingVar->waitTurn);
pthread_mutex_unlock(workingVar->bsem);
cout << var << endl;
return nullptr;
}
int main() {
int turn = 0, NTHREADS = 5;
foo mainStruct;
pthread_mutex_t bsem;
pthread_mutex_init(&bsem, NULL);
pthread_cond_t waitTurn = PTHREAD_COND_INITIALIZER;
mainStruct.bsem = &bsem;
mainStruct.waitTurn = &waitTurn;
mainStruct.turn = &turn;
pthread_t tid[NTHREADS];
for (int i = 0; i < NTHREADS; i++) {
mainStruct.index = i;
mainStruct.var = i;
pthread_create(&tid[i], nullptr, threadFunc, &mainStruct);
}
for (int i = 0; i < NTHREADS; i++)
pthread_join(tid[i], NULL);
}
The code above is from a thread function. I'm trying to make threads wait until it is their 'turn' using pthread_cond_wait, and then once the condition is true, the struct info passed from main will be copied into local variables and will increment the turn and exit the critical section (also not using global variables, so mutex and condition variable is passed using a pointer through the struct). Turn is initialized to 0, and index is the thread number (in the order of which it was created).
This process is deadlocked, and times out.
Please let me know if any more context/information is needed, this is my first Stack Overflow question.
I see race condition on mainStruct.index
. Main thread modifies it without lock and multiple threads are accessing it under a lock. So if first thread starts fast it will interact with your loop spawning threads.
Looks like you plan was to have multiple instances of Foo
, but you have one. So imagine scenario:
mainStruct.index
is 4
!turn
is 0
and workingVar->index
is 4
(see point 3)All threads are waiting no one has called pthread_cond_broadcast
condition *workingVar->turn != workingVar->index
is always true
Also your code is written in C
not in C++
. The only C++
is use of std::cout
!. Try rewrite this using std::thread
and it will fix itself (if you pas arguments by values).