i am trying to implement Dining Philosophers in C using Resource hierarchy solution. when i am using valgrind everything goes fine. Unfortunately when i done this using console im getting random seqfaults. One time my program will be succesful,one time it will broke on the beginning. I would be grateful if anybody could point where i did mistake and why it's 100% succesfull.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_PHILOSPHERS 5
sem_t forks[NUM_PHILOSPHERS];
void *philosopher(void *param){
printf("Thread created!");
int *id = (int *)param;
int L = 0;
sem_t* Myforks[2];
int par = *id;
if(par == 4){
Myforks[0] = &forks[4];
Myforks[1] = &forks[0];
}else{
Myforks[0] = &forks[par];
Myforks[1] = &forks[par+1];
}
while(L!=5){
printf("Eat spaghetti!",*id);
sem_wait(Myforks[0]);
sem_wait(Myforks[1]);
//.....
printf("EAT spaghetti!",*id);
sem_post(Myforks[1]);
sem_post(Myforks[0]);
L=L+1;
}
pthread_exit(NULL);
}
int main(){
int i;
pthread_t threads[NUM_PHILOSPHERS];
for(i = 0; i < NUM_PHILOSPHERS; i++)
sem_init(&forks[i], 0, 1);
for(i = 0; i < NUM_PHILOSPHERS; i++)
pthread_create(&threads[i], NULL, philosopher, (void *)&i);
return 0;
}
int i;
...
for(i = 0; i < NUM_PHILOSPHERS; i++)
pthread_create(&threads[i], NULL, philosopher, (void *)&i);
^^
Passing a pointer to a local variable isn't going to work. You're passing the same address to all of the threads, so there's an inherent race condition. You point them a pointer to i and them almost immediately you increment i. What value will they read when they access *param? Who knows!
You'll want to create an array with NUM_PHILOSPHERS (sic) slots in it and pass a different address to each thread. You'll also want to make sure that array isn't destroyed when main() exits—i.e., make the array global or static, not local.
Related
I am working on a function that creates a thread and calculates the Fibonacci sequence to a certain user inputted value. For example, if a user enters 5, the output will be: 0 1 1 2 3 5
However, the sequence must be calculated in the created thread, and the results have to be printed out after the thread is exited.
I can create the thread and calculate the sequence, but I need to pass the array fibSequence[] back to the original thread using pthread_exit and pthread_join. I am having trouble figuring out the syntax and can't find any examples of people passing arrays through.
What I have so far:
I created a function fib_runner() that is called by a newly created thread. The Fibonacci sequence is created and placed into the array fibSequence[]. I need to pass this back through to the main function. I am temporarily printing out the sequence in the function, but it should be printed in the main.
Thank you!
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* fib_runner(void* arg)
{
int *limit_ptr = (int*) arg;
int limit = *limit_ptr;
int fibSequence[limit];
int size = sizeof(fibSequence)/sizeof(fibSequence[0]);
printf("Size: %d\n", size);
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++)
{
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
for (int i = 0; i <= size; i++)
{
printf("%d ", fibSequence[i]);
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, &limit);
pthread_join(tid, NULL);
}
Currently, the array is a local variable, so it would go out of scope when the function exits. You need to dynamically allocate memory for it instead:
int *fibSequence = malloc(sizeof(int) * limit);
Then return this pointer from the function:
return fibSequence;
In your main function, you then pass the address of a pointer to receive this value. Then you can print the content of the array. When you're done, be sure to free it:
int *fibSequence;
pthread_join(tid, (void **)&fibSequence);
for (int i = 0; i < limit; i++)
{
printf("%d ", fibSequence[i]);
}
free(fibSequence);
Also, you don't need size in your thread function, since it is the same as limit, and the way you currently calculate it won't work anyway since you now have a pointer instead of an array. Your loop limit in fib_runner also goes one past the end of the array. The exit condition should be i < size, not i <= size.
you have to pass in a value of void * to pthread_exit which is pthread_exit(( void * ) &fibSequence, once that function is called the passed in value will populate the second argument to pthread_join, the second argument will be a pointer to a pointer void ** it will hold the values passed in to pthred_exit
All the threads running within a process share the same address space, file descriptors, stack and other process related attributes.
Threads are sharing memory by definition, they do not own anything except stack and local variables;
If you make fibSequence[limit] global then all threads will have access to it.
You can also declare fibSequence[limit] on the stack in main and pass pointer to it to your thread.
To pass multiple arguments it is convenient to wrap them up in a structure.
The solutions below employ:
struct arg_struct {
int limit;
int *ptrFib;
}args;
Program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct {
int limit;
int *ptrFib;
}args;
void* fib_runner(void* arg)
{
struct arg_struct *a = (struct arg_struct *) arg;
int size = a->limit;
int * fibSequence = a->ptrFib;
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++){
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
int fibSequence[limit];
struct arg_struct argF;
argF.limit = limit;
argF.ptrFib = fibSequence;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, &argF);
pthread_join(tid, NULL);
for (int i = 0; i <= limit; i++){
printf("%d ", fibSequence[i]);
}
}
Output:
Enter Number: 5
0 1 1 2 3 5
The solution with global variable argF is of course possible but it is less elegant.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct {
int limit;
int *ptrFib;
}args;
struct arg_struct argF;
void* fib_runner()
{
int size = argF.limit;
int * fibSequence = argF.ptrFib;
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++){
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
int fibSequence[limit];
argF.limit = limit;
argF.ptrFib = fibSequence;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, NULL);
pthread_join(tid, NULL);
for (int i = 0; i <= limit; i++){
printf("%d ", fibSequence[i]);
}
}
I'm currently confused as to why the following code won't print the following:
My value is 0
My value is 1
My value is 2
Every time I run this I either get 1-2 printed lines or nothing and the program just sits their until I ctrl-c. I feel like it might have something to do with me using the same condition variable and mutex with 3 different threads, would this be correct? Any explanations are greatly appreciated.
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
struct id_holder
{
int id;
};
pthread_mutex_t intersectionMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t directionCondition = PTHREAD_COND_INITIALIZER;
struct id_holder * holder;
void * logic(void* val)
{
struct id_holder * id_struct = (struct id_holder *) val;
pthread_cond_wait(&directionCondition, &intersectionMutex);
printf("My value is %d\n", id_struct->id);
free(id_struct);
return NULL;
}
int main(void)
{
pthread_t threads[3];
for(int i = 0; i <3; i++)
{
holder = (struct id_holder *) malloc(sizeof(struct id_holder));
holder->id = i;
pthread_create(&threads[i], NULL, logic, holder);
}
for(int i = 0; i < 3; i++)
{
sleep(1);
pthread_cond_signal(&directionCondition);
}
for(int i = 0; i < 3; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
When condition is waited for or signalled, it must be done under the lock, otherwise the behavior is unpredictable as it could into race condition. Therefore your code should look like:
pthread_mutex_lock(&intersectionMutex);
pthread_cond_wait(&directionCondition, &intersectionMutex);
pthread_mutex_unlock(&intersectionMutex);
And the same for main (you can move the lock outside the loop if you wish):
for(int i = 0; i < 3; i++) {
sleep(1);
pthread_mutex_lock(&intersectionMutex);
pthread_cond_signal(&directionCondition);
pthread_mutex_unlock(&intersectionMutex);
}
Still the code is not 100% safe as the main thread can signal the condition before the child thread invokes the wait. Although it's highly improbable here due to sleep() in the main function, generally there should be a variable that identifies whether the wait is actually needed or not. In other words, conditions are not queue but can be used to create queue.
I'm pretty new with multithreading and I was trying to increment a shared counter whithout using global variables, my goal is try to maximize the concurrency among the different threads and increment the variable until a number I give in arguments... Sorry if is a lame question, but I would like a help here, when I compile my code and run it i get a segmentation fault... I think the error is in the variable count that I create and the shared counter!
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
typedef struct {
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
void *sfun(void *arg) {
targ_t *est = (targ_t *) arg;
here:
pthread_mutex_lock(&mutex);
(*(est->cnt))++;
pthread_mutex_unlock(&mutex);
if(*(est->cnt)<est->n)
goto here;
return NULL;
}
int main(int argc, char *argv[]){
targ_t real[3];
int c=0;
long count=0;
real[0].cnt=&count;
pthread_mutex_init(&mutex, NULL);
for(c=0;c<3;c++){
real[c].n=atoi(argv[1]);
real[c].nr=c+1;
pthread_create(&real[c].id,NULL,&sfun,&real[c]);
}
for(c=0;c<3;c++){
pthread_join(real[c].id,NULL);
}
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
TY in advance.
There are a number of problems identified in the comments:
Writing out loops with a label here: and a goto here; is not a particularly good idea. There are occasions (some, but not many, occasions) when it is appropriate to use goto — this is not one of those rare occasions.
You don't actually validate that your code was given an argv[1] to convert; could it be that you forgot to pass that argument?
However, your primary problem is that you initialize real[0].cnt but you do not initialize real[1].cnt or real[2].cnt, so those threads are accessing who knows what memory — it might be that they're using null pointers, or they might be pointers to anywhere in memory, allocated or not, aligned or not, writable or not.
You're also missing <stdlib.h>
You're testing *(est->cnt) outside the scope of mutual exclusion.
This code fixes those and some other issues:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct
{
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
static void *sfun(void *arg)
{
targ_t *est = (targ_t *)arg;
while (1)
{
pthread_mutex_lock(&mutex);
long cval = *est->cnt;
if (cval < est->n)
++*est->cnt;
pthread_mutex_unlock(&mutex);
if (cval >= est->n)
break;
}
return NULL;
}
int main(int argc, char *argv[])
{
targ_t real[3];
long count = 0;
if (argc != 2)
{
fprintf(stderr, "Usage: %s count\n", argv[0]);
return(EXIT_FAILURE);
}
for (int c = 0; c < 3; c++)
{
real[c].cnt = &count;
real[c].n = atoi(argv[1]);
real[c].nr = c + 1;
if (pthread_create(&real[c].id, NULL, &sfun, &real[c]) != 0)
break;
}
for (int c = 0; c < 3; c++)
pthread_join(real[c].id, NULL);
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
When run (for example, the program is pth59):
$ pth59 100
OVERALL 100
$
Before moving the test (now on cval) so that the read of *est->cnt was done inside the scope of the mutex, I got an output OVERALL 102 from the same command line. It is important to access shared variables with proper mutual exclusion, even if it is read-only access.
Here is a block of code that creates a number of threads provided by the user, each thread then generates a random number and calculates its squareroot. I cannot figure out why the threads are getting the same ID, line 64 is the culprit as it is where the threads are being created. I suspect that there is something happening in the loop that is causing the threads to all be generated at the same time.
////////////////////////////////////////////////
//
//
// Zach
//
//
//
//
////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *squareroot(void *num1)
{
int *id = (int *)num1;
int incoming = rand()/100;
float *outgoing = (float *)malloc(sizeof(float));
printf("%d \n", *id);
printf("%d\n", incoming);
*outgoing = 5.000;
//Calculate the square root of the number passed to the function
*outgoing = sqrt(incoming);
return outgoing;
}
int main(int argc, char* argv[])//testing funcion
{
srand(time(NULL));
int i, j;
int *temp = (int *)malloc(sizeof(int));
if (argc != 2)
{
printf ("ERROR: Enter a number\n");
return 1;
}
int loop = atoi(argv[1]); //grabbing the integer supplied by user
pthread_t thread_id[loop];
void *exit_status;
float *thread_result;
for(i = 0; i < loop; i++)
{
pthread_create(&thread_id[i], NULL, squareroot, &i);
}
for(j = 0; j < loop; j++)
{
pthread_join(thread_id[j], &exit_status);
thread_result = (float *)exit_status;
printf("%f\n", *thread_result);
}
}
I think what is happening is that your loop finishes creating all the threads (or at least some of them) before any of the threads actually run and extract their unique id.
Because you're passing a pointer to i, when each thread finally gets around to checking its parameter, i is already finished... Or at least partway through. The danger is that multiple threads might see the same value for i. It's even worse that you never copy the value out of that pointer - you always dereference it. That means it might change in the middle of your thread's execution.
What you should do instead is pretend it is a pointer:
pthread_create(&thread_id[i], NULL, squareroot, (void*)i);
And in your thread function:
int id = (int)num1;
This works because the pointer is passed by value. Whatever value you provide is the value that goes into the thread function. Previously it didn't work because you passed a pointer to a value that could change in another thread.
PS: Don't forget to free the result from each thread in your loop at the end. At the moment you're not cleaning up memory that you allocated.
This is my code. It's very simple.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *func(void *arg)
{
printf("ID=%d\n", *(int*)arg);
pthread_exit(NULL);
}
int main()
{
pthread_t pt[4];
int i;
for (i = 0; i < 4; i++)
{
int temp = i;
pthread_create(&pt[i], NULL, func, (void*)&temp);
}
sleep(1);
return 0;
}
I compiled it:
gcc p_test.c -lpthread
I ran it. It printed 2 2 3 3. I ran it again. It printed 2 3 3 2.
My problem is:
Why was 2 or 3 printed twice?
Why didn't it print 1 3 2 0 or any other results?
The major problem here is that you're taking the address of the local variable temp, and then using that pointer outside the scope of the variable - as soon as you exit one iteration of the loop, your pointer to temp becomes invalid and you must not dereference it.
You're passing a pointer to a temporary variable into the thread creation function and this temporary goes out of scope at the end of the loop block. It would seem to me that the temporary address is being reused by the compiler and so that when the threads are executing, they see the same address location.
If you do:
int *temp = malloc(sizeof(int));
*temp = i;
pthread_create(&pt[i], NULL, func, (void*)temp);
instead, you should see the results you expect.
In this case, the thread function needs to free the int after it is printed it to avoid a memory leak.
Also, it's better practice to pthread_join() the threads that you're waiting for rather than just sleep()ing.
because it prints temp, all threads shares the memory(why temp is "shared" is explained by TheJuice), so all threads "share" temp . Use a mutex or make temp a private variable.
Private Variables in Threads
Or you can use phtread_join like this:
int main()
{
pthread_t pt[4];
int i;
for (i =0 ; i < 4; i++)
{
pthread_create(&pt[i], NULL, func, (void*)&i);
pthread_join(pt[i],NULL);
}
//sleep(1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *func(void* arg)
{
printf("ID=%d\n", (int)arg);
pthread_exit(NULL);
return 0;
}
int main()
{
pthread_t pt[4];
int i;
for (i =0 ; i < 4; i++)
{
pthread_create(&pt[i], NULL, func, (void*)i);
pthread_join(pt[i],NULL);
}
return 0;
}