Program goes infinite loop when semaphore is used (Deadlock) - c

The program is being executed correctly without semaphores, but when I use semaphores for sync, the program goes into an infinite loop (deadlock)!. I can't find out why this is happening. After being executed the program get inputs from the user and goes to an infinite loop; *This is seeking tutor problem.
Here are my functions with semaphores ->
void* CoOrdinator(void* arg)
{
sem_wait(&co);
// sorting
std temp;
for (int i = 0; i < chair-1; i++)
{
for (int j = 0; j < chair-i-1; j++)
{
if (buffer[j].priority == buffer[j+1].priority)
{
continue;
}
else if(buffer[j].priority>buffer[j+1].priority)
{
temp = buffer[j];
buffer[j] = buffer[j+1];
buffer[j+1] = temp;
}
}
}
// End Sorting
printf("I'm a CoOrdinator\n");
for (int i = 0; i < chair; i++)
{
printf("Student - %d -",buffer[i].id);
printf("Priority - %d\n",buffer[i].priority);
}
sem_post(&tc);
}
// Teacher
void* Teacher(void* ox)
{
for (int i = 0; i < teachers; i++)
{
sem_wait(&tc);
pthread_mutex_lock(&mutex);
tcObj[i] = buffer[out];
out = (out+1)%chair;
printf("Student - %d is in classroom. Priority: %d\n",tcObj[i].id,tcObj[i].priority);
pthread_mutex_unlock(&mutex);
sem_post(&st);
}
// // Studing with Teacher
// for (int i = 0; i < teachers; i++)
// {
// printf("Stuying with Teacher - %d", i);
// printf("Student - %d -",tcObj[i].id);
// printf("Priority - %d\n",tcObj[i].priority);
// }
}
// Student
void* Student(void *px)
{
// we have to use semaphore
for (int i = 0; i < students; i++)
{
sem_wait(&st);
pthread_mutex_lock(&mutex);
buffer[in] = stObj[i];
in = (in+1)%chair;
pthread_mutex_unlock(&mutex);
sem_post(&co);
// if((int*)px == students)
// {
// break;
// }
}
}
and the rest of the program is
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include<semaphore.h>
// Global Variables
int teachers, students, chair, help;
// Student Structure
typedef struct Student
{
int id;
int priority;
}std;
// Objects Array
std *stObj, *tcObj, *buffer;
// Buffer
int in = 0, out = 0;
// Semaphores
sem_t st, tc, co;
pthread_mutex_t mutex;
main function
int main(int argc, char const *argv[])
{
// Getting Inputs
printf("Enter The Number Of Students: ");
scanf("%d",&students);
printf("Enter The Number Of Teachers: ");
scanf("%d",&teachers);
printf("Enter The Number Of Chair: ");
scanf("%d",&chair);
// Buffer Array
buffer = (std*)malloc(chair * sizeof(std));
stObj = (std*)malloc(students * sizeof(std));
tcObj = (std*)malloc(students * sizeof(std));
//Declaring Thread Variables
pthread_t tc_thread[teachers], st_thread[students], co_thread;
//Getting Priorities
for(int i=0; i<students; i++)
{
stObj[i].id = i+1;
printf("Enter The Priority of Student: ");
scanf("%d",&stObj[i].priority);
}
// Mutex & Semaphores
pthread_mutex_init(&mutex, NULL);
// sem_init(&empty,0,chair);
// sem_init(&full,0,0);
sem_init(&st, 0, 1);
sem_init(&tc, 0, 1);
sem_init(&co, 0, 1);
// Creating Threads
for (int i = 0; i < students; ++i)
{
pthread_create(&st_thread[i],NULL,Student,(void*)&stObj[i].id);
pthread_join(st_thread[i],NULL);
}
for (int i = 0; i < teachers; ++i)
{
pthread_create(&tc_thread[i],NULL,Teacher,(void*)i);
pthread_join(tc_thread[i],NULL);
}
pthread_create(&co_thread,NULL,CoOrdinator,NULL);
pthread_join(co_thread,NULL);
// Destroying Semaphores & Mutex
pthread_mutex_destroy(&mutex);
sem_destroy(&st);
sem_destroy(&tc);
sem_destroy(&co);
return 0;
}
is there any error?

The pthread_join is your problem. Once the first loop of student has run, it has consumed the st semaphore and there is nothing to replenish it.
for (int i = 0; i < students; ++i)
{
pthread_create(&st_thread[i],NULL,Student,(void*)&stObj[i].id);
pthread_join(st_thread[i],NULL);
}
Remove the pthread_join from these loops; and after all threads have been created, add loops to join them. So your main would look more like:
// Creating Threads
for (int i = 0; i < students; ++i)
{
pthread_create(&st_thread[i],NULL,Student,(void*)&stObj[i].id);
}
for (int i = 0; i < teachers; ++i)
{
pthread_create(&tc_thread[i],NULL,Teacher,(void*)i);
}
pthread_create(&co_thread,NULL,CoOrdinator,NULL);
pthread_join(co_thread,NULL);
for (int i = 0; i < students; ++i)
{
pthread_join(st_thread[i],NULL);
}
for (int i = 0; i < teachers; ++i)
{
pthread_join(tc_thread[i],NULL);
}
Also, unrelated to your immediate problem, this allocation: tcObj = (std*)malloc(students * sizeof(std)); should likely be tcObj = malloc(teachers * sizeof(*tcObj)); Note you had the wrong number; but also you should not cast malloc, and it is usually better to use sizeof(*var_you_are_assigning_malloc_to) since it is less fragile and self documenting.
Make these changes, and your program runs for a lot longer before hanging...

Related

Multithreading but first few threads are being skipped

It's been a few hours and i can't seem to understand the issue. Build this program to count from 1 - 10. The goal of this program is to use multithreading and dynamically split the array depending on how many threads it requested. Problem is the first 2 threads are being skipped and the last thread is doing most of th e process. I suspect it's the for loop that creates the threads.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
typedef struct
{
int *array;
int batch;
int start;
int end;
} Parameter;
void *method(void *p)
{
Parameter *param = (Parameter *)p;
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
}
}
int main(int argc, char **argv)
{
// Getting the user input
int array_length = atoi(argv[1]);
int batches = atoi(argv[2]);
printf("User specified Array:%d\tBatch:%d\n", array_length, batches);
// Creating an array
int *array = (int *)calloc(array_length, sizeof(int));
// Fill it up with some data
for (int i = 0; i < array_length; i++)
{
array[i] = i;
}
// Determine the Batches
int batch_size = array_length / batches;
int remainder = array_length % batches;
printf("%d\n", batch_size);
printf("%d\n", remainder);
int start = 0;
int end = 0;
int index =0;
// List of parameters
Parameter *param = (Parameter *)calloc(batches, sizeof(Parameter));
pthread_t *threads = (pthread_t *)calloc(batches, sizeof(pthread_t));
// Loop through each batch.
for (int i = 0; i < batches; i++)
{
printf("\n\nBatch number -> %d\n", i);
end = start + batch_size;
if (remainder > 0)
{
remainder --;
end ++;
}
// Fill the parameters
param[i].array = array;
param[i].end = end;
param[i].start = start;
param[i].batch = i;
// Call the thread.
pthread_create(threads + index, NULL, method, (void *)&param[i]);
index++;
start = end;
}
for (int i = 0; i < batches; i++)
{
pthread_join(threads[i], NULL);
}
free(param);
free(threads);
free(array);
return 0;
}
Been playing with the index of the for loop(line 57) as i'm certain it's the cause of the issue. been getting some results but the main problem still persisted.
Code Works as intended. I'm a dumbas who didn't put the printf in the void function. like so:
void *method(void *p) {
Parameter *param = (Parameter *)p;
printf("\n\nBatch number -> %d\n", param->batch); //<-- moved from main method
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
} }
Thanks for pointing it out that the program works

How do u dynamically fill a struct *array instead of manually making them

we've been working on some structs, and decided that we wanted to make them dynamic so we could run a function that would basically make AREASIZE amount of struct areas and store them in our area *array, instead of us having to manually make a block of code with for example 10, 100 or 1000 struct areas and subsequently *Narea amount of subareas.
We've been stuck a couple of hours, and thought it might be more productive to ask where our logic is shit, cuz we cannot seem to find it. The code just crashes in the nested for loop of our create areas function.
Our logic:
we have a struct *array called area, which has a struct *array inside called subareas.
we pass the struct *array area to our function create_areas
create_areas uses the arrow operator to parse through our struct *array areas[i] and then our struct *array subareas[j]. And then fills up the values of our subareas.
before exiting we also assign the other value in our struct *array area, which is its average
In our heads would lead to our struct *array area being filled with 5x areas.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MARGIN 70
#define MARGIN2 30
#define SIZE 5
#define NAREA 4
#define AREASIZE 5
typedef struct subarea
{
int co2_cost, time;
double average, sensorData[SIZE];
} subarea;
typedef struct area
{
subarea *subarea_array[NAREA];
double average;
} area;
void create_areas(area *area_array[NAREA]);
void sensor_data_start(area *area, double start_var);
int main(void)
{
int co2_counter = 0, time_counter = 0;
int day_counter = 0;
int area_number;
srand(time(NULL));
area *area_array[AREASIZE] = {};
create_areas(area_array);
printf("Hello");
return 0;
}
void create_areas(area *area_array[NAREA])
{
printf("create areas\n");
for (int i = 0; i < AREASIZE; i++)
{
printf("First for loop\n");
for (int j = 0; j < NAREA; j++)
{
printf("Second for loop\n");
area_array[i]->subarea_array[j]->co2_cost = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->time = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->average = 0;
printf("Second for loop\n");
sensor_data_start(area_array[i], 0);
}
area_array[i]->average = 0;
}
}
void sensor_data_start(area *area, double start_var)
{
for (int i = 0; i < NAREA; i++)
{
for (int j = 0; j < SIZE; j++)
{
area->subarea_array[i]->sensorData[j] = start_var;
}
}
}
This:
area *area_array[AREASIZE] = {};
Creates an array of pointers to areas (area *). You have yet to create any areas!.
Thus when you try to access area_array[i]->subarea_array you access unallocated memory, causing a crash.
Look into pointers in C if you don't understand why.
Look into the malloc and free functions to actually instantiate your areas. You will also need the sizeof operator.
Note: you will have to do the same with subareas.
In the end you're looking for something like this:
void create_areas(area *area_array[NAREA])
{
printf("create areas\n");
for (int i = 0; i < AREASIZE; i++)
{
area_array[i] = malloc(sizeof(area)); //or malloc(sizeof(*area_array[i]))
if (area_array[i] == NULL) //always check malloc return value!!
exit(-1);
printf("First for loop\n");
for (int j = 0; j < NAREA; j++)
{
area_array[i]->subarea_array[j] = malloc(sizeof(subarea));
if (area_array[i]->subarea_array[j] == NULL) //always check malloc return value!!
exit(-1);
printf("Second for loop\n");
area_array[i]->subarea_array[j]->co2_cost = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->time = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->average = 0;
printf("Second for loop\n");
sensor_data_start(area_array[i], 0);
}
area_array[i]->average = 0;
}
}
Happy Learning!
Use pointer to structs which will act as array :
typedef struct subarea
{
int co2_cost, time;
double average, sensorData[SIZE];
// note that you can also define sensorSata as pointer and allocate dynamically
} subarea;
typedef struct area
{
subarea *subarea_array; // will be allocated dynamically
double average;
} area;
int main(void)
{
…
/*allocate soace for the area array */
area *area_array = calloc(AREASIZE, sizeof(area));
create_areas(area_array);
printf("Hello");
return 0;
}
void create_areas(area *area_array)
{
printf("create areas\n");
for (int i = 0; i < AREASIZE; i++)
{
/* allocate space for subarea */
area_array[i].subarea_array = malloc(sizeof(subarea)*NAREA);
printf("First for loop\n");
for (int j = 0; j < NAREA; j++)
{
printf("Second for loop\n");
area_array[i].subarea_array[j].co2_cost = 0;
printf("Second for loop\n");
area_array[i].subarea_array[j].time = 0;
printf("Second for loop\n");
area_array[i].subarea_array[j].average = 0;
printf("Sensor dafa start\n");
sensor_data_start(&area_array[i], 0);
}
area_array[i].average = 0;
}
}
void sensor_data_start(area *area, double start_var)
{
for (int i = 0; i < NAREA; i++)
{
// you can allocate sensorSata here if it was a pointer
for (int j = 0; j < SIZE; j++)
{
area->subarea_array[i].sensorData[j] = start_var;
}
}
}
Other things that could be done for more dynamic is to add the number of subarea in area struct if it is not constant . Same for sensorSata if you make it dynamic.

Non recursive factorial in C

I have a simple question for you. I made this code to calculate the factorial of a number without recursion.
int fact2(int n){
int aux=1, total = 1;
int i;
int limit = n - 1;
for (i=1; i<=limit; i+=2){
aux = i*(i+1);
total = total*aux;
}
for (;i<=n;i++){
total = total*i;
}
return total;
}
As you can see, my code uses loop unrolling to optimize clock cycles in the execution. Now I'm asked to add two-way parallelism to the same code, any idea how?
You can use ptherads library to create two separate threads. Each thread should do half of the multiplications. I could put together following solution.
#include <pthread.h>
typedef struct {
int id;
int num;
int *result;
} thread_arg_t;
void* thread_func(void *arg) {
int i;
thread_arg_t *th_arg = (thread_arg_t *)arg;
int start, end;
if(th_arg->id == 0) {
start = 1;
end = th_arg->num/2;
} else if (th_arg->id == 1) {
start = th_arg->num / 2;
end = th_arg->num + 1;
} else {
return NULL;
}
for(i=start; i < end; i++) {
th_arg->result[th_arg->id] *= i;
}
return NULL;
}
int factorial2(int n) {
pthread_t threads[2];
int rc;
int result[2];
thread_arg_t th_arg[2];
for(i=0; i<2; i++) {
th_arg[i].id = i;
th_arg[i].num = n;
th_arg[i].result = result;
rc = pthread_create(&threads[i], NULL, thread_func, (void *)&th_arg[i]);
if (rc){
printf("pthread_create() failed, rc = %d\n", rc);
exit(1);
}
}
/* wait for threads to finish */
for(i=0; i<2; i++) {
pthread_join(thread[i], NULL);
/* compute final one multiplication */
return (result[0] * result[1]);
}
The pthread library implementation should take care of parallelizing the work of two threads for you. Also, this example can be generalized for N threads with minor modifications.

glibc detected free() while using posix threads in C

I keep getting this "glibc detected free(): invalid next size (fast)" error but dont know exactly why. I read it is because of an out of bounds error but dont see anywhere in my code where this could be happening, does anyone see anything I missed?
Here is my code:
typedef struct
{
int* inputData;
int* histogramData;
int numElements;
pthread_t* tid;
} threadInput;
void* threadRoutine(void* argv)
{
// initializers
int i, avgInputSize, lastInputSize, threadStart, threadEnd, threadNum, numThreadsUsed;
// stores input data into tempData
threadInput* tempData = (threadInput*) argv;
// calculates the required number of threads
numThreadsUsed = NUM_THREADS;
if(NUM_THREADS > tempData->numElements)
{
numThreadsUsed = tempData->numElements;
}
// create histogram
for(threadNum = 0; threadNum < numThreadsUsed; threadNum++)
{
if(tempData->tid[i] == pthread_self())
{
// finds start and end of data set for thread
if(tempData->numElements > numThreadsUsed)
{
avgInputSize = (int)((tempData->numElements)/NUM_THREADS);
threadStart = threadNum*avgInputSize;
if(i < (NUM_THREADS-1))
{
threadEnd = ((threadNum+1)*avgInputSize);
}
else if(i == (NUM_THREADS-1))
{
threadEnd = (tempData->numElements);
}
}
else
{
threadStart = i;
threadEnd = i + 1;
}
// creates histogram
pthread_mutex_lock(&lock);
for(i = threadStart; i < threadEnd; i++)
{
tempData->histogramData[tempData->inputData[i]]++;
}
pthread_mutex_unlock(&lock);
}
}
pthread_exit(0);
}
void compute_using_pthreads(int *input_data, int *histogram, int num_elements, int histogram_size)
{
// initializers
int i, j;
threadInput* input = malloc(sizeof(threadInput*));
input->inputData = malloc(sizeof(input_data));
input->histogramData = malloc(sizeof(histogram));
input->tid = malloc(NUM_THREADS*sizeof(pthread_t));
// enters data into struct
input->inputData = input_data;
input->histogramData = histogram;
// Create threads
for(i = 0; i < NUM_THREADS; i++)
pthread_create(&input->tid[i], NULL, threadRoutine, (void*) &input);
// reaps threads
for(i = 0; i < NUM_THREADS; i++)
pthread_join(input->tid[i], NULL);
pthread_mutex_destroy(&lock);
// frees space
free(input->inputData);
free(input->histogramData);
free(input->tid);
free(input);
}
This is a mistake:
threadInput* input = malloc(sizeof(threadInput*));
as it is only allocating enough space for threadInput*, when it should be allocating for a threadInput:
threadInput* input = malloc(sizeof(*input));
Similar error with input_data and histogram in that a sizeof(int*) is being allocated instead of sizeof(int).

Reading array from threads, c, cygwin

I'm pretty new to threads and would like some insight. I'm trying to get the percentage each thread has completed for its calculation. Each thread will report its percentage to a different element of the same array. I have this working with pthread_join immediately after pthread_create and a separate thread for reading all the values of the array and printing the percentage but when I have all threads running after each other without waiting for the previous one to finish I get some weird behavior. This is how I'm accessing the shared (global) array.
//global
int *currentProgress;
//main
currentProgress = malloc(sizeof(int)*threads);
for(i=0; i<threads; i++)
currentProgress[i] = 0;
//child threads
currentProgress[myId] = (int)percent; //myId is unique
//progress thread
for(i=0; i<threads; i++)
progressTotal += currentProgress[i];
progressTotal /= threads;
printf("Percent: %d", progressTotal);
This is essentially the code I think is not being used correctly for multi-threads. When I print out the state of the shared array, I notice that as soon as another thread starts accessing the array (different element though), the previous element immediately goes to some random number... -2147483648 and when the latter element finishes the prior element continues like normal. Should I be using semaphores for this? I thought I could access different elements of an array at the same time and I thought reading them wasn't an issue.
This is the entire code:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <pthread.h>
#include <string.h>
#define STDIN 0
int counter = 0;
uint64_t *factors;
void *getFactors(void *arg);
void *deleteThreads(void *arg);
void *displayProgressThread(void *arg);
int *currentProgress;
struct data
{
uint64_t num;
uint64_t incrS;
uint64_t incrF;
int threads;
int member;
} *args;
int main(int argc, char *argv[])
{
if(argc < 3) {printf("not enough arguments"); exit(1);}
int i;
int threads = atoi(argv[2]);
pthread_t thread_id[threads];
pthread_t dThread;
currentProgress = malloc(sizeof(int)*threads);
for(i=0; i<threads; i++)
currentProgress[i] = 0;
args = (struct data*)malloc(sizeof(struct data));
args->num = atoll(argv[1]);
args->threads = threads;
uint64_t increment = (uint64_t)sqrt((uint64_t)args->num)/threads;
factors = (uint64_t*)malloc(sizeof(uint64_t)*increment*threads);
pthread_create(&dThread, NULL, displayProgressThread, (void*)args);
//for the id of each thread
args->member = 0;
for(i=0; i<threads; i++)
{
args->incrS = (i)*increment +1;
args->incrF = (i+1)*increment +1;
pthread_create(&thread_id[i], NULL, getFactors, (void*)args);
usleep(5);
}
for(i=0; i<threads; i++)
{
pthread_join(thread_id[i], NULL);
}
sleep(1);
printf("done\n");
for (i=0; i<counter; i++)
printf("\n%llu : %llu", factors[++i], factors[i]);
return 0;
}
void *getFactors(void *arg)
{
uint64_t count;
int myId;
int tempCounter = 0, i;
struct data *temp = (struct data *) arg;
uint64_t number = temp->num;
float total = temp->incrF - temp->incrS, percent;
myId = temp->member++;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
for(count=temp->incrS; count<=temp->incrF; count++)
{
percent = (float)(count-temp->incrS)/total*100;
currentProgress[myId] = (int)percent;
if (number%count == 0)
{
factors[counter++] = count;
factors[counter++] = number/count;
}
usleep(1);
}
usleep(1);
pthread_exit(NULL);
}
void *displayProgressThread(void *arg)
{
struct data *temp = (struct data *) arg;
int toDelete = 0;
while(1)
{
int i;
int progressTotal = 0;
char *percent = malloc(sizeof(char)*20);
for(i=0; i<toDelete; i++)
printf("\b \b");
for(i=0; i<temp->threads; i++){
progressTotal += currentProgress[i];
}
progressTotal /= temp->threads;
printf("|");
for(i=0; i<50; i++)
if(i<progressTotal/2)
printf("#");
else
printf("_");
printf("| ");
sprintf(percent, "Percent: %d", progressTotal);
printf("%s", percent);
toDelete = 53 + strlen(percent);
usleep(1000);
fflush(stdout);
if(progressTotal >= 100)
pthread_exit(NULL);
}
}
There are some non synchronized pieces of code that are accessed by the threads which cause this problem.
One first place to be synchronized is:
myId = temp->member++;
But more importantly is that, the main thread is doing:
args->incrS = (i)*increment +1;
args->incrF = (i+1)*increment +1;
while at the same time in the threads:
for(count=temp->incrS; count<= temp->incrF; count++)
{
percent = (float)(count-temp->incrS)/total*100;
currentProgress[myId] = (int)percent;
if (number%count == 0)
{
factors[counter++] = count;
factors[counter++] = number/count;
}
usleep(1);
}
The unsynchronized accesses mentioned above affect the calculation of percent value which results in such abnormal happenings. You have to do synchronization in all these places in order to get the kind of behavior you would expect.

Resources