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.
Related
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.
Working from this example:
https://computing.llnl.gov/tutorials/pthreads/samples/hello.c
I've worked backwards and tried to edit in what I'm hoping to accomplish.
I'd like to pass data to the thread being spawned.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
long NUM_THREADS=0;
void *Entropy(void *depth)
{
long tid;
tid = (long)depth;
printf("This is where things get done.\n", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
NUM_THREADS = sysconf(_SC_NPROCESSORS_ONLN);
printf("Cores: %i\n", NUM_THREADS);
pthread_t threads[NUM_THREADS];
int rc;
long t;
int depth;
depth = atoi(argv[1]);
for(t=0;t<NUM_THREADS;t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, Entropy(depth), (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
I see on line:
rc = pthread_create(&threads[t], NULL, Entropy(depth), (void *)t);
My function Entropy gets called here, so I thought I'd try to tack on some brackets and pass a variable to that function the way I'd seen it done before. This seems to be a little different though, since this whole line returns something to rc, I wonder if that changes how I pass data to my thread, but I'm not sure how else I'd do it.
Right now this code compiles and runs, int main() goes fine without a hitch but it seg faults the moment it tries to create new threads.
In order to pass data to a thread you need to prepare the data in some place in memory, and pass a pointer to that place into pthread_create. It is pthread_create's job to pass that pointer to the runner function of your thread:
typedef struct {
long tid;
int depth;
}thread_data;
...
void *Entropy(void *dataPtr) {
thread_data *data= (thread_data*)dataPtr;
printf("This is where things get done for %li.\n", data->tid);
pthread_exit(NULL);
}
...
pthread_t threads[NUM_THREADS];
thread_data data[NUM_THREADS];
...
for(t=0;t<NUM_THREADS;t++) {
data[t].tid = t;
data[t].depth = depth;
rc = pthread_create(&threads[t], NULL, Entropy, (void *)&data[t]);
}
Your code crashes since you pass incorrect parameters:
rc = pthread_create(&threads[t], NULL, Entropy(depth), (void *)t);
// ^^^^^^^^^^^^^^
Here you should pass function pointer void *(*)(void *) but you are passing void *, and moreover value is unspecified since Entropy() has no return statement (did you turn warnings on at all?). I guess it should be like this:
rc = pthread_create(&threads[t], NULL, Entropy, (void *)t);
Next, how to pass parameter to thread routine? Technically you can use any pointer, but you should think twice about what you are passing. First of all pointed data must be valid when new thread runs. I.e. you shouldn't pass addresses of any locals except if you are sure that thread is finished when you are leaving scope of passed data - use pthread_join(new_thread) at the scope end to achieve that. Another approach is to pass pointer to data at global scope, that is surely valid at any moment. But there is one flaw - such data are visible to all threads, so you may accidentally make a mess. To avoid it - use dynamic memory - allocate data block with malloc() pass pointer to thread and free it in that thread. Latter option reduces chances to corrupt someone's else data.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
long NUM_THREADS=0;
void *Entropy(void *depth)
{
long tid = *((long *)depth);
free(depth);
printf("This is where things get done.\n", tid);
return NULL;
}
int main(int argc, char *argv[])
{
NUM_THREADS = sysconf(_SC_NPROCESSORS_ONLN);
printf("Cores: %i\n", NUM_THREADS);
pthread_t threads[NUM_THREADS];
int rc;
long t;
int depth;
depth = atoi(argv[1]);
for(t=0;t<NUM_THREADS;t++){
long *arg = malloc(sizeof(*arg));
*arg = t;
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, Entropy, arg);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for(t=0;t<NUM_THREADS;t++){
pthread_join(threads[t], NULL);
}
}
I'm writing a program that uses threads to compute the production of an array by a one dimensional array, all dimensions equal "n".
Each thread must compute the production of a row of the array with that one dimensional array.
The output i'm getting seems to have got addresses values instead of the values i already entered as the matrix elements.
What am i doing wrong?
here's the code i wrote:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define mat_dim 5
static struct param
{
int mat[mat_dim][mat_dim];
int vec[mat_dim];
int ind;
int alter[mat_dim];
};
void *Calculate_row(struct param tid)
{
int i;
for (i=0; i<5; i++) {
tid.alter[tid.ind] = tid.alter[tid.ind]+tid.mat[tid.ind][i]*tid.vec[i];
}
pthread_exit((void *)&tid);
}
int main (int argc, char *argv[])
{
pthread_t thread[mat_dim];
pthread_attr_t attr;
int rc;
long t;
void *status;
int th_array[5][5]={{1,4,3,5,1},{4,6,2,8,5},{3,5,1,3,6},{1,5,6,2,8},{4,7,5,3,6}};
int th_vec[5]={1,2,1,2,1};
struct param thread_parameter;
thread_parameter.mat[5][5]=th_array;
thread_parameter.vec[5]=th_vec;
int tmp[5]={0,0,0,0,0};
thread_parameter.alter[5]=tmp;
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<mat_dim; t++) {
printf("Main: creating thread %ld\n", t);
thread_parameter.ind=t;
rc = pthread_create(&thread[t], &attr, Calculate_row,&thread_parameter);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
printf("the result vector is : ");
for(t=0; t<mat_dim; t++) {
rc = pthread_join(thread[t], NULL);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("%d, ",thread_parameter.alter[t]);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
you are calling rc = pthread_create(&thread[t], &attr, Calculate_row,&thread_parameter);
where
struct param thread_parameter;
and the function is void *Calculate_row(struct param tid)
it should be void *Calculate_row(struct param *tid)
as a pointer is passed and change all . to ->.
All these lines:
thread_parameter.mat[5][5]=th_array;
thread_parameter.vec[5]=th_vec;
thread_parameter.alter[5]=tmp;
are wrong. The array indexes go from 0 to 4, therefore by addressing the 5th element you're out of their bounds.
You're using pthread_create the wrong way. This is the prototype:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Your Calculate_row receives a void* as a parameter, which needs to be cast to a (struct param *) and then dereferenced.
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?
I'am new to C and would like to play with threads a bit. I would like to return some value from a thread using pthread_exit()
My code is as follows:
#include <pthread.h>
#include <stdio.h>
void *myThread()
{
int ret = 42;
pthread_exit(&ret);
}
int main()
{
pthread_t tid;
void *status;
pthread_create(&tid, NULL, myThread, NULL);
pthread_join(tid, &status);
printf("%d\n",*(int*)status);
return 0;
}
I would expect the program output "42\n" but it outputs a random number. How can I print the returned value?
It seems to be a problem that I am returning a pointer to a local variable. What is the best practice of returning/storing variables of multiple threads? A global hash table?
Here is a correct solution. In this case tdata is allocated in the main thread, and there is a space for the thread to place its result.
#include <pthread.h>
#include <stdio.h>
typedef struct thread_data {
int a;
int b;
int result;
} thread_data;
void *myThread(void *arg)
{
thread_data *tdata=(thread_data *)arg;
int a=tdata->a;
int b=tdata->b;
int result=a+b;
tdata->result=result;
pthread_exit(NULL);
}
int main()
{
pthread_t tid;
thread_data tdata;
tdata.a=10;
tdata.b=32;
pthread_create(&tid, NULL, myThread, (void *)&tdata);
pthread_join(tid, NULL);
printf("%d + %d = %d\n", tdata.a, tdata.b, tdata.result);
return 0;
}
You are returning the address of a local variable, which no longer exists when the thread function exits. In any case, why call pthread_exit? why not simply return a value from the thread function?
void *myThread()
{
return (void *) 42;
}
and then in main:
printf("%d\n", (int)status);
If you need to return a complicated value such a structure, it's probably easiest to allocate it dynamically via malloc() and return a pointer. Of course, the code that initiated the thread will then be responsible for freeing the memory.
You've returned a pointer to a local variable. That's bad even if threads aren't involved.
The usual way to do this, when the thread that starts is the same thread that joins, would be to pass a pointer to an int, in a location managed by the caller, as the 4th parameter of pthread_create. This then becomes the (only) parameter to the thread's entry-point. You can (if you like) use the thread exit value to indicate success:
#include <pthread.h>
#include <stdio.h>
int something_worked(void) {
/* thread operation might fail, so here's a silly example */
void *p = malloc(10);
free(p);
return p ? 1 : 0;
}
void *myThread(void *result)
{
if (something_worked()) {
*((int*)result) = 42;
pthread_exit(result);
} else {
pthread_exit(0);
}
}
int main()
{
pthread_t tid;
void *status = 0;
int result;
pthread_create(&tid, NULL, myThread, &result);
pthread_join(tid, &status);
if (status != 0) {
printf("%d\n",result);
} else {
printf("thread failed\n");
}
return 0;
}
If you absolutely have to use the thread exit value for a structure, then you'll have to dynamically allocate it (and make sure that whoever joins the thread frees it). That's not ideal, though.
I think you have to store the number on heap. The int ret variable was on stack and was destructed at the end of execution of function myThread.
void *myThread()
{
int *ret = malloc(sizeof(int));
if (ret == NULL) {
// ...
}
*ret = 42;
pthread_exit(ret);
}
Don't forget to free it when you don't need it
Another solution is to return the number as value of the pointer, like Neil Butterworth suggests.
#include<stdio.h>
#include<pthread.h>
void* myprint(void *x)
{
int k = *((int *)x);
printf("\n Thread created.. value of k [%d]\n", k);
//k =11;
pthread_exit((void *)k);
}
int main()
{
pthread_t th1;
int x =5;
int *y;
pthread_create(&th1, NULL, myprint, (void*)&x);
pthread_join(th1, (void*)&y);
printf("\n Exit value is [%d]\n", y);
}
You are returning a reference to ret which is a variable on the stack.
Question : What is the best practice of returning/storing variables of multiple threads? A global hash table?
This totally depends on what you want to return and how you would use it? If you want to return only status of the thread (say whether the thread completed what it intended to do) then just use pthread_exit or use a return statement to return the value from the thread function.
But, if you want some more information which will be used for further processing then you can use global data structure. But, in that case you need to handle concurrency issues by using appropriate synchronization primitives. Or you can allocate some dynamic memory (preferrably for the structure in which you want to store the data) and send it via pthread_exit and once the thread joins, you update it in another global structure. In this way only the one main thread will update the global structure and concurrency issues are resolved. But, you need to make sure to free all the memory allocated by different threads.
if you're uncomfortable with returning addresses and have just a single variable eg. an integer value to return, you can even typecast it into (void *) before passing it, and then when you collect it in the main, again typecast it into (int). You have the value without throwing up ugly warnings.
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
void *myThread(void *args)
{
return (void *)(intptr_t)42;
}
int main(void)
{
pthread_t tid;
void *status;
int ret;
pthread_create(&tid, NULL, myThread, NULL);
ret = pthread_join(tid, &status);
if (ret) {
fprintf(stderr, "pthread_join() failed\n");
return -1;
}
/* pthread_join() copies the exit status (namely 42) of the target thread
* into the location pointed to by retval (namely &status), &status points
* to void *, so we need to cast void * to int.
*/
printf("%ld\n", (intptr_t)status);
return 0;
}