I have a problem with this program in C. In a nutshell I have to send the data created by a sensor, through an aggregator. The aggregator, through a writer thread, read the value generated by the sensor to three different queues through three reader threads (thread_lettore) only that when I create the threads, all three connect to the last queue created. I would like have each thread with its own queue. Passing the message queue id of the sensor is easy because is only one message queue but how can I pass a different message queue id to each thread?
I found the error in this for cycle but I can't resolve it. It generates the correct queues but when I pass the arguments to the pthread_create, it pass only the last queue created.
MonitorLS * m = (MonitorLS*) malloc(sizeof(MonitorLS));
for (int i=0; i<3; i++){
m->id_coda_c = id_code_collettori[i];
pthread_create(&threads[i], &attr, thread_lettore, (void*)m);
}
This is the structure in the header file:
typedef struct {
int variabile;
pthread_mutex_t mutex;
pthread_cond_t cv_lett;
pthread_cond_t cv_scritt;
int num_scrittori;
int num_lettori;
int id_coda_s;
int id_coda_c;
} MonitorLS;
This is how I create three different message queues in the main file:
char chiave = 'a';
int id_code_collettori[3];
for (int i=0; i<3; i++){
key_t key_c = ftok (".", chiave);
id_code_collettori[i] = msgget(key_c, IPC_CREAT|0644);
chiave = chiave + 1;
}
This is a homework exercise that my university professor assigned to me. Sorry for my bad english.
The problem is you only allocate one MonitorLS struct.
You put the first queue ID in the struct. You start the first thread. You put the second queue ID in the struct. You start the second thread. You put the third queue ID in the struct. You start the third thread.
... a few microseconds later, the first thread starts up and looks at the struct and gets the queue ID (which is the third one because that's what you put there).
... a few microseconds later, the second thread starts up and looks at the struct and gets the queue ID (which is the third one because that's what you put there).
... a few microseconds later, the third thread starts up and looks at the struct and gets the queue ID (which is the third one because that's what you put there).
So, you need to use three different variables to store the three different queue IDs, instead of using one variable three times. You could allocate three different MonitorLS structs, one per thread. In fact, that is basically your only option. I see that MonitorLS has other stuff in it, though, so you might want to make another struct (let's call it ThreadInfo), that has a pointer to your MonitorLS struct (same pointer in every ThreadInfo) and a queue ID (different in every ThreadInfo).
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 am using threads to simulate a number of customers who want to book threater seats. Each customer (thread) is supposed to have a unique id and each thread receives some data through a struct (the id is included in that data inside the struct). The problem is that some threads have the same ID when I execute the code and I am wondering how is this happening since, in order for a thread to be created, another iteration of the for loop needs to happen and this way, the thread_id is updated with another value, before the struct is passed to the new thread and the next thread is created.
Can someone help me understand why duplicate values appear and how to fix that? Thanks!
int main(int argc, char *argv[])
{
ThreadData threadData; //the struct which is used as input in the
// thread_transaction method, contains the id and other thread
//information
pthread_t* thread_ids = (pthread_t*)malloc(sizeof(pthread_t) *
n_cust);
for(i = 0; i < n_cust; i++){
threadData.thread_id = i;
pthread_create(&thread_ids[i], NULL, &thread_transaction, (void *)
(&threadData));
}
for(j=0; j < n_cust; j++) {
pthread_join(thread_ids[j], NULL);
}
printf("SEAT ARRANGEMENT: \n");
for(y=0; y<Nseat;y++){
printf("Seat %d / Costumer %d, ", y, threadData.seats_array[y]);
}
free(thread_ids);
return 0;
}
void* thread_transaction(void* arg)
{
ThreadData* threadData = (ThreadData*) arg;
pthread_mutex_lock(&id_mut); //i even tried mutex-locking the ID
int id= threadData->thread_id;
pthread_mutex_unlock(&id_mut);
.
.
.
printf("Your reservation is completed successfully. Your transaction
number is %d ", id); //for 5 customers eg. it printed 4 0 4 2 2
}
I am wondering how is this happening since, in order for a thread to
be created, another iteration of the for loop needs to happen and this
way, the thread_id is updated with another value, before the struct is
passed to the new thread and the next thread is created.
You have just about answered your own question. Yes, on the next iteration of the loop, you update the thread_id of the same structure you presented to the previous thread. So what do you suppose happens if the previous thread hasn't read its ID value yet? Answer: it can read the value meant for the next thread instead of its own.
More generally, you have a data race because the thread_id member is shared between the main thread and the thread it has just created, they access it without proper synchronization,* and one of the accesses is a write. A program that contains a data race has undefined behavior, so threads getting the wrong IDs is the least of your worries.
You could perhaps use a semaphore to provide the needed synchronization and ordering between the main thread and each new one, so that the main thread does not modify threadData prematurely or unsafely. But I think it would be easier and more general to give each thread its own, separate ThreadData object, whether dynamically allocated or from an ordinary array of them.
*Although the new thread protects its access with a mutex, that is not sufficient. All accesses must be protected by the same mutex for that to provide proper synchronization. Moreover, even that wouldn't ensure the needed relative ordering of the write and read.
I have a data structure which I personally implemented that now needs to be used across multiple threads.
typedef struct
{
void** array_of_elements;
size_t size;
} myStruct;
For simplicity, let's say my data structure has these functions:
// Gets a data element from the structure.
void* get(myStruct *x);
// Prints out all the data elements.
void print(myStruct *x);
// Adds an element into the structure.
void add(myStruct *x, void *to_be_added);
It's not a problem whatsoever to call get while another thread is calling print since they are both accessors. However, get and print cannot work while add is currently being called. Vice versa, add cannot work if get and print are currently in-progress.
So I changed myStruct to look like the following:
typedef struct
{
void** array_of_elements;
size_t size;
// True when a mutator is editing this struct.
bool mutating;
// The number of threads currently accessing this struct.
int accessors;
} myStruct;
Now my functions look like the following:
void* get(myStruct *x)
{
// Wait for mutating to end.
while (x->mutating);
// Indicate that another accessor is now using this struct.
x->accessors++;
// get algorithm goes here
// Declare we are finished reading.
x->accessors--;
return ...
}
// Same as above...
void print(myStruct *x)
...
void add(myStruct *x)
{
// Wait for any accessors or mutators to finish.
while (x->mutating || x->accessors > 0);
x->mutating = true;
// add algorithm here
x->mutating = false;
}
BUT, I think there are a lot of problems with this approach and I can't find a way to solve them:
One of my classmates told me using while loops like this slows the thread down immensely.
It has no sense of a queue. The first method that begins waiting for the myStruct to finish being used isn't necessarily the one that goes next.
Even IF I had a queue data structure for which thread goes next, that data structure would also need to be synchronized, which in itself is an infinite loop of needing a synchronized data structure to synchronize itself.
I think it's possible that in the same nano second one thread changes the accessors counter from 0 to 1 (meaning they want to start reading), it's possible for a mutator thread to see it's value is 0 and start mutating. Then, both a mutator thread and an accessor thread would be going at the same time.
I'm pretty sure this logic can cause grid-lock (threads waiting on each other infinitely).
I don't know how to make certain threads sleep and wake up right when they need to for this task, besides having it stuck in a while loop.
You have the right idea, just the wrong approach. I'm not sure what OS you're programming on, but you want to look at the concepts of mutex or semaphore to do what you want to do.
On Linux/Unix that is POSIX compliant, you can look at pthreads:
http://www.cs.wm.edu/wmpthreads.html
On Windows, you can look at Critical Sections for something close to a mutex concept:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx
Or WaitForMultipleObjects for something close to a semaphore:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx
And, yes, using while loops are a bad idea. In this case, you are using what is known as a busy loop. More reading on it here:
What is a busy loop?
Using mutex or semaphore, no while loop is required. Good luck!
What is the impact of freeing the struct that holds the pthread_t on the thread itself?
I have a struct that represents a thread:
typedef struct car{
int cur_place;
pthread_t car_thread;
}car;
and i have an array that holds these cars, after some time i want to free the struct from inside the thread, i mean:
void * car_thread(void * number){
int num = *(int *)number;
free(maze[num]);
maze[num] = NULL;
pthread_exit(NULL);
}
is it possible? what will happen to the thread after i free the pthread that holds it? will the it run the next lines?
thanks in advance.
Freeing car only releases the memory used to store those values. The thread will still be other there somewhere possibly. Think of pthread_t as simply holding a number or address used by the system to talk about the thread. Not the thread itself.
Just don't refer to the memory of car anywhere after its free'd.
You have just freed the location storing thread's ID, the data structure which stores thread attributes is freed when you do pthread_exit(NULL). Therefore answer to your question: thread stll exists.
The thread will not exit until pthread_exit() is called or, in the case you have signal handling built in, a signal for exiting has been received. The thread is attached to the process but different threads are isolated entities until you tie them up in any kind of thread organization. Apologize for the vague phrasing but this the best way I can describe it.
If you intend to signal the cars to exit when you free the data structure, you need to have signal handling build in to notify each thread to exit. Or, call pthread_exit() in each thread somehow.
I am trying to set-up race condition to see how it happens to get an understanding. I wrote the code below. This compiles without any issue but when I run it, it does not print the count at every run. If is run it twice or thrice , then the count is printed. Is my understanding correct that in this code it is not necessary that race condition actually takes place.
( if this is correct,then I am not sure how this exits since there are no boundary condition!). Can some one give me some idea if my understanding is incorrect or the code?
Thanks.
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
void *banking(void *);
int main(){
int accounts[2]={0,0};
pthread_t tid1,tid2;
if(pthread_create(&tid1,NULL,banking,(void *)accounts))
{
perror("pthread_create");
return 1;
}
if(pthread_create(&tid2,NULL,banking,(void *)accounts))
{
perror("pthread_create");
return 1;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);//program now goes into infinite loop.
return 0;
}
void *banking(void * accounts){
int *ptr=accounts;
int count=0;
do{
int temp1=ptr[0];
int temp2=ptr[1];
int amount=rand();
ptr[0]=temp1-amount;
ptr[1]=temp2+amount;
//printf("%d \n %d\n",ptr[0],ptr[1]);
count++;
}while((ptr[0]+ptr[1])==0);
printf("%d\n",count);
//return NULL;
exit(0);
}
I was trying to implement pthread_exit(NULL) to achieve the logic where the thread would exit once it do-while loop is over but as per my understanding the other running thread will not stop this way,because of which the programs goes into an infinite loop. I realized that exit() from any thread terminates process and incorporated exit(0) . The code works fine for some values but at random generates two different 'count' values. This happens once in 10-12 tries. Please suggest if usage of exit in a threaded function is advisable and under what situation will I have two diff values of count.
1> first correct that mistakes which "Paul R" has sauggested. then
2>
you need to use pthread_join function to get succesfully completion of both thread..
here after creating both thread main process may be get over so at that time both threads are also gets over so to over come form this use othread_join for both thread in main()
add this code to end of at your main()
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
if you still not getting the funda of race condition then read belows part. which i have copied from one refrence book
Suppose that your program has a series of queued jobs that are processed by several
concurrent threads.The queue of jobs is represented by a linked list of struct job
objects.
After each thread finishes an operation, it checks the queue to see if an additional
job is available. If job_queue is non-null, the thread removes the head of the linked list
and sets job_queue to the next job on the list.
The thread function that processes jobs in the queue might look like Listing 4.10.
Listing 4.10 ( job-queue1.c) Thread Function to Process Jobs from the Queue
#include <malloc.h>
struct job {
/* Link field for linked list.
struct job* next;
*/
/* Other fields describing work to be done... */
};
/* A linked list of pending jobs.
struct job* job_queue;
*/
/* Process queued jobs until the queue is empty.
void* thread_function (void* arg)
{
while (job_queue != NULL) {
/* Get the next available job. */
struct job* next_job = job_queue;
/* Remove this job from the list. */
job_queue = job_queue->next;
/* Carry out the work. */
process_job (next_job);
/* Clean up. */
free (next_job);
}
return NULL;
}
*/
4.4
Synchronization and Critical Sections
Now suppose that two threads happen to finish a job at about the same time, but only
one job remains in the queue.The first thread checks whether job_queue is null; find-
ing that it isn’t, the thread enters the loop and stores the pointer to the job object in
next_job. At this point, Linux happens to interrupt the first thread and schedules the
second.The second thread also checks job_queue and finding it non-null, also assigns
the same job pointer to next_job. By unfortunate coincidence, we now have two
threads executing the same job.
To make matters worse, one thread will unlink the job object from the queue,
leaving job_queue containing null.When the other thread evaluates job_queue->next,
a segmentation fault will result.
This is an example of a race condition. Under “lucky” circumstances, this particular
schedule of the two threads may never occur, and the race condition may never
exhibit itself. Only under different circumstances, perhaps when running on a heavily
loaded system (or on an important customer’s new multiprocessor server!) may the
bug exhibit itself.
To eliminate race conditions, you need a way to make operations atomic. An atomic
operation is indivisible and uninterruptible; once the operation starts, it will not be
paused or interrupted until it completes, and no other operation will take place mean-
while. In this particular example, you want to check job_queue; if it’s not empty,
remove the first job, all as a single atomic operation.