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.
Related
I'm in a situation where every given time interval (let's say 1 second) I need to generate a thread that follows a pre-determined set of actions. Then after it is done, somehow I need to clean up the resources associated with that thread. But I'm not sure how I can do this while still generating new threads, since pthread_join is blocking, so I can't keep generating new threads while waiting for others to finish.
The typical method I have seen suggested to do something like this is:
int i;
pthread_t threads[NUM_THREADS];
for (i = 0; i < NUM_THREADS; ++i) {
pthread_create(&threads[i], NULL, mythread, NULL);
}
for (i = 0; i < NUM_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
However, I don't want to generate a pre-determined amount of threads at the start and let them run. I want to generate the threads one at a time, and just keep generating (this will be ok since the threads reach a saturation point where they just end at the first step if there's more than 100 of them). One solution I thought of is to have the pthread_joins running in their own thread, but then I'm not sure how to tell it which ones to join. These threads have randomised sleep times within them so there's no specified order in which they ought to finish. What I have in mind as to how the program should run is something like this:
Thread[1] created/running
Thread[2] created/running
Thread[3] created/running
Thread[2] finished -> join/free memory
new Thread[2] created/running (since 2 finished, now create a new thread 2)
So for example, you can never have more than 5 threads running, but every time one does finish you create a new one. The threads don't necessarily need to be in an array, I just thought that would make it easier to manage. I've been thinking about this for hours now and can't think of a solution. Am I just approaching the problem the completely wrong way, and there's something easier?
Main thread:
Initialize counting semaphore to 5
Semaphore down
Launch thread
Loop back
Worker thread:
Work
Cleanup
Semaphore up
Die
pthread_join is a function for joining threads, not to wait for them. Yes, the caller will wait until the thread returns from the starting function, but that is only a side effect.
Waiting for threads are accomplished via condition variables (pthread_cond_wait) or barriers (pthread_barrier_wait).
Another approach would be to introduce a global list, where the finished threads will be stored (before exiting the thread, add the thread to that list). And every interval (i assume from your main function), work off the list and join all threads. I don't think that i have to mention, that the list has to be protected by a mutex.
e.g.
struct thread_data {
struct thread_data *next; //single linked list instead of array
pthread_t id; //thread id
void *priv_data; //some data needed for other functionality
bool in_use; //test flag to indicate
//if the specific data/thread is in use/running
};
//mutex to protect the global garbage data
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
//global list for garbage collection, protected via 'lock'
struct thread_data *garbage = NULL;
//thread starting function
void* thread_func(void *arg)
{
//1. cast 'arg' to 'struct thread_data'
struct thread_data *data = (struct thread_data*) arg;
//2. do your other stuff
//3. before returning/exiting
pthread_mutex_lock(&lock);
//add data to garbage
data->next = garbage;
garbage = data;
pthread_mutex_unlock(&lock);
return NULL;
}
int main()
{
#define MAX_THREADS 5 //some arbitrary number
struct thread_data data[MAX_THREADS]; //main data storage
while (true) {
//1. your sleep/wait routine
//2. on wake up, collect garbage first
pthread_mutex_lock(&lock);
for (; garbage ; garbage = garbage->next) {
//destroy garbage->priv_data, if not already done somewhere else
pthread_join(garbage->id); //clear thread resources
garbage->in_use = false; //data no longer in use, free to reuse
}
pthread_mutex_unlock(&lock);
//3. iterate over data storage and if a reusable data is found,
//create the thread and pass the specific data
//as argument to the thread starting function
for (int i=0; i < MAX_THREADS; ++i) {
if (!data[i].in_use) {
data[i].in_use = true;
//data[i].priv_data = ...
pthread_create(&data[i].id, NULL, thread_func, &data[i]);
break; //we only want one thread at a time, right?
}
}
}
return 0;
}
You could call pthread_tryjoin_np for existing threads when you're about to create a new one. (This is a GNU extension to POSIX.)
You could create a list of completed threads, and join them and empty the list when you're about to create a new one. An easily-implemented stack could be used as the list.
You could detach the threads so they get cleaned up automatically. You will need a mechanism to wait for threads to complete before existing the main program, but that can easily be accomplished with a cond var.
I'm using semaphors. I have two threads. The first thread, every two seconds, executes a loop that creates a dynamic array. At the beginning of the loop it creates the dynamic array, and eventually deletes it. On the other hand, a thread must write to this dynamic array, obviously provided that it has already been created and that it has not yet been deleted (i.e., after creation and before deletion). I don't know how to use correctly semaphores. Where am I doing wrong? Thank you for your help!
int *array
int position = 0;
static void *thread_A(void *p_vp_arg)
{
while (1)
{
sem_post(&sem);
array = malloc(1024*sizeof(int));
/* SOME STUFF HERE */
sleep(2);
free(array);
}
}
static void function_B(...){
if(sem_trywait(&sem)){
printf("I can write into the array\n");
array[position] = variable;
position += 1;
}
}
Into the main:
sem_init(&sem, 0, 0)
In your deceleration of the array you perform sem_post() before you allocate the array this should really be after it, with a sem_wait() before the deletion as right now you are releasing the lock and allowing the other thread to try access it before it has been malloced. and you could also delete it while another thread is currently writing to the array.
In the writing method i would switch to using sem_wait instead of sem_trywait it will then handle most of the waiting itself. this is unless you have a specific reason to use sem_trywait
Also don't use the sem result from sem_trywait() or any sem as a loop condition this can cause it to fail. instead do
int result = sem_trywait(&sem)
if(result == 0){
//rest of code
it returns 0 on success and or an errorcode for anything else more can be read on the manual page about the specific errors
Finally you never release the lock in the writing thread, you need to do sem_post() when you are done with the lock as right now you never release the lock.
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.
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.
I've got some code that currently looks like this (simplified)
/* instance in global var *mystruct, count initialized to 0 */
typedef struct {
volatile unsigned int count;
} mystruct_t;
pthread_mutex_t mymutex; // is initialized
/* one thread, goal: block while mystruct->count == 0 */
void x(void *n) {
while(1) {
pthread_mutex_lock(&mymutex);
if(mystruct->count != 0) break;
pthread_mutex_unlock(&mymutex);
}
pthread_mutex_unlock(&mymutex);
printf("count no longer equals zero");
pthread_exit((void*) 0)
}
/* another thread */
void y(void *n) {
sleep(10);
pthread_mutex_lock(&mymutex);
mystruct->count = 10;
pthread_mutex_unlock(&mymutex);
}
This seems inefficient and wrong to me--but I don't know a better way of doing it. Is there a better way, and if so, what is it?
Condition variables allow you to wait for a certain event, and have a different thread signal that condition variable.
You could have a thread that does this:
for (;;)
{
if (avail() > 0)
do_work();
else
pthread_cond_wait();
}
and a different thread that does this:
for (;;)
{
put_work();
pthread_cond_signal();
}
Very simplified of course. :) You'll need to look up how to use it properly, there are some difficulties working with condition variables due to race conditions.
However, if you are certain that the thread will block for a very short time (in order of µs) and rarely, using a spin loop like that is probably more efficient.
A general solution is to use a POSIX semaphore. These are not part of the pthread library but work with pthreads just the same.
Since semaphores are provided in most other multi-threading APIs, it is a general technique that may be applied perhaps more portably; however perhaps more appropriate in this instance is a condition variable, which allows a thread to pend on the conditional value of a variable without polling, which seems to be exactly what you want.
Condition variables are the solution to this problem. Your code can be fairly easily modified to use them:
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
/* one thread, goal: block while mystruct->count == 0 */
void x(void *n) {
pthread_mutex_lock(&mymutex);
while (mystruct->count == 0)
pthread_cond_wait(&mycond, &mymutex);
printf("count no longer equals zero");
pthread_mutex_unlock(&mymutex);
pthread_exit((void*) 0)
}
/* another thread */
void y(void *n) {
sleep(10);
pthread_mutex_lock(&mymutex);
mystruct->count = 10;
pthread_cond_signal(&mycond);
pthread_mutex_unlock(&mymutex);
}
Note that you should generally keep the mutex locked while you act on the result - "consume" the event or similar. That's why I moved the pthread_mutex_unlock() to a point after the printf(), even though it doesn't really matter in this toy case.
(Also, in real code it might well make sense to put the mutex and condition variable inside mystruct).
You could use barriers.
You may also use semaphores to synchronize threads.