passing a local variable to thread. is it possible? - c

i'm working on gcc ,
i'm wondering if this is possible:
I have a function (NOTmain but aLocalFn) and I declare a local variable in it. Then I pass this local argument as a thread argument. is it doable? or there is the chance (depending on what is run first) that the aLocalVar will be lost before threadFunction is run and the reference idxPtr will be pointing to senselessness??
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
return 0;
}
thank you for your help

This code is incorrect. The function aLocalFn may return before the thread function starts executing. And so by the time the thread function reads the local variable, the scope of that variable may have ended.
What can confuse matters is that this code may very well appear to work, at least some of the time. However, it is incorrect and you should use heap allocated memory instead.

your code has a life-time issue with "aLocalVar"
if you just want to pass an integer, here is a non-portable way to do it.
it does not work on some platforms, but you are not likely to encounter those.
void threadFunction ( void * idxptr ) {
int rec_idx = (int) idxptr;
....
}
int rec_idx = returnsRecordIndex();
pthread_create (&thread1, &attr_detached, (void *) &threadFunction, (void *)rec_idx);

It's doable, but it's not done in the code in your question. You will have to add a signal variable to indicate when the new thread is done using the variable. Then your outer function can return.
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t signal = PTHREAD_COND_INITIALIZER;
int done;
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
pthread_mutex_lock(&lock);
done = 1;
pthread_cond_signal(&signal);
pthread_mutex_unlock(&lock);
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
done = 0;
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
pthread_mutex_lock(&lock);
while (!done)
pthread_cond_wait(&signal, &lock);
pthread_mutex_unlock(&lock);
return 0;
}
Note that this example code is itself not thread safe (if multiple threads call aLocalFn).
This does complicate the code, and locking is expensive. So in most cases you're probably better off storing the data in the heap and letting the new thread or pthread_join code free it.

#pizza's answer is what I'd do. Another way for you to do it would be to use malloc/free as #David hinted at. I would certainly do this over the wait loop proposed in other answers here.
int *threadFunction(void *idxPtr){
int rec_idx = *(int *)idxPtr;
// free up our int buffer
free(idxPtr);
...
}
int aLocalFn(){
int aLocalVar = returnsRecordIndex();
// allocate some space for our int
int *intBuf = (int *)malloc(sizeof(int));
*intBuf = aLocalVar;
pthread_create(&thread_id,&attr_detached,threadFunction, intBuf)!=0)
return 0;
}

Whenever you are passing variables to a thread function, it is your job to ensure that the variable remains alive and valid till the thread function is done using it.
In your case aLocalFn() continues to execute simultaneously with the new thread and may even finish execution before the thread, that leaves you with an dangling pointer(pointer pointing to data that may not exist) in thread function since the local variable aLocalVar in the function ceases to exist after function returns.

Related

Main thread and worker thread initialization

I'm creating a multi-thread program in C and I've some troubles.
There you have the function which create the threads :
void create_thread(t_game_data *game_data)
{
size_t i;
t_args *args = malloc(sizeof(t_args));
i = 0;
args->game = game_data;
while (i < 10)
{
args->initialized = 0;
args->id = i;
printf("%zu CREATION\n", i);//TODO: Debug
pthread_create(&game_data->object[i]->thread_id, NULL, &do_action, args);
i++;
while (args->initialized == 0)
continue;
}
}
Here you have my args struct :
typedef struct s_args
{
t_game_data *object;
size_t id;
int initialized;
}args;
And finally, the function which handle the created threads
void *do_action(void *v_args)
{
t_args *args;
t_game_data *game;
size_t id;
args = v_args;
game = args->game;
id = args->id;
args->initialized = 1;
[...]
return (NULL);
}
The problem is :
The main thread will create new thread faster than the new thread can init his variables :
args = v_args;
game = args->game;
id = args->id;
So, sometime, 2 different threads will get same id from args->id.
To solve that, I use an variable initialized as a bool so make "sleep" the main thread during the new thread's initialization.
But I think that is really sinful.
Maybe there is a way to do that with a mutex? But I heard it wasn't "legal" to unlock a mutex which does not belong his thread.
Thanks for your answers!
The easiest solution to this problem would be to pass a different t_args object to each new thread. To do that, move the allocation inside the loop, and make each thread responsible for freeing its own argument struct:
void create_thread(t_game_data *game_data) {
for (size_t i = 0; i < 10; i++) {
t_args *args = malloc(sizeof(t_args));
if (!args) {
/* ... handle allocation error ... */
} else {
args->game = game_data;
args->id = i;
printf("%zu CREATION\n", i);//TODO: Debug
if (pthread_create(&game_data->object[i]->thread_id, NULL,
&do_action, args) != 0) {
// thread creation failed
free(args);
// ...
}
}
}
}
// ...
void *do_action(void *v_args) {
t_args *args = v_args;
t_game_data *game = args->game;
size_t id = args->id;
free(v_args);
args = v_args = NULL;
// ...
return (NULL);
}
But you also write:
To solve that, I use an variable initialized as a bool so make "sleep"
the main thread during the new thread's initialization.
But I think that is really sinful. Maybe there is a way to do that
with a mutex? But I heard it wasn't "legal" to unlock a mutex which
does not belong his thread.
If you nevertheless wanted one thread to wait for another thread to modify some data, as your original strategy requires, then you must employ either atomic data or some kind of synchronization object. Your code otherwise contains a data race, and therefore has undefined behavior. In practice, you cannot assume in your original code that the main thread will ever see the new thread's write to args->initialized. "Sinful" is an unusual way to describe that, but maybe appropriate if you belong to the Church of the Holy C.
You could solve that problem with a mutex by protecting just the test of args->initialized in your loop -- not the whole loop -- with a mutex, and protecting the threads' write to that object with the same mutex, but that's nasty and ugly. It would be far better to wait for the new thread to increment a semaphore (not a busy wait, and the initialized variable is replaced by the semaphore), or to set up and wait on a condition variable (again not a busy wait, but the initialized variable or an equivalent is still needed).
The problem is that in create_thread you are passing the same t_args structure to each thread. In reality, you probably want to create your own t_args structure for each thread.
What's happening is your 1st thread is starting up with the args passed to it. Before that thread can run do_action the loop is modifying the args structure. Since thread2 and thread1 will both be pointing to the same args structure, when they run do_action they will have the same id.
Oh, and don't forget to not leak your memory
Your solution should work in theory except for a couple of major problems.
The main thread will sit spinning in the while loop that checks the flag using CPU cycles (this is the least bad problem and can be OK if you know it won't have to wait long)
Compiler optimisers can get trigger happy with respect to empty loops. They are also often unaware that a variable may get modified by other threads and can make bad decisions on that basis.
On multi core systems, the main thread may never see the change to args->initiialzed or at least not until much later if the change is in the cache of another core that hasn't been flushed back to main memory yet.
You can use John Bollinger's solution that mallocs a new set of args for each thread and it is fine. The only down side is a malloc/free pair for each thread creation. The alternative is to use "proper" synchronisation functions like Santosh suggests. I would probably consider this except I would use a semaphore as being a bit simpler than a condition variable.
A semaphore is an atomic counter with two operations: wait and signal. The wait operation decrements the semaphore if its value is greater than zero, otherwise it puts the thread into a wait state. The signal operation increments the semaphore, unless there are threads waiting on it. If there are, it wakes one of the threads up.
The solution is therefore to create a semaphore with an initial value of 0, start the thread and wait on the semaphore. The thread then signals the semaphore when it is finished with the initialisation.
#include <semaphore.h>
// other stuff
sem_t semaphore;
void create_thread(t_game_data *game_data)
{
size_t i;
t_args args;
i = 0;
if (sem_init(&semaphore, 0, 0) == -1) // third arg is initial value
{
// error
}
args.game = game_data;
while (i < 10)
{
args.id = i;
printf("%zu CREATION\n", i);//TODO: Debug
pthread_create(&game_data->object[i]->thread_id, NULL, &do_action, args);
sem_wait(&semaphore);
i++;
}
sem_destroy(&semaphore);
}
void *do_action(void *v_args) {
t_args *args = v_args;
t_game_data *game = args->game;
size_t id = args->id;
sem_post(&semaphore);
// Rest of the thread work
return NULL;
}
Because of the synchronisation, I can reuse the args struct safely, in fact, I don't even need to malloc it - it's small so I declare it local to the function.
Having said all that, I still think John Bollinger's solution is better for this use-case but it's useful to be aware of semaphores generally.
You should consider using condition variable for this. You can find an example here http://maxim.int.ru/bookshelf/PthreadsProgram/htm/r_28.html.
Basically wait in the main thread and signal in your other threads.

Confused about thread safe and race condition in C

The book says that we need to eliminate global or static data to be thread safe. I think that thread safe means that there is no race condition in the program.
However, in the following example, it changes the local veritable "Point pt_ptr" from a non-pointer type to a pointer type"Point *pt_ptr" in order to prevent the race condition. I noticed that he uses "malloc", which means he is going to create something in the heap. And things in the heap are shared by all the threads... Since it creates something that is shared, it prevents the data race BUT will it be thread UNSAFE?
int main(void) {
pthread_t tids[NUM_THREADS];
int i;
Point *pt_ptr;
for (i= 0; i < NUM_THREADS; i++) {
pt_ptr= malloc(sizeof(*pt_ptr));
pt_ptr->x= i;
pt_ptr->y= 3 * i + 2;
pthread_create(&tids[i], NULL, print_point, pt_ptr);
}
It will only be thread unsafe if more than one thread attempts to access the same memory space (variable as an example) without some thread-safety mechanism, such as mutex or semaphore. They are used to provide a blocking mechanism, so that one thread will sit and "wait" until the current owning thread is thru, at which point the 2nd thread will have the ability to access/modify the variable.
Think of them as numbers at the DMV, and you have to wait until yours is called before you can get service.
In this case, each iteration of the loop calls malloc(), creating a new block of memory that is passed only to one thread. (As J. Murray correctly pointed out.) These dynamic variables are not really global at all. You could instead write:
int main(void)
{
pthread_t tids[NUM_THREADS];
for ( int i = 0; i < NUM_THREADS; i++) {
Point * const pt_ptr = malloc(sizeof(*pt_ptr));
assert(pt_ptr); /* TODO: Handle the out-of-memory error. */
pt_ptr->x= i;
pt_ptr->y= 3 * i + 2;
pthread_create(&tids[i], NULL, print_point, pt_ptr);
}
/* ... */
return EXIT_SUCCESS;
}
That version makes clearer that each iteration of pt_ptr is really a separate local variable.

Pthreads: Main overwrites mutex lock

I am fairly new in threads programming and I wanted to test the mutex functionality. So I programmed the following in order to test it.
**thread_test.h
...
extern int flags;
extern pthread_mutex my_mutex;
...
**thread_test.c
...
#include"thread_test.h"
...
void * thread_test(void *thread_parameters)
{
long tid = (long) thread_parameters;
pthread_mutex_lock(&my_mutex);
++flags;
printf("**THREAD %d** started. Flag value is %d.\n",tid, flags);
sleep(6);
pthread_mutex_unlock(&my_mutex);
pthread_exit(NULL);
}
...
**main.c
...
#include"thread_test.h"
...
#define THREADS 5
pthread_t threads[THREADS];
pthread_mutex_t my_mutex;
int flags = 0;
...
int main(){
int rct;
for(rct = 0; rct<THREADS; rct++)
if(pthread_create(&threads[rct],NULL, thread_test, (void *)rct))
printf("ERROR!")
else
{
sleep(1);
printf("Thread %d initialised in main and the flags value is %d.\n", rct,flags);
}
pthread_mutex_destroy(&my_mutex);
...
It appears that even though I lock the mutex in the child threads, the main program somehow overwrites the mutex lock while a thread has it and assigns variable flags with a new value..
Does anyone have an idea why this is happening?
From what I see you have several errors in your code, part of which your compiler should have told you if you switch all warnings on.
pthread_mutex_t variables must be initialized. For static initialization using = PTHREAD_MUTEX_INITIALIZER at the point of defininition would be enough. (And there is not much point in destroying a static mutex on the other end.)
in the code snippet you gave there is no declaration of thread_test visible to main
you exit main (and destroy the mutex) before the threads have terminated. You may do this, but then you'd have to use an explit pthread_exit in main (and definitively don't do the destroy then). The commonly used approach is not to do this, but to use pthread_join for all threads that have been created.
Also, you could indent your code before posting here, that would much help to make it more readable.

Passing a struct by value to another function initializes it to zero

I am trying to create a thread library and my thread is a struct type. Have to follow a certain interface and in that I need to pass the thread by value. For ex: to join on a thread my code is as follows:
int thread_join(thread_t thread, void **status1)
{
printf("Joining thread\n");
long int thId = thread.id;
printf("Thread id: %ld\n", thId);
gtthread_t * thrd = getThreadFromID(thId);
while(thrd->status != EXIT)
{
}
status1 = &(thrd->ret_value);
return 0;
}
And I an passing a struct of type thread_t to this function. My problem is when I see the thread's ID in the calling function, its displayed properly but when I check it in the thread_join function its displayed as 0. The caller function is as follows:
void* caller(void* arg)
{
thread_t th;
thread_create(&th, some_function, NULL);
thread_join(th, NULL);
while(1);
}
Thread create initializes the ID of the thread to a non-zero value and starts the function associated with it.
My thread structure (and other relevant structure is):
typedef enum
{
RUNNING,
WAITING,
CANCEL,
EXIT
} stat;
//Thread
typedef struct
{
ucontext_t t_ctxt;
long int id;
stat status;
void * ret_value;
int isMain;
} thread_t;
int thread_create(thread_t *thread, void *(*start_routine)(void *), void *arg)
{
thread = (thread_t *)malloc(sizeof(thread_t));
thread->id = ++count;
thread->status = RUNNING;
thread->ret_value = NULL;
thread->isMain = 0;
if(getcontext(&(thread->t_ctxt)) == -1)
handle_error("getcontext");
thread->t_ctxt.uc_stack.ss_sp = malloc(SIGSTKSZ);
thread->t_ctxt.uc_stack.ss_size = SIGSTKSZ;
thread->t_ctxt.uc_link = &sched_ctxt;
makecontext(&thread->t_ctxt, (void (*)(void))wrap_func, 2, (void (*)(void))start_routine, arg);
enqueue(gQ, thread);
printf("Thread id: %ld\n", thread->id);
swapcontext(&(curr_thread->t_ctxt),&sched_ctxt);
return 0;
}
Why does this happen? After all, I am passing by value and this should create a copy of the thread with the same values. Thanks.
EDIT:
Basically I am having a queue of threads and there is a scheduler which round-robins. I can post that code here too but I'm sure that's needless and that code works fine.
EDIT2:
I am making a header file from this code and including that header in another file to test it. All my thread_t variables are static. The caller is a function which includes my header file.
What is this line:
thread = (thread_t *)malloc(sizeof(thread_t));
for?
You pass in to thread_create() an address which referrs to a struct thread_t defined in caller() as auto variable.
Doing as you do, you allocate memory to the pointer passed in to thread_create() initialise it and forget the address on return.
The code never writes to the memory being referenced by the address passed in! Besides this it is a memory leak.
To fix this simply remove the line of code quoted above.
You have no mutex guard on thread id getter. Presumably, there is no guard on setter. What can be happening is that the variable is not visible in the other thread yet. And, without a critical section, it may never become visible.
Each variable which is accessed for both read and write from different threads has to be accessed in a critical section (pthread_mutex_lock / unlock).
Another possibility is that you are setting the thread id inside the running thread and you are accessing the variable even before it is set. If you attempt to join immediately after starting a thread it is possible, that the other thread hasn't been run at all yet and the variable is not set.
side note: do yourself a favor and use calloc:)
In caller function,
thread_create(&th, some_function, NULL);
should be
gtthread_create(&th, some_function, NULL);

How to avoid usage of Global variables in threads

I have written a C program that uses two threads for reading and writing. I have declared the variable which are accessed by both the threads as Global. How to avoid the use of global variables in this case.
Please look into following methods of pthread library in C for having exclusive access of Shared Global variables in C:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
Similarly, you can look into Semaphores for synchronizing the use of global variables in C threads.
HOw to avoid the use of global variables in this case.
There is no need to avoid global variables. Only thing you have to consider is valid data by some lock mechanism.
Putting all global variables in to a struct is for readability and code control when your project grows.
I suggest you to use mutex lock.. Here is an modified sample code.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
double *a;
double *b;
double sum;
int veclen;
} DOTDATA;
/* Define globally accessible variables and a mutex */
#define NUMTHRDS 4
#define VECLEN 100
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum;
void *dotprod(void *arg)
{
/* Define and use local variables for convenience */
int i, start, end, len ;
long offset;
double mysum, *x, *y;
offset = (long)arg;
len = dotstr.veclen;
start = offset*len;
end = start + len;
x = dotstr.a;
y = dotstr.b;
/*
Perform the dot product and assign result
to the appropriate variable in the structure.
*/
mysum = 0;
for (i=start; i<end ; i++)
{
mysum += (x[i] * y[i]);
}
/*
Lock a mutex prior to updating the value in the shared
structure, and unlock it upon updating.
*/
pthread_mutex_lock (&mutexsum);
dotstr.sum += mysum;
pthread_mutex_unlock (&mutexsum);
pthread_exit((void*) 0);
}
/*
The main program creates threads which do all the work and then
print out result upon completion. Before creating the threads,
the input data is created. Since all threads update a shared structure,
we need a mutex for mutual exclusion. The main thread needs to wait for
all threads to complete, it waits for each one of the threads. We specify
a thread attribute value that allow the main thread to join with the
threads it creates. Note also that we free up handles when they are
no longer needed.
*/
int main (int argc, char *argv[])
{
long i;
double *a, *b;
void *status;
/* Assign storage and initialize values */
a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
for (i=0; i<VECLEN*NUMTHRDS; i++)
{
a[i]=1.0;
b[i]=a[i];
}
dotstr.veclen = VECLEN;
dotstr.a = a;
dotstr.b = b;
dotstr.sum=0;
pthread_mutex_init(&mutexsum, NULL);
for(i=0; i<NUMTHRDS; i++)
{
/*
Each thread works on a different set of data.
The offset is specified by 'i'. The size of
the data for each thread is indicated by VECLEN.
*/
pthread_create(&callThd[i], NULL, dotprod, (void *)i);
}
/* Wait on the other threads */
for(i=0; i<NUMTHRDS; i++)
{
pthread_join(callThd[i], &status);
}
/* After joining, print out the results and cleanup */
printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
Do you truly need a shared variable, or do you actually need 2 copies of the same data for each thread? If so, instead of declaring it global, pass it as an argument to the thread at creation.
If it truly needs to be shared, it will need to be protected by a mutex. You can still also do away with the global variable if you bundle the shared variable into a struct along with the mutex and pass it along to the threads as an argument at creation.
I think you're asking how to avoid having your threads accessing globals by passing them their work-data during startup.
Please see the last parameter to pthread_create, which allows you to define a user-defined custom pointer that can be anything you want. Use that to pass data (such as a struct address or even by-value so long as the value can fit in the platform's size of a void pointer.
For example, a parent can send a child thread data by doing such:
Data data;
pthread_create(&thrd, NULL, threadProc, &data);
The child proc would reference this by:
void *threadProc(void *pv)
{
Data *pData = (Data*)pv;
.. use data here...
pthread_exit(NULL);
}
I hope this makes sense, and hope it helps you understand how to pass data to a thread proc, which was what I think your question is.
If you want each thread to have a separate copy of the variable, declare the variables as thread local.
You can make structs. I usually to use a struct called globalArgs where I put all there global variables.
Something like this:
static typedef struct {
int foo;
int baa;
} globalargs;
Or, you can pass all values as parameters to functions that needs of.

Resources