I have the following code and it is being killed by a SEGV signal. Using the debugger shows that it is being killed by the first sem_init() in main(). If I comment out the first sem_init() the second causes the same problem. I have tried figuring out what would cause this sys call to cause a SEGV. The else is not being run, so the error is happening before it can return a value.
Any help would be greatly appreciated,
Thank you.
I removed the rest of the code that isnt being run before this problem occurs.
#define PORTNUM 7000
#define NUM_OF_THREADS 5
#define oops(msg) { perror(msg); exit(1);}
#define FCFS 0
#define SJF 1;
void bindAndListen();
void acceptConnection(int socket_file_descriptor);
void* dispatchJobs(void*);
void* replyToClient(void* pos);
//holds ids of worker threads
pthread_t threads[NUM_OF_THREADS];
//mutex variable for sleep_signal_cond
pthread_mutex_t sleep_signal_mutex[NUM_OF_THREADS];
//holds the condition variables to signal when the thread should be unblocked
pthread_cond_t sleep_signal_cond[NUM_OF_THREADS];
//mutex for accessing sleeping_thread_list
pthread_mutex_t sleeping_threads_mutex = PTHREAD_MUTEX_INITIALIZER;
//list of which threads are sleeping so they can be signaled and given a job
std::vector<bool> *sleeping_threads_list = new std::vector<bool>();
//number of threads ready for jobs
sem_t* available_threads;
sem_t* waiting_jobs;
//holds requests waiting to be given to one of the threads for execution
std::vector<std::vector<int> >* jobs = new std::vector<std::vector<int> >();
pthread_mutex_t jobs_mutex = PTHREAD_MUTEX_INITIALIZER;
int main (int argc, char * const argv[]) {
//holds id for thread responsible for removing jobs from ready queue and assigning them to worker thread
pthread_t dispatcher_thread;
//initializes semaphores
if(sem_init(available_threads, 0, NUM_OF_THREADS) != 0){ //this is the line causing the SEGV
oops("Error Initializing Semaphore");
}
if(sem_init(waiting_jobs, 0, 0) !=0){
oops("Error Initializing Semaphore");
}
//initializes condition variables and guarding mutexes
for(int i=0; i<NUM_OF_THREADS; i++){
pthread_cond_init(&sleep_signal_cond[i], NULL);
pthread_mutex_init(&sleep_signal_mutex[i], NULL);
}
if(pthread_create(&dispatcher_thread, NULL, dispatchJobs, (void*)NULL) !=0){
oops("Error Creating Distributer Thread");
You declare pointers to your semaphores:
sem_t* available_threads;
sem_t* waiting_jobs;
but never initialize the memory. The sem_init function is not expecting to allocate memory, just to initialize an existing blob of memory. Either allocate some memory and assign these pointers to it, or declare the semaphores as sem_t and pass the address to sem_init.
Related
My goal is to process data on multiple cores by using multiple worker threads, and then further process the results in a master thread. I'm working on linux and I'd like to use pthreads. I'm created a simple example to learn how to do this properly. I have one main thread named "callback" and 4 worker threads. The idea is that the main thread signals the worker threads to start processing, and the 4 threads then signal the main thread when they are done, and the main thread quits after it has been notified by all 4 threads that they are done. I want the 4 worker threads to be able to run in parallel, so I don't want any of those threads waiting for the others. In my example I've tried to just let each of the threads sleep for a different duration (1, 2, 3 and 4 seconds), with the idea that the code would exit after 4 seconds (i.e. when worker thread 4 has done waiting 4 seconds).
For some reason, my code is incorrect, and it always exits immediately, printing this:
thread 3 start (sleeping 3000 ms)
thread 2 start (sleeping 2000 ms)
thread 1 start (sleeping 1000 ms)
thread 4 start (sleeping 4000 ms)
thread 1 stop
thread 2 stop
thread 3 stop
thread 4 stop
Main(): Waited on 5 threads. Done.
So the threads do seem to exit in the correct order but the program doesn't take 4 seconds to run.
What is going on here? I've pasted the code below
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
// based on https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables
#define DUR 1000
#define NUM_THREADS 5
int state = 0;
pthread_mutex_t mutex;
pthread_cond_t conddone;
pthread_cond_t condwork;
void* callback(void* t) {
// signal worker threads to start work
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&condwork);
pthread_mutex_unlock(&mutex);
// wait for worker threads to finish
pthread_mutex_lock(&mutex);
while (state < 4)
pthread_cond_wait(&conddone, &mutex);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void* worker(void* t) {
long id = (long)t;
// wait for signal from callback to start doing work
pthread_mutex_lock(&mutex);
pthread_cond_wait(&condwork, &mutex);
pthread_mutex_unlock(&mutex);
// do work
printf("thread %d start (sleeping %d ms)\n", id, id * DUR);
usleep(id * DUR);
printf(" thread %d stop\n", id);
// tell callback we're done
pthread_mutex_lock(&mutex);
state++;
pthread_cond_signal(&conddone);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
int i, rc;
pthread_t threads[5];
pthread_attr_t attr;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init (&condwork, NULL);
pthread_cond_init (&conddone, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, callback, (void *)0);
pthread_create(&threads[1], &attr, worker, (void *)1);
pthread_create(&threads[2], &attr, worker, (void *)2);
pthread_create(&threads[3], &attr, worker, (void *)3);
pthread_create(&threads[4], &attr, worker, (void *)4);
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(&mutex);
pthread_cond_destroy(&condwork);
pthread_cond_destroy(&conddone);
pthread_exit(NULL);
}
Your immediate problem is just that usleep() sleeps for microseconds not milliseconds so your threads are sleeping for a thousandth of the time that you intend them to.
You do have another problem, though: your condwork condition variable is not paired with a predicate over shared state (eg the predicate state < 4 for the conddone variable). If one of your worker threads executes the pthread_cond_wait() after the "callback" thread has executed the pthread_cond_broadcast(), the worker will wait indefinitely.
You could fix this by initialising the state variable to -1:
int state = -1;
and having your workers wait on the predicate state < 0:
// wait for signal from callback to start doing work
pthread_mutex_lock(&mutex);
while (state < 0)
pthread_cond_wait(&condwork, &mutex);
pthread_mutex_unlock(&mutex);
and having the "callback" signal the workers by setting state to 0:
// signal worker threads to start work
pthread_mutex_lock(&mutex);
state = 0;
pthread_cond_broadcast(&condwork);
pthread_mutex_unlock(&mutex);
I'm reading the book, Modern Operation Systems by AS TANENBAUM and it gives an example explaining condition variable as below. It looks to me there is a deadlock and not sure what I miss.
Lets assume consumer thread starts first. Right after the_mutex is locked, consumer thread is blocked waiting for the condition variable, condc.
If producer is running at this time, the_mutex will still be locked, because consumer never releases it. So producer will also be blocked.
This looks to me a textbook deadlock issue. Did I miss something here? Thx
#include <stdio.h>
#include <pthread.h>
#define MAX 10000000000 /* Numbers to produce */
pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
int buffer = 0;
void* consumer(void *ptr) {
int i;
for (i = 1; i <= MAX; i++) {
pthread_mutex_lock(&the_mutex); /* lock mutex */
/*thread is blocked waiting for condc */
while (buffer == 0) pthread_cond_wait(&condc, &the_mutex);
buffer = 0;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
void* producer(void *ptr) {
int i;
for (i = 1; i <= MAX; i++) {
pthread_mutex_lock(&the_mutex); /* Lock mutex */
while (buffer != 0) pthread_cond_wait(&condp, &the_mutex);
buffer = i;
pthread_cond_signal(&condc);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
int main(int argc, char **argv) {
pthread_t pro, con;
//Simplified main function, ignores init and destroy for simplicity
// Create the threads
pthread_create(&con, NULL, consumer, NULL);
pthread_create(&pro, NULL, producer, NULL);
}
When you wait on a condition variable, the associated mutex is released for the duration of the wait (that's why you pass the mutex to pthread_cond_wait).
When pthread_cond_wait returns, the mutex is always locked again.
Keeping this in mind, you can follow the logic of the example.
I am new to pthread programming. I am writing one sample code in which I want to transfer variable in pthread_cond_signal() as shown below
pthread_t th1,th2;
pthread_cond_t con1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t con2 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* fun(void *gh)
{
pthread_mutex_lock(&mutex);
flag=1;
pthread_cond_wait(&con1,&mutex);
printf("This is test\n");
pthread_mutex_unlock(&mutex);
}
int main()
{
char *s;
int a;
s=malloc(sizeof(char)*4);
printf("Enter thread Number \n");
scanf("%d",&a);
sprintf(s,"con%d",a);
pthread_create(&th1,NULL,fun,NULL);
sleep(1);
while(flag==0) //wait until pthread_cond_wait is called
{}
pthread_mutex_lock(&mutex);
pthread_cond_signal((pthread_cond_t *)s);
pthread_mutex_unlock(&mutex);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
return 0;
}
You are using threads. All threads of a program share memory with each other. The problem isn't reading variables from other threads. The problem is reading them in the correct order: not half-updated, out of date, or from the future.
Solving that problem is the entire reason for mutexes and semaphores and conditions.
What you want to do is NOT pass a value through pthread_cond_signal. What you do is set the value into some memory both threads can read and then send the signal.
I have to wonder why you considered that pthread_cond_signal((pthread_cond_t *)s) would work? s is not, and never was, a condition. A pthread_cond_t is not a value that you pass around. It is the structure that the POSIX Thread library uses to track condition states.
I tried to find a solution in order to keep the number of working threads constant under linux in C using pthreads, but I seem to be unable to fully understand what's wrong with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_JOBS 50
#define MAX_THREADS 5
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int jobs = MAX_JOBS;
int worker = 0;
int counter = 0;
void *functionC() {
pthread_mutex_lock(&mutex1);
worker++;
counter++;
printf("Counter value: %d\n",counter);
pthread_mutex_unlock(&mutex1);
// Do something...
sleep(4);
pthread_mutex_lock(&mutex1);
jobs--;
worker--;
printf(" >>> Job done: %d\n",jobs);
pthread_mutex_unlock(&mutex1);
}
int main(int argc, char *argv[]) {
int i=0, j=0;
pthread_t thread[MAX_JOBS];
// Create threads if the number of working threads doesn't exceed MAX_THREADS
while (1) {
if (worker > MAX_THREADS) {
printf(" +++ In queue: %d\n", worker);
sleep(1);
} else {
//printf(" +++ Creating new thread: %d\n", worker);
pthread_create(&thread[i], NULL, &functionC, NULL);
//printf("%d",worker);
i++;
}
if (i == MAX_JOBS) break;
}
// Wait all threads to finish
for (j=0;j<MAX_JOBS;j++) {
pthread_join(thread[j], NULL);
}
return(0);
}
A while (1) loop keeps creating threads if the number of working threads is under a certain threshold. A mutex is supposed to lock the critical sections every time the global counter of the working threads is incremented (thread creation) and decremented (job is done). I thought it could work fine and for the most part it does, but weird things happen...
For instance, if I comment (as it is in this snippet) the printf //printf(" +++ Creating new thread: %d\n", worker); the while (1) seems to generate a random number (18-25 in my experience) threads (functionC prints out "Counter value: from 1 to 18-25"...) at a time instead of respecting the IF condition inside the loop. If I include the printf the loop seems to behave "almost" in the right way... This seems to hint that there's a missing "mutex" condition that I should add to the loop in main() to effectively lock the thread when MAX_THREADS is reached but after changing a LOT of times this code for the past few days I'm a bit lost, now. What am I missing?
Please, let me know what I should change in order to keep the number of threads constant it doesn't seem that I'm too far from the solution... Hopefully... :-)
Thanks in advance!
Your problem is that worker is not incremented until the new thread actually starts and gets to run - in the meantime, the main thread loops around, checks workers, finds that it hasn't changed, and starts another thread. It can repeat this many times, creating far too many threads.
So, you need to increment worker in the main thread, when you've decided to create a new thread.
You have another problem - you should be using condition variables to let the main thread sleep until it should start another thread, not using a busy-wait loop with a sleep(1); in it. The complete fixed code would look like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_JOBS 50
#define MAX_THREADS 5
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
int jobs = MAX_JOBS;
int workers = 0;
int counter = 0;
void *functionC() {
pthread_mutex_lock(&mutex1);
counter++;
printf("Counter value: %d\n",counter);
pthread_mutex_unlock(&mutex1);
// Do something...
sleep(4);
pthread_mutex_lock(&mutex1);
jobs--;
printf(" >>> Job done: %d\n",jobs);
/* Worker is about to exit, so decrement count and wakeup main thread */
workers--;
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&mutex1);
return NULL;
}
int main(int argc, char *argv[]) {
int i=0, j=0;
pthread_t thread[MAX_JOBS];
// Create threads if the number of working threads doesn't exceed MAX_THREADS
while (i < MAX_JOBS) {
/* Block on condition variable until there are insufficient workers running */
pthread_mutex_lock(&mutex1);
while (workers >= MAX_THREADS)
pthread_cond_wait(&cond1, &mutex1);
/* Another worker will be running shortly */
workers++;
pthread_mutex_unlock(&mutex1);
pthread_create(&thread[i], NULL, &functionC, NULL);
i++;
}
// Wait all threads to finish
for (j=0;j<MAX_JOBS;j++) {
pthread_join(thread[j], NULL);
}
return(0);
}
Note that even though this works, it isn't ideal - it's best to create the number of threads you want up-front, and have them loop around, waiting for work. This is because creating and destroying threads has significant overhead, and because it often simplifies resource management. A version of your code rewritten to work like this would look like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_JOBS 50
#define MAX_THREADS 5
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int jobs = MAX_JOBS;
int counter = 0;
void *functionC()
{
int running_job;
pthread_mutex_lock(&mutex1);
counter++;
printf("Counter value: %d\n",counter);
while (jobs > 0) {
running_job = jobs--;
pthread_mutex_unlock(&mutex1);
printf(" >>> Job starting: %d\n", running_job);
// Do something...
sleep(4);
printf(" >>> Job done: %d\n", running_job);
pthread_mutex_lock(&mutex1);
}
pthread_mutex_unlock(&mutex1);
return NULL;
}
int main(int argc, char *argv[]) {
int i;
pthread_t thread[MAX_THREADS];
for (i = 0; i < MAX_THREADS; i++)
pthread_create(&thread[i], NULL, &functionC, NULL);
// Wait all threads to finish
for (i = 0; i < MAX_THREADS; i++)
pthread_join(thread[i], NULL);
return 0;
}
Using pthreads in linux 2.6.30 I am trying to send a single signal which will cause multiple threads to begin execution. The broadcast seems to only be received by one thread. I have tried both pthread_cond_signal and pthread cond_broadcast and both seem to have the same behavior. For the mutex in pthread_cond_wait, I have tried both common mutexes and separate (local) mutexes with no apparent difference.
worker_thread(void *p)
{
// setup stuff here
printf("Thread %d ready for action \n", p->thread_no);
pthread_cond_wait(p->cond_var, p->mutex);
printf("Thread %d off to work \n", p->thread_no);
// work stuff
}
dispatch_thread(void *p)
{
// setup stuff
printf("Wakeup, everyone ");
pthread_cond_broadcast(p->cond_var);
printf("everyone should be working \n");
// more stuff
}
main()
{
pthread_cond_init(cond_var);
for (i=0; i!=num_cores; i++) {
pthread_create(worker_thread...);
}
pthread_create(dispatch_thread...);
}
Output:
Thread 0 ready for action
Thread 1 ready for action
Thread 2 ready for action
Thread 3 ready for action
Wakeup, everyone
everyone should be working
Thread 0 off to work
What's a good way to send signals to all the threads?
First off, you should have the mutex locked at the point where you call pthread_cond_wait(). It's generally a good idea to hold the mutex when you call pthread_cond_broadcast(), as well.
Second off, you should loop calling pthread_cond_wait() while the wait condition is true. Spurious wakeups can happen, and you must be able to handle them.
Finally, your actual problem: you are signaling all threads, but some of them aren't waiting yet when the signal is sent. Your main thread and dispatch thread are racing your worker threads: if the main thread can launch the dispatch thread, and the dispatch thread can grab the mutex and broadcast on it before the worker threads can, then those worker threads will never wake up.
You need a synchronization point prior to signaling where you wait to signal till all threads are known to be waiting for the signal. That, or you can keep signaling till you know all threads have been woken up.
In this case, you could use the mutex to protect a count of sleeping threads. Each thread grabs the mutex and increments the count. If the count matches the count of worker threads, then it's the last thread to increment the count and so signals on another condition variable sharing the same mutex to the sleeping dispatch thread that all threads are ready. The thread then waits on the original condition, which causes it release the mutex.
If the dispatch thread wasn't sleeping yet when the last worker thread signals on that condition, it will find that the count already matches the desired count and not bother waiting, but immediately broadcast on the shared condition to wake workers, who are now guaranteed to all be sleeping.
Anyway, here's some working source code that fleshes out your sample code and includes my solution:
#include <stdio.h>
#include <pthread.h>
#include <err.h>
static const int num_cores = 8;
struct sync {
pthread_mutex_t *mutex;
pthread_cond_t *cond_var;
int thread_no;
};
static int sleeping_count = 0;
static pthread_cond_t all_sleeping_cond = PTHREAD_COND_INITIALIZER;
void *
worker_thread(void *p_)
{
struct sync *p = p_;
// setup stuff here
pthread_mutex_lock(p->mutex);
printf("Thread %d ready for action \n", p->thread_no);
sleeping_count += 1;
if (sleeping_count >= num_cores) {
/* Last worker to go to sleep. */
pthread_cond_signal(&all_sleeping_cond);
}
int err = pthread_cond_wait(p->cond_var, p->mutex);
if (err) warnc(err, "pthread_cond_wait");
printf("Thread %d off to work \n", p->thread_no);
pthread_mutex_unlock(p->mutex);
// work stuff
return NULL;
}
void *
dispatch_thread(void *p_)
{
struct sync *p = p_;
// setup stuff
pthread_mutex_lock(p->mutex);
while (sleeping_count < num_cores) {
pthread_cond_wait(&all_sleeping_cond, p->mutex);
}
printf("Wakeup, everyone ");
int err = pthread_cond_broadcast(p->cond_var);
if (err) warnc(err, "pthread_cond_broadcast");
printf("everyone should be working \n");
pthread_mutex_unlock(p->mutex);
// more stuff
return NULL;
}
int
main(void)
{
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
pthread_t worker[num_cores];
struct sync info[num_cores];
for (int i = 0; i < num_cores; i++) {
struct sync *p = &info[i];
p->mutex = &mutex;
p->cond_var = &cond_var;
p->thread_no = i;
pthread_create(&worker[i], NULL, worker_thread, p);
}
pthread_t dispatcher;
struct sync p = {&mutex, &cond_var, num_cores};
pthread_create(&dispatcher, NULL, dispatch_thread, &p);
pthread_exit(NULL);
/* not reached */
return 0;
}