pthread_join() for unknown number of threads - c

poll() in main() waits for some sort of a trigger from another application and when there is a trigger, pollHandler() is executed. In pollHandler(), I want to start 'n' number of threads based on the number of requests in the poll message.
But now in pollHandler(), when I want to use pthread_join in a different for loop, I don't have access to the thread_ids. I could create an array of pthread ids and use it outside the for loop block accessible to both pthread_create and pthread_join but the poll() function is active and it could get called again and again, thus overwriting the thread ids. How do I keep things clean here - wait for each thread to finish and make room to have more threads?
int pollHandler(){
int num_req = poll.size();
for(int i=0; i < num_req; i++){
// start thread for each req
pthread_t tid;
// thread paramters dynamically allocated and freed later
struct parameters *p = (struct parameters*)malloc(sizeof(struct parameters));
if((pthread_create(&tid, NULL, thread_func, p) != 0){
return -1;
}
}
for(int i=0; i < num_req; i++){
// pthread_join here but no access to thread ids?
}
return 0;
}
int main(){
......
while(1){
poll(); //waits for a trigger from another application
}
}

I want to start 'n' number of threads based on the number of requests in the poll message.
This design is fundamentally flawed: if you get a request with (say) 10,000 requests, it is unlikely that you will be able to create a separate thread to handle each one, and even if you could, thread creation and destruction are inefficient and best avoided.
A much better design is to start a thread pool, and dispatch work to them, waiting for all work to be completed before returning, as Martin James suggested.
That said, here is correct (except error checking is omitted for clarity) way to implement your current design:
int pollHandler(){
int num_req = poll.size();
pthread_t *tids = calloc(num_req * sizeof(pthread_t));
for(int i=0; i < num_req; i++){
// start thread for each req
// thread paramters dynamically allocated and freed later
struct parameters *p = (struct parameters*)malloc(sizeof(struct parameters));
if((pthread_create(&tid[i], NULL, thread_func, p) != 0){
// bug here.
return -1;
}
}
for(int i=0; i < num_req; i++){
pthread_join(tids[i], NULL);
}
free(tids);
return 0;
I could create an array of pthread ids and use it outside the for loop block accessible to both pthread_create and pthread_join but the poll() function is active and it could get called again and again, thus overwriting the thread ids.
Unless pollHandler() can interrupt another pollHandler(), it will not be invoked until previous invocation finishes, so the code above is "safe".
If pollHandler() can run as part of an interrupt, then your code is already hopelessly broken (neither malloc, nor pthread_create are async-signal safe and thus can't be called in signal handler).
P.S. What's up with //bug here?
You can't just return there -- you need to join the threads you've already created. You would also need to free(tids); there as well.

Related

c pthreads | creating and joining specific threads without waiting?

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.

Pool Threads in pthread C

In my Advance OS work, I need to read data from file and assign it to threads for further processing..
this is my code to read data from file and pass it to thread function
int main() {
FILE *fp = fopen(fileName, "r");
char str_pass[80][MAX_CHAR];
if (fp == NULL){
printf("Could not open file");
return 1;
}
int i=0;
pthread_t thread[THREADS];
int rc;
for(int th=1; th<=THREADS; th++)
{
if(fgets(str_pass[i], MAX_CHAR, fp) != NULL){
//printf("Hello, Thread %d\n",i);
rc = pthread_create(&thread[i], NULL, create_thread, (void*)str_pass[i]);
pthread_join(thread[i],NULL);
if(rc)
{
printf("ERROR; return code from pthread_create() is %d\n",rc);
exit(-1);
}
pthread_join(thread[i],NULL);
i++;
}
else{
printf("End of File");
exit(0);
}
}
pthread_exit(NULL);
fclose(fp);
return 0;
}
and here is my thread code;
void * create_thread(void *hash_string)
{
gen_combinations(hash_string);
//sleep(1);
pthread_exit(NULL);
return NULL;
}
This code is working fine and it is creating threads as much as I define value in THREADS variable, until unless it does not find any record in file. But now I've to do it with thread pooling concept. Because I can't generate as many threads as data in file.
So I need to implement multi-threading using thread pooling. I did
some search on it but didn't get any clearance on it. And now I'm
totally stuck here and not getting any idea from where to start and
how to do this work???
Any kind of help will be appreciated.
Look up the "producer / consumer problem" if you are not already familiar with it, specifically the variation with multiple consumers. Your main thread plays the role of the producer, reading data and parameters from the input file, and packaging them into tidy units of work -- these are the widgets being produced. The worker threads play the role of the consumers, accepting units of work and "consuming" them, as it were, by actually performing the work described. That's a thread pool.
Your particular implementation probably does not need to be generic. It can be designed and tuned as appropriate to specifically serve the problem at hand.
rc = pthread_create(&thread[i], NULL, create_thread, (void*)str_pass[i]);
pthread_join(thread[i],NULL);
if(rc)
{
printf("ERROR; return code from pthread_create() is %d\n",rc);
exit(-1);
}
pthread_join(thread[i],NULL);
Two major bugs here:
You call pthread_join right after you create the thread. That means you wait for the thread to complete. What's the point of creating the thread then?
Once pthread_join returns, the thread no longer exists and its ID is now invalid. Yet you call pthread_join again and pass it the thing that was the ID before but is now junk. The consequences of doing this are entirely unpredictable.
In your example you only have one thread active at a time. You start it and wait till it ends up before reading the next line from the file. It is caused by the pthread_join which follows the thread creation. Instead you need to move the join statement outside of the loop to join all the threads you created.
Now, you can limit the number of thread without creating a pool. You just need an atomic counter which you would increment before the thread starts and decrement when the thread finishes. This way you can check the value of the counter before creating the next thread and wait on a conditional variable. This would be a kind of a semaphore.
Schematically something like the following:
counter = 0;
while {
lock counter;
while (counter > 8)
wait_on_conditional_variable
counter ++;
unlock counter;
run thread;
}
join all remaining threads.
in the thread
do work;
lock counter;
counter --;
signal cond var;
unlock counter;
return;
For the pool you would need to start several threads. Every thread has a loop where it waits for some job to be available. Most likely getting it from a fifo. It has to wait on a conditional variable to check.
thread
do {
lock fifo;
while (fifo.size == 0)
wait on conditional variable.
read job from fifo;
unlock fifo;
do work;
} while (!exiting);
while you reading the file, the following should be done
while ... {
lock fifo;
push line into fifo;
signal var;
unlock fifo;
}
set-exit-condition;
join the pools.
I hope this would help.
But there are multiple ways and optimizations which you could do there.

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.

C - massive # of posix threads spinning out of control and no longer creating new ones

I have an assignment in class that requires us to use POSIX threads and create n*(n-1)/2 of them to process a dataset of n elements.
You can think of it as basically the classical "handshake" in probability.
I know that for a large data set it's going to make the application CPU-bound and eventually it will spend so much time context switching that it will be useless, but the assignment requires us to do this.
However, my loop to create all the threads ceases creating them after a while.
For the code below, I will see output like:
making thread
thread start
thread done
made thread 1944
making thread
thread start
thread done
made thread 1945
making thread
thread start
thread done
made thread 1946
making thread
for a while, but then I will stop seeing the "thread start" and "thread done" messages, and only see the "making thread, made thread" messages.
Here is the loop that creates the threads:
int tCtr = 0;
tArr = (pthread_t*)malloc(((numbers_read) * (numbers_read - 1)/2) * sizeof(pthread_t));
for(i=0; i<numbers_read; i++){
int j;
for(j=i; j<numbers_read; j++){
// n(n-1)/2
if(i != j){
printf("making thread\n");
struct comparison_struct *data;
data = (struct comparison_struct *)malloc(sizeof(struct comparison_struct));
data->i_value = &numbers[i];
data->j_value = &numbers[j];
data->i_arr_entry = &wArr[i];
data->j_arr_entry = &wArr[j];
pthread_create(&tArr[tCtr], NULL, compare_thread, (void *)data);
printf("made thread %d\n", tCtr);
tCtr++;
}
}
}
for(i=0; i<tCtr; i++){
pthread_join(tArr[i], NULL);
}
free(tArr);
and here is the subroutine containing the thread code:
void *compare_thread(void *vData) {
printf("thread start\n");
struct comparison_struct *data;
data = (struct comparison_struct *)vData;
if(*data->i_value <= *data->j_value){
*data->i_arr_entry = 0;
} else {
*data->j_arr_entry = 0;
}
free(vData);
printf("thread done\n");
return NULL;
}
Anybody have any ideas? I'm new to pthreads and having trouble figuring it out.
I know that if I put the pthread_join call immediately after the pthread_create, the application works - but then it blocks on every thread, which I'd assume would decrease performance because there will only ever actually be 2 threads running at a time.
check the return value of pthread_create, maybe you are hitting a resource limit.
pthread_create() will fail if:
[EAGAIN] The system lacked the necessary resources to create
another thread, or the system-imposed limit on the
total number of threads in a process
[PTHREAD_THREADS_MAX] would be exceeded.
[EINVAL] The value specified by attr is invalid.
If you are reaching a resource limit, you can try to make a thread that joins on the other threads, make a worker queue and give work to each of the threads via the queue, or if you control the resource limit of the system try to increase it.
if I put the pthread_join call immediately after the pthread_create ...then it blocks on every thread...there will only ever actually be 2 threads running at a time.
An alternative to joining the threads is to just create them as detached. Create and initialize a pthread_attr_t, set it detached and pass the attr in with your pthread_create call.
pthread_attr_t attr;
int ret;
ret = pthread_attr_init(&attr);
if (ret)
// error .........
ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
for (....)
{
//........
ret = pthread_create(&tArr[tCtr], &attr, compare_thread, (void *)data);
//.......
}
ret = pthread_attr_destroy(&attr);
There is also no requirement that a thread that creates another thread has to be the one to join it. You can create a thread just to join all other created threads. But that is probably going beyond the call of duty for this assignment.

Resources