Segmentation fault on Dining Philosophers in C with Pthreads - c

I have this segmentation fault problem in the exercise of the dining philosophers with one thread per philosopher which I can't manage. Each threads think for a random period of time and same with eat. Each philosopher can eat with two forks, he has to pick both forks to eat. To avoid deadlock I made a sort for the picking forks. The philosophers with odd number pick the right fork first. I used a global semaphore which I initialize with the function init at the start of main. Is there someone who can help me please? I tried to put some fprintf(stderr,"HERE\n") but because of concurrency I can't find the problem. Here is the code
'''
//global array of semaphore
pthread_mutex_t *mtx;
//intialize array of semaphore
void init(pthread_mutex_t *mtx){
mtx=malloc(N*sizeof(pthread_mutex_t));
if(!mtx){
perror("malloc fallita\n");
exit(EXIT_FAILURE);
}
for(int i=0;i<N;i++){
if(pthread_mutex_init(&mtx[i],NULL) != 0){
perror("init fallita\n");
exit(EXIT_FAILURE);
}
}
}
void eat(unsigned int *seed){
long r = rand_r(seed) % 800000;
struct timespec t={0,r};
nanosleep(&t,NULL);
}
void think(unsigned int *seed){
long r = rand_r(seed) % 1000000;
struct timespec t={0,r};
nanosleep(&t,NULL);
}
void *filosofo(void *arg){
unsigned int id = *((unsigned int*)arg);
unsigned int seed=id;
int left = id % N;
int right = id-1;
while(1){
think(&seed);
if(id % 2){ //il filosofo di indice dispari prende prima la forchetta di destra
pthread_mutex_lock(&mtx[right]);
pthread_mutex_lock(&mtx[left]);
eat(&seed);
pthread_mutex_unlock(&mtx[left]);
pthread_mutex_unlock(&mtx[right]);
}else{ //il filosofo di indice pari prende prima la forchetta a sinista
pthread_mutex_lock(&mtx[left]);
pthread_mutex_lock(&mtx[right]);
eat(&seed);
pthread_mutex_unlock(&mtx[right]);
pthread_mutex_unlock(&mtx[left]);
}
}
pthread_exit(NULL);
}
int main(void){
init(mtx);
//array of N philosophers
pthread_t *th;
th = malloc(N*sizeof(pthread_t));
if(!th){
perror("Malloc fallita\n");
exit(EXIT_FAILURE);
}
for(unsigned int i=0;i<N;i++){
if(pthread_create(&th[i],NULL,filosofo,(void*)(intptr_t)i) != 0){
perror("create fallita\n");
exit(EXIT_FAILURE);
}
}
for(unsigned int i=0;i<N;i++){
if(pthread_join(th[i],NULL) == -1){
perror("join fallita\n");
}
}
free(th);
free(mtx);
return 0;
}
'''

You need to make init take a pointer to a pointer to a mutex to initialize. Currently, the global mtx isn't changed.
Here's roughly how:
void init(pthread_mutex_t **mtx){ // pointer to pointer
*mtx=malloc(N*sizeof(pthread_mutex_t)); // dereference
if(!*mtx){
perror("malloc fallita\n");
exit(EXIT_FAILURE);
}
for(int i=0;i<N;i++){
if(pthread_mutex_init(&(*mtx)[i],NULL) != 0){ // pointer acrobatics
perror("init fallita\n");
exit(EXIT_FAILURE);
}
}
}
and then pass a pointer to the global mtx in main:
int main(void){
init(&mtx);
I suggest naming your global mutex and your local mutex in init differently so this doesn't confuse you again.
Also, right here you're passing the value of i as a void *, instead of passing its address:
if(pthread_create(&th[i],NULL,filosofo,(void*)(intptr_t)i) != 0){
If you do this (which I actually recommend to avoid race conditions), then you should change filosofo to take input in the same way:
unsigned int id = (unsigned int)arg;

Related

What is the best way to have multiple threads read a file at the same time?

What is the best way to have multiple threads read a file at the same time ?
For example, if I tell my program to run with 4 threads and the file is 12 characters long, I want each thread to read 3 chars at the same time.
This is what I have so far :
thread function :
void *thread(void *arg) {
// can't seem to find the right solution to make it work here...
}
main function (thread_count is the number of threads and text_size the size of text) :
// Number of characters each thread should read
uint16_t thread_chars_num = (text_size / thread_count);
pthread_t threads[thread_count];
for (int i = 0; i < thread_count; i++) {
if(i == thread_count - 1) { // last thread might have more work
thread_chars_num += (text_size % thread_count )
}
if (pthread_create(&threads[i], NULL, thread, &thread_chars_num) != 0) {
fprintf(stderr, "pthread_create failed!\n");
return EXIT_FAILURE;
}
}
I was thinking of giving to the thread function a struct with index to start reading and index to stop reading, but it's really confusing and I can't seem to find the right solution.
Assuming you have a struct like:
struct ft
{
char* file_name;
int start_index;
int end_index;
};
Then in your thread:
void *thread(void *arg) {
int i;
int c;
struct ft* fi = (struct ft*)arg;
FILE* file = fopen(fi->file_name);
fseek (file , fi->start_index, SEEK_SET);
for(i = 0; i < fi->end_index - fi->start_index; i++)
{
c = getc(file);
//do something
}
}
Also, don't forget to do pthread_join in your main thread, which will make it wait for the other threads to finish.

C Program exits without any output

This had a previous question regarding multi thread issues Here. Now the issue is that the program exits without any input. The program gets the input from a text file given as arguments with executing. It should only contain numbers separated by spaces and if theres any other character it should give an error as done in row_check functions. Can anyone suggest why it would exit without any error ?.
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<ncurses.h>
const unsigned int NUM_OF_THREADS = 9;
typedef struct thread_data_s {
char *ptr;
int row_num;
} thread_data_t;
void report(const char *s,int w,int q);
void* row_check(void* data)
{
thread_data_t *my_data_ptr = data;
int j, flag;
flag=0x0000;
for(j = 0; j < 9; j++)
{
flag |= 1u << ( (my_data_ptr->ptr)[j] - 1 );
if (flag != 0x01FF){
report("row", my_data_ptr->row_num, j-1);
}
}
return NULL;
}
void report(const char *s,int w,int q)
{
printf("\nThe sudoku is INCORRECT");
printf("\nin %s. Row:%d,Column:%d",s,w+1,q+1);
getchar();
exit(0);
}
int main(int argc, char* argv[])
{
int i,j;
char arr1[9][9];
FILE *file = fopen(argv[1], "r");
if (file == 0)
{
fprintf(stderr, "failed");
exit(1);
}
int col=0,row=0;
int num;
while(fscanf(file, "%c ", &num) ==1) {
arr1[row][col] = num;
col++;
if(col ==9)
{
row++;
col = 0;
}
}
fclose(file);
int n;
thread_data_t data[NUM_OF_THREADS];
pthread_t tid;
pthread_attr_t attr;
for(n=0; n < NUM_OF_THREADS; n++)
{
data[n].ptr = &arr1[n][0];
data[n].row_num = n;
pthread_create(&tid, &attr, row_check, &data[n]);
}
for(n=0; n < NUM_OF_THREADS; n++)
{
pthread_join(tid, NULL);
}
return 0;
}
The following in one of the issues in the code and it would explain why the application exists so soon...
The following code doesn't join all the threads it creates (so the application exits and terminates the threads before they finished running):
thread_data_t data[NUM_OF_THREADS];
pthread_t tid;
pthread_attr_t attr;
for(n=0; n < NUM_OF_THREADS; n++)
{
data[n].ptr = &arr1[n][0];
data[n].row_num = n;
pthread_create(&tid, &attr, row_check, &data[n]);
}
for(n=0; n < NUM_OF_THREADS; n++)
{
pthread_join(tid, NULL);
}
As you can see, the code is only saving the pointer to one of the threads (the value in tid is always replaced, overwriting the existing data) and joining that thread (instead of all of them).
This might be better constructed as:
thread_data_t data[NUM_OF_THREADS];
pthread_t tid[NUM_OF_THREADS];
for(n=0; n < NUM_OF_THREADS; n++)
{
data[n].ptr = &arr1[n][0];
data[n].row_num = n;
pthread_create(tid + n, NULL, row_check, &data[n]);
}
for(n=0; n < NUM_OF_THREADS; n++)
{
pthread_join(tid[n], NULL);
}
This way the application will wait for all the threads to complete their tasks (and report any errors) before returning.
Can anyone suggest why it would exit without any error ?.
Yes,
the posted code has no action when all 9 rows of the puzzle result are correct, it just gracefully exits.
and to further muddy the logic.
The posted code only checks the last thread created, and when that thread exits, the program exits, That does not mean the other threads have exited
One further serious detail. the call to pthread_create() is passing the address of the attr variable, but that variable contains what ever trash is/was on the stack where that variable was declared. Since the code is not setting any specific attributes for the threads, strongly suggest eliminate the variable and simply use NULL in the second parameter to pthread_create()

C multithreading with pthread

I was trying to create 30 threads with pthread_create within a loop.I used proper headers.
struct student_thread{
int id;
char * message;
};
void *student(void *i)
{
struct student_thread *s;
s = (struct student_thread *) i;
printf("%s%d\n",s->message,s->id);
//sleep(1);
pthread_exit(NULL);
}
void creat_student_thread()
{
pthread_t st[N];
struct student_thread stt[N];
int i,ct;
for(i=0;i<N;i++){
stt[i].id =i+1;
stt[i].message = "Created student thread ";
ct = pthread_create(&st[i],NULL,student,(void *) &stt[i].id);
//enqueue(Q1,stt[i].id);
if(ct){
printf("Error!Couldn't creat thread\n");
exit(-1);
}
}
}
int main()
{
creat_student_thread();
}
But the output shows only 28 threads created.output
What am i missing here?Thanks in advance.
Move the parameter array, 'struct student_thread stt[N];' out of 'creat_student_thread()'. Make it global, say.
Prevent main() from exiting early, eg. with an infinite sleep loop, or input request.

program spinning on pthread lock

After banging my head against a wall for a few hours during this exercise, I am stuck at that wall.
First off, this is a program designed to find and print all prime numbers between 1 and ceiling, where ceiling is some user input. The design is to implement POSIX threads.
In my program, it runs successfully until on one of the later iterations in the thread's method. When it gets to that later iteration, it steps to the line pthread_mutex_lock(lock); and spins, forcing me to kill it with Ctrl+z. The 2 input's I've been using are 1 for the number of threads and 10 for the ceiling. This flaw is reproducible as it happens every time I've tried it. note: although this code should be able to implement multiple threads, I'd like to get it working correctly with 1 child thread before adding more.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int* numbermarker = NULL;
int* buffer = NULL;
int* checked = NULL;
int pullposition = 0;
int placeposition = 0;
pthread_mutex_t* lock;
int ceiling;
/*This method places one of the primes in the buffer. It
offers a safe way to manage where the next value will be placed*/
void placevalue(int value){
buffer[placeposition] = value;
placeposition++;
}
void* threadmethod(){
int i;
int k;
int l;
while(1){
printf("pull %d number %d \n",pullposition, buffer[pullposition]);
pthread_mutex_lock(lock);
printf("FLAG\n");
l = buffer[pullposition];
pullposition++;
printf("pullTWO %d number %d \n",pullposition, buffer[pullposition-1]);
pthread_mutex_unlock(lock);
for(k=l+1;k<=ceiling;k++){
if(k%l){
if(k%2){
checked[k]=1;
placevalue(k);
}
}
else{
numbermarker[k-1] = 1;
}
}
int sum=0;
for(i=0; i<ceiling; i++){
if(numbermarker[i]){
checked[i] = numbermarker[i];
}
printf("checked|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d|\n",
checked[0], checked[1], checked[2], checked[3], checked[4], checked[5], checked[6], checked[7], checked[8], checked[9]);
sum += checked[i];
printf("sum %d ceiling %d\n",sum,ceiling);
}
printf("number |%d|%d|%d|%d|%d|%d|%d|%d|%d|%d|\n",
numbermarker[0], numbermarker[1], numbermarker[2], numbermarker[3], numbermarker[4], numbermarker[5], numbermarker[6], numbermarker[7], numbermarker[8], numbermarker[9]);
if(sum == ceiling){
return NULL;
}
}
}
int main()
{
int numthreads;
int i;
printf("Enter number of threads: \n");
scanf("%d", &numthreads);
printf("Enter the highest value to check \n");
scanf("%d", &ceiling);
/* This will hold 1's and 0's.
1 = number has been checked or is
confirmed not to be a prime
0 = number is a possible prime
The idea behind these values is that the next
prime can always be identified by the 0 with
the lowest index
*/
numbermarker = (int*)malloc(sizeof(int)*(ceiling));
checked = (int*)malloc(sizeof(int)*(ceiling));
/*This will hold the primes as they are found*/
buffer = (int*)malloc(sizeof(int)*(ceiling));
/*allocate space for the lock*/
lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(lock,NULL);
for(i=0; i<ceiling; i++){
if(i<1){
numbermarker[i] = 1;
}
else{
numbermarker[i] = 0;
}
checked[i]=0;
buffer[i]=0;
printf("%d \n",numbermarker[i]);
}
checked[0]=1;
placevalue(2);
printf("checked|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d|\n", checked[0], checked[1], checked[2], checked[3], checked[4], checked[5], checked[6], checked[7], checked[8], checked[9]);
pthread_t **tid = (pthread_t **) malloc(sizeof(pthread_t *) * numthreads);
for(i=0;i<numthreads;i++){
tid[i] = (pthread_t *) malloc(sizeof(pthread_t));
}
for(i=0;i<numthreads;i++){
if(pthread_create(tid[i],
NULL,
threadmethod,
NULL)){
printf("Could not create thread \n");
exit(-1);
}
}
for(i=0;i<numthreads;i++){
if(pthread_join(*tid[i], NULL)){
printf("Error Joining with thread \n");
exit(-1);
}
free(tid[i]);
}
free(tid);
for(i=0;i<ceiling;i++){
if(numbermarker[i] == 0){
printf("%d sdfsddd \n", numbermarker[i]);
printf("%d \n", i+1);
}
}
free(buffer);
free(numbermarker);
buffer=NULL;
numbermarker=NULL;
return(0);
}
I've tried your code and in
void placevalue(int value)
{
buffer[placeposition] = value;
placeposition++;
}
placeposition goes beyond the size of buffer. This results in undefined behaviour, a very plausible outcome of which is the trashing of the mutex (which is malloc()ed right after buffer).
On top of that, there's a race condition is placevalue(). However, if you're using a single worker thread, you are not (yet) running into it.

C: pthread performance woes. How can I make this code perform as expected?

I have created this little program to calculate pi using probability and ratios. In order to make it run faster I decided to give multithreading with pthreads a shot. Unfortunately, even after doing much searching around I was unable to solve the problem I have in that when I run the threadFunc function, with one thread, whether that be with a pthread, or just normally called from the calculate_pi_mt function, the performance is much better (at least twice or if not 3 times better) than when I try running it with two threads on my dual core machine. I have tried disabling optimizations to no avail. As far as I can see, when the thread is running it is using local variables apart from at the end when I have used a mutex lock to create the sum of hits...
Firstly are there any tips for creating code that will run better here? (ie style) because I'm just learning by trying this stuff.
And secondly would there be any reason for these obvious performance problems?
When running with number of threads set to 1, one of my cpus maxes out at 100%. When set to two, the second cpu rises to roughly 80%-90%, but all this extra work it is apparently doing is to no avail! Could it be the use of the rand() function?
struct arguments {
int n_threads;
int rays;
int hits_in;
pthread_mutex_t *mutex;
};
void *threadFunc(void *arg)
{
struct arguments* args=(struct arguments*)arg;
int n = 0;
int local_hits_in = 0;
double x;
double y;
double r;
while (n < args->rays)
{
n++;
x = ((double)rand())/((double)RAND_MAX);
y = ((double)rand())/((double)RAND_MAX);
r = (double)sqrt(pow(x, 2) + pow(y, 2));
if (r < 1.0){
local_hits_in++;
}
}
pthread_mutex_lock(args->mutex);
args->hits_in += local_hits_in;
pthread_mutex_unlock(args->mutex);
return NULL;
}
double calculate_pi_mt(int rays, int threads){
double answer;
int c;
unsigned int iseed = (unsigned int)time(NULL);
srand(iseed);
if ( (float)(rays/threads) != ((float)rays)/((float)threads) ){
printf("Error: number of rays is not evenly divisible by threads\n");
}
/* argument initialization */
struct arguments* args = malloc(sizeof(struct arguments));
args->hits_in = 0;
args->rays = rays/threads;
args->n_threads = 0;
args->mutex = malloc(sizeof(pthread_mutex_t));
if (pthread_mutex_init(args->mutex, NULL)){
printf("Error creating mutex!\n");
}
pthread_t thread_ary[MAXTHREADS];
c=0;
while (c < threads){
args->n_threads += 1;
if (pthread_create(&(thread_ary[c]),NULL,threadFunc, args)){
printf("Error when creating thread\n");
}
printf("Created Thread: %d\n", args->n_threads);
c+=1;
}
c=0;
while (c < threads){
printf("main waiting for thread %d to terminate...\n", c+1);
if (pthread_join(thread_ary[c],NULL)){
printf("Error while waiting for thread to join\n");
}
printf("Destroyed Thread: %d\n", c+1);
c+=1;
}
printf("Hits in %d\n", args->hits_in);
printf("Rays: %d\n", rays);
answer = 4.0 * (double)(args->hits_in)/(double)(rays);
//freeing everything!
pthread_mutex_destroy(args->mutex);
free(args->mutex);
free(args);
return answer;
}
There's a couple of problems I can see:
rand() is not thread-safe. Use drand48_r() (which generates a double in the range [0.0, 1.0) natively, which is what you want)
You only create one struct arguments structure, then try to use that for multiple threads. You need to create a seperate one for each thread (just use an array).
Here's how I'd clean up your approach. Note how we don't need to use any mutexes - each thread just stashes its own return value in a seperate location, and the main thread adds them up after the other threads have finished:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include <pthread.h>
struct thread_info {
int thread_n;
pthread_t thread_id;
int rays;
int hits_in;
};
void seed_rand(int thread_n, struct drand48_data *buffer)
{
struct timeval tv;
gettimeofday(&tv, NULL);
srand48_r(tv.tv_sec * thread_n + tv.tv_usec, buffer);
}
void *threadFunc(void *arg)
{
struct thread_info *thread_info = arg;
struct drand48_data drand_buffer;
int n = 0;
const int rays = thread_info->rays;
int hits_in = 0;
double x;
double y;
double r;
seed_rand(thread_info->thread_n, &drand_buffer);
for (n = 0; n < rays; n++)
{
drand48_r(&drand_buffer, &x);
drand48_r(&drand_buffer, &y);
r = x * x + y * y;
if (r < 1.0){
hits_in++;
}
}
thread_info->hits_in = hits_in;
return NULL;
}
double calculate_pi_mt(int rays, int threads)
{
int c;
int hits_in = 0;
if (rays % threads) {
printf("Error: number of rays is not evenly divisible by threads\n");
rays = (rays / threads) * threads;
}
/* argument initialization */
struct thread_info *thr = malloc(threads * sizeof thr[0]);
for (c = 0; c < threads; c++) {
thr[c].thread_n = c;
thr[c].rays = rays / threads;
thr[c].hits_in = 0;
if (pthread_create(&thr[c].thread_id, NULL, threadFunc, &thr[c])) {
printf("Error when creating thread\n");
}
printf("Created Thread: %d\n", thr[c].thread_n);
}
for (c = 0; c < threads; c++) {
printf("main waiting for thread %d to terminate...\n", c);
if (pthread_join(thr[c].thread_id, NULL)) {
printf("Error while waiting for thread to join\n");
}
hits_in += thr[c].hits_in;
printf("Destroyed Thread: %d\n", c+1);
}
printf("Hits in %d\n", hits_in);
printf("Rays: %d\n", rays);
double answer = (4.0 * hits_in) / rays;
free(thr);
return answer;
}
You're using far too many synchronization primitives. You should sum the local_hits at the end in the main thread, and not use a mutex to update it in an asynchronous fashion. Or, at least, you could use an atomic operation (it's just an int) to do it instead of lock an entire mutex to update one int.
Threading has a cost. It may be that, as your useful computing code looks very simple, the cost of thread management (cost paid when changing thread and synchronisation cost) is much higher than the benefit.

Resources