pthread_join() and sleep in main - c

I have a program that creates two worker threads like the following:
void *Producer(void *threadarg){
while (!terminate_producer){ //do something}
printf("Producer: finalizing thread\n");
pthread_exit(NULL);
}
void *Consumer(void *threadarg){
while (!terminate_consumer){ //do something}
printf("Consumer: finalizing thread\n");
pthread_exit(NULL);
}
// Initialize array of the worker threads
void initFuncArray(long result[])
{
result[0] = (long)&Producer;
result[1] = (long)&Consumer;
}
// The main method
int main (int argc, char* argv[]){
long th_funcs[CPUS_NUM];
initFuncArray(th_funcs);
// threads data
pthread_t tid[CPUS_NUM];
thread_data prod_th_data[CPUS_NUM];
bool pt = false;
for (int i=0;i<CPUS_NUM;i++){
prod_th_data[i].thread_id = i;
pt = pthread_create(&tid[i], NULL, (void *)th_funcs[i], (void*)&prod_th_data[i]);
if (pt) return -1;
}
sleep(5);
terminate_producer = true;
pthread_join (tid[0], NULL);
**sleep(1);**
terminate_consumer = true;
pthread_join (tid[1], NULL);
// Exiting the main thread
return 0;
}
My question is about a call to sleep before terminating the consumer thread. If I do not have this call, the program terminates normally. However, if I have that sleep, the program never terminates. I see the message that the producer thread terminates, but I do not get the message from the consumer thread. What might be the problem?
Following suggestions I modified the code as follows, however, the problem now appears even without a call to sleep in-between:
typedef void (*func_type) (void *);
pthread_mutex_t terminate_producer;
pthread_mutex_t terminate_consumer;
void *Producer(void *threadarg){
while (pthread_mutex_trylock(&terminate_producer)){ //do something}
printf("Producer: finalizing thread\n");
pthread_mutex_unlock(&terminate_producer);
return NULL;
}
void *Consumer(void *threadarg){
while (pthread_mutex_trylock(&terminate_consumer))
printf("Consumer: finalizing thread\n");
pthread_mutex_unlock(&terminate_consumer);
return NULL;
}
// Initialize array of the worker threads
void initFuncArray(func_type result[])
{
result[0] = Producer;
result[1] = Consumer;
}
// The main method
int main (int argc, char* argv[]){
func_type th_funcs[CPUS_NUM];
initFuncArray(th_funcs);
// threads data
pthread_t tid[CPUS_NUM];
thread_data prod_th_data[CPUS_NUM];
// Using mutexes as termination condition
pthread_mutex_init(&terminate_producer,NULL);
pthread_mutex_init(&terminate_consumer,NULL);
pthread_mutex_lock(&terminate_producer);
pthread_mutex_lock(&terminate_consumer);
bool pt = false;
for (int i=0;i<CPUS_NUM;i++){
prod_th_data[i].thread_id = i;
pt = pthread_create(&tid[i], NULL, (void *)th_funcs[i], (void*)&prod_th_data[i]);
if (pt) return -1;
}
sleep(5);
pthread_mutex_unlock(&terminate_producer);
pthread_join (tid[0], NULL);
pthread_mutex_unlock(&terminate_consumer);
pthread_join (tid[1], NULL);
// Exiting the main thread
return 0;
}

Flag terminate_producer represents a critical section. Producers are reading its value and main thread is rewriting it at the same time. Access to this flag should be protected with some synchronization mechanism such as mutex:
inline stopProducers() {
/* GET LOCK */
terminate_producer = 1;
/* RELEASE LOCK */
}
inline unsigned char shouldProduce() {
unsigned char terminate = 0;
/* GET LOCK */
terminate = terminate_producer;
/* RELEASE LOCK */
return !terminate;
}
void *Producer(void *threadarg){
while (shouldProduce()){ /* do something */ }
printf("Producer: finalizing thread\n");
return NULL; // <-- use return instead of pthread_exit
}
and in main you would call stopProducers(); instead of rewriting the flag;

It could be due to the compiler heuristically concluding (as an optimization) that terminate_consumer is a variable which is only read in the consumer thread, so it "caches" it in a register and never reads it.
Can you change the declarations of terminate_producer and terminate_consumer to:
volatile int terminate_producer;
volatile int terminate_consumer;
.. and try again?

Related

Producers Consumers Threads and Mutex

In relation to when producer accesses the shared source, Do I need another condition variable/condition signal? So it does get blocked when the shared resource is locked. I have a condition variable for the consumer, so it does it waits and if it won't try to access if there is nothing there to be added on (to consume)
int pnum; // number updated when producer runs.
int csum; // sum computed using pnum when consumer runs.
int (*pred)(int); // predicate indicating number to be consumed
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condc,condp;
int toConsume = 0; // condition varibale counter
int produceT() {
//Start Critical Section
pthread_mutex_lock(&mutex);
scanf("%d",&pnum);
toConsume++;
//End Critical Section
pthread_cond_signal (&condc);
pthread_mutex_unlock(&mutex);
return pnum;
}
void *Produce(void *a) {
int p;
p=1;
while (p) {
printf("producer thinking...\n");
sleep(1);
printf("..done!\n");
p = produceT();
printf("PRODUCED %d\n",p);
}
printf("EXIT-P\n");
pthread_exit(0);
}
int consumeT() {
pthread_mutex_lock(&mutex); //protect buffer
while(toConsume <=0){ // if nothing in buffer then wait
pthread_cond_wait(&condc,&mutex);
}
pthread_mutex_unlock(&mutex); //release buffer
//sleep()
pthread_mutex_lock(&mutex); //protect buffer
if ( pred(pnum) ) { csum += pnum; }
toConsume--;
pthread_mutex_unlock(&mutex);
return pnum;
}
void *Consume(void *a) {
int p;
p=1;
while (p) {
printf("consumer thinking...\n");
sleep(rand()%3);
printf("..done!\n");
p = consumeT();
printf("CONSUMED %d\n",csum);
}
printf("EXIT-C\n");
pthread_exit(0);
}
int main (int argc, const char * argv[]) {
// the current number predicate
static pthread_t prod,cons;
long rc;
pred = &cond1;
if (argc>1) {
if (!strncmp(argv[1],"2",10)) { pred = &cond2; }
else if (!strncmp(argv[1],"3",10)) { pred = &cond3; }
}
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&condc,NULL);//Initialize consumer condition variable
pthread_cond_init(&condp,NULL);//Initialize producer condition variable
pnum = 999;
csum=0;
srand(time(0));
printf("Creating Producer:\n");
rc = pthread_create(&prod,NULL,Produce,(void *)0);
if (rc) {
printf("ERROR return code from pthread_create(prod): %ld\n",rc);
exit(-1);
}
printf("Creating Consumer:\n");
rc = pthread_create(&cons,NULL,Consume,(void *)0);
if (rc) {
printf("ERROR return code from pthread_create(cons): %ld\n",rc);
exit(-1);
}
pthread_join( prod, NULL);
pthread_join( cons, NULL);
printf("csum=%d.\n",csum);
return 0;
}
A conditional variable is a way of efficiently blocking a thread until a certain condition is verified.
You use a conditional variable in the consumer simply because you dictate you can't consume if there isn't anything to consume -- so you decide to block until there is something to consume. In your case, this happens when toConsume == 0.
You may dictate that the producer must also wait -- that's entirely up to your specification. Some ideas:
You may want to prevent the variable to go over a certain value (e.g. 1000, or INT_MAX to avoid overflow).
If instead of a counter you use a circular buffer to place your things to be consumed, the producer must wait if there are no free slots to place the things in the buffer. This is the most common way of teaching the producers-consumers in textbooks :)

Thread immediately executes after pthread_create?

When I'm creating T threads, I have the following code in the main thread.
pthread_t threads[T];
for (a=0; a<T; a++) {
pthread_create(&(threads[a]), NULL, foo(threads, locks, transition), NULL);
}
printf("in main thread\n");
It creates the first thread, and I noticed that it immediately begins executing the first thread. foo is called for the first thread and "in main thread" gets outputed after. My actual intent was to create all T threads first (pushing the threads into a 'ready' queue) and then continue executing code in the main thread until it exits or yields. Once main exits, I want one of the T threads to execute.
In foo function:
void foo(pthread_t *threads, pthread_mutex_t **locks, double **transition) {
printf("in foo\n");
}
In the main_thread function:
void main_thread (int *N, int *T) {
double **transition;
pthread_mutex_t **locks;
transition = malloc(*N * sizeof *transition);
locks = malloc(*N * sizeof *locks);
for (a=0; a< *N; a++) {
transition[a] = malloc(*N * sizeof *transition[a]);
locks[a] = malloc(*N * sizeof *locks[a]);
}
// lock for each element in transition matrix
for (a=0; a<*N; a++) {
for (b=0; b<*N; b++) {
if (pthread_mutex_init(&(locks[a][b]), NULL) != 0) {
printf("\n mutex init has failed\n");
}
}
}
for (a=0; a<*N; a++) {
for (b=0; b<*N; b++) {
transition[a][b] = 0.0;
}
}
pthread_t threads[T];
for (a=0; a<T; a++) {
pthread_create(&(threads[a]), NULL, foo(threads, locks, transition), NULL);
}
printf("in main thread\n");
}
In the main function:
int main(int argc, char *argv[]) {
int N = 4;
int T = 2;
pthread_t main_t;
pthread_create(&main_t, NULL, &main_thread(&N, &T), NULL);
return 0;
}
With foo(...) you call the function, passing the result of it to the pthread_create function. That means the function will execute before any thread is created.
You need to pass a pointer to the thread function instead:
pthread_create(&threads[a], NULL, foo, NULL);
Also note that when the main function exits, it usually leads to the whole process exiting and that will kill all threads you have started.
If you want to keep threads running after you exit the main thread then you need to use pthread_exit from the main thread, and detach the threads you create.
And to not start the threads at once, IIRC there are attributes you can set and pass to the pthread_create function (the second argument) to start the threads as suspended. You have to explicitly resume the threads though, that won't happen automatically.

Segfault with pthread and concurrency in C

I'm trying to have a thread, that waits until a task is assigned and then will do it, however I'm running into complications.
#include "dispatchQueue.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
task_t *task;
void test1() {
sleep(1);
printf("test1 running\n");
}
void* do_stuff(void *args) {
printf("in do stuff\n");
pthread_mutex_lock(&mutex);
printf("after do stuff has lock\n");
task_t *task = (task_t *)args;
(task->work) (task->params);
pthread_mutex_unlock(&mutex);
}
int main(int argc, char** argv) {
pthread_t thread;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&mutex);
printf("after main gets lock\n");
pthread_create(&thread, NULL, do_stuff, task);
task = task_create(test1, NULL, "test1");
pthread_mutex_unlock(&mutex);
printf("after main unlocks \n");
pthread_join(thread, NULL);
}
The above code will give a segfault, however if I switch the lines pthread_create and task = task_create(), then it works fine. I'm not familiar with C at all, so I'm wondering why this is?
This is how task is created if that helps, at this point I'm pretty sure it's a problem with the way I'm using pthreads.
task_t *task_create(void (*work)(void *), void *param, char* name) {
task_t *task_ptr = malloc(sizeof(task_t));
if (task_ptr == NULL) {
fprintf(stderr, "Out of memory creating a new task!\n");
return NULL;
}
task_ptr->work = work;
task_ptr->params = param;
strcpy(task_ptr->name, name);
return task_ptr;
}
pthread_create(&thread, NULL, do_stuff, task);
task = task_create(test1, NULL, "test1");
You're passing junk to the thread. You haven't set task to any particular value here, yet you pass it to the thread as a parameter.
void* do_stuff(void *args) { // *** args is garbage here
printf("in do stuff\n");
pthread_mutex_lock(&mutex);
printf("after do stuff has lock\n");
task_t *task = (task_t *)args; // ** So task is garbage here
(task->work) (task->params);
pthread_mutex_unlock(&mutex);
}
Here, you initialize task from args. But args has a garbage value.
If you have some kind of collection that's going to track what tasks a thread is going to work on, you have to pass the thread a parameter that allows it to reliably find that collection. In this particular case, &task would work.

C multithread shared variable

I need help with multithreading in C.
Initially, I have a variable named client in the main function.
void *my_function (void *arg) {
int *client = (int*)arg;
*client = 5;
return 0;
}
void *my_function2 (void *arg) { ... }
void *my_function3 (void *arg) { ... }
int main()
{
int client = 0;
pthread_t connect_thread, func2_thread, func3_thread;
pthread_create(&connect_thread, NULL, my_function, (void *)&client);
pthread_create(&func2_thread, NULL, my_function2, (void *)&client);
pthread_create(&func3_thread, NULL, my_function3, (void *)&client);
// how can i make it such that after executing my_function, client's value = 5 in main()??
pthread_join(my_function, NULL);
// once the value is updated, i will pass this updated value into another thread
pthread_join(my_function2, NULL);
pthread_join(my_function3, NULL);
return 0;
}
How can I change the value of client in main from 0 to 5 after the execution of my_function?
The problem with your code is that when main() completes, it terminates the entire program, all other threads included. Your code will indeed modify the value of client, but it isn't doing it in a safe way (in general), as you should be using mutexes to protect data accessed in multiple threads. It's most likely your program is terminating before the thread is fully created.
You need to add mutexes to your code, and use pthread_join() to wait for the thread to complete before allowing main() to complete and return. Please refer to the corrected example below.
Code Listing
/*******************************************************************************
* Preprocessor directives
******************************************************************************/
#include <stdio.h>
#include <pthread.h>
/*******************************************************************************
* Globals
******************************************************************************/
pthread_mutex_t mDataMutex = PTHREAD_MUTEX_INITIALIZER;
/*******************************************************************************
* Function prototypes
******************************************************************************/
void *my_function(void *arg);
/*******************************************************************************
* Function definitions
******************************************************************************/
/*----------------------------------------------------------------------------*/
void *my_function(void *arg)
{
int *client = (int*)arg;
printf("Thread started.\n");
pthread_mutex_lock(&mDataMutex);
*client = 5;
pthread_mutex_unlock(&mDataMutex);
printf("Thread completed.\n");
return 0;
}
/*----------------------------------------------------------------------------*/
int main(void)
{
int client = 0;
int rc;
void *status;
pthread_t connect_thread;
pthread_attr_t attr;
// Print initial value of variable.
printf("Initial value of client:%d.\n", client);
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// Create the thread and start it.
rc = pthread_create(&connect_thread, &attr, my_function, (void *)&client);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
return (-1);
}
// Clean up the attribute struct, don't need it anymore
pthread_attr_destroy(&attr);
// Wait for the thread to complete.
rc = pthread_join(connect_thread, &status);
// Print update value of client
pthread_mutex_lock(&mDataMutex);
printf("Updated value of client:%d.\n", client);
pthread_mutex_unlock(&mDataMutex);
return 0;
}
Sample Output
Initial value of client:0.
Thread started.
Thread completed.
Updated value of client:5.
Your code already changes the value. The error in your code is in the pthread_join call which takes as input a thread id of type pthread_t (connect_thread variable in your case) while you passed to it the function.
#include<pthread.h>
#include<stdio.h>
void *my_function (void *arg) {
int *client = (int*)arg;
*client = 5;
return 0;
}
int main()
{
int client = 0;
pthread_t connect_thread, func2_thread, func3_thread;
pthread_create(&connect_thread, NULL, my_function, (void *)&client);
// how can i make it such that after executing my_function, client's value = 5 in main()??
pthread_join(connect_thread, NULL);
// once the value is updated, i will pass this updated value into another thread
printf("%d\n", client);
return 0;
}
Another alternative is to use a global variable and mutex to change the value.

How to destroy thread in c linux

I need a thread that will call continuously in while(1), but when i use to call thread function by pthread_create() a new thread creates.
I need help on following points :~
1) Is there any method to call thread function without creating thread.
2) Is there any method to destroy the previous thread.
Sample code is
void main()
{
pthread_t thread1;
while(1)
{
pthread_create( &thread1, NULL, myFun, (void*) NULL);
}
}
void * myFun(void *ptr)
{
printf("Hello");
}
* We can not create more than 380 threads, Here we have to use only single thread.
um, I think what you really want to do is like that:
bool received_data = false;
bool beExit = false;
struct recvPacket;
pthread_mutex_t recvMutex;
void main()
{
pthread_t thread1;
void *status;
pthread_mutex_init(&recvMutex, NULL);
pthread_create(&thread1, NULL, myFun, (void*) NULL);
while(1)
{
if (received_data) {
pthread_mutex_lock(&recvMutex); // you should also synchronize received_data and beExit valuables, cuz they are shared by two threads
/* do what you want with recvPacket */
pthread_mutex_unlock(&recvMutex);
received_data == false;
}
/* do else you want, or you can let beExit = true to stop the thread */
}
if (err = pthread_join(thr_main, &status))
printf("pthread_join Error. %s\n", strerror(err)), exit(1);
}
void * myFun(void *ptr)
{
while (!beExit) {
if (true == tryRecvPacket()) {
pthread_mutex_lock(&recvMutex);
/* fill data to recvPacket */
pthread_mutex_unlock(&recvMutex);
received_data = true;
}
}
}
Suggested design is.
void * myFun(void *ptr);
volatile int thread_exit = 1;
void main()
{
pthread_t thread1;
pthread_create( &thread1, NULL, myFun, (void*) NULL);
while(1)
{
//Ask every 10 sec for killing thread like
sleep(10);
printf("Do you wish to kill [0/1]???");
scanf("%d", &thread_exit);
}
//Add code here to make main() to wait till thread dies.
//pthread_join(&thread1);
}
void * myFun(void *ptr)
{
while(thread_exit)
{
printf("Hello");
}
}
For destroying the thread, you can use pthread_kill function available
int pthread_kill(pthread_t thread, int sig);
But its not good practice to kill the thread forcefully as it might cause the problem of the memory leak.
When the parent thread is finished, then all the child threads are finished abruptly.
In your example, as child thread will be in the infinite loop so child thread never finishes. But parent thread-main thread will finish after executing the return 0 statement. So main thread will terminate the child thread also.
To overcome this situation i.e. wait until all child threads have finished, pthread_join(thread1) method is there. So the thread calling this function will wait unless thread1 has finished.
Thanks to all for quick reply..
Problem has been fixed by using following code.
setsockopt (socket_desc, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,sizeof(timeout));
Here i set the timeout for accept the tcp clients request in microseconds.. now code is working OK.

Resources