Threads not acting on global variable - c

I have a huge multi-threaded code base. There are 100 threads. 99 threads have a function do_thread_operations associated with each of them. 100th thread has an operation monitor_99threads associated with it.
do_thread_operations have infinite loop, so they never stop. monitor_99threads keeps track of time. One minute after it was started, it has to close all 99 threads and return to the main thread.
Following is my code.
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
int *to_close_thread;
void * do_thread_operations(void * thread_data){
int i = *(int *)thread_data;
while (1){
//do something
if (to_close_thread[i]) break;
}
}
void * monitor_99threads(void * data){
int i = 0;
while(1){
i++;
if(i > 60){
for (int i = 0; i < 99; ++i){
printf("Closing %d", i);
to_close_thread[i] = 1;
}
}
}
}
int main(){
to_close_thread = (int *)malloc(99 * sizeof(int));
memset(to_close_thread, 0, 99*sizeof(int));
pthread_t threads[100];
for (int i = 0; i < 99; ++i){
int j = i;
pthread_create(&threads[i], NULL, do_thread_operations, (void *)&j);
}
pthread_create(&threads[99], NULL, monitor_99threads, NULL);
for (int i = 0; i < 100; ++i){
pthread_join(threads[i], NULL);
}
}
Problem is that although closing prints, the threads do not break out of their loops.

In addition to the problems described by #P.P., there appears to be a synchronization problem with the referent of to_close_thread. Since the elements are not _Atomic and they are accessed without protection of a mutex, semaphore, or other synchronization object, the do_thread_operations() threads may not ever see any writes performed by control_99threads().
Note also, by the way, that it's a bit silly to pass a pointer to an offset from the base of to_close_thread as the thread argument, when you could instead just pass a pointer directly to the appropriate element. Then you don't need any kind of auxiliary variable:
for (int i = 0; i < 99; ++i){
pthread_create(&threads[i], NULL, do_thread_operations,
(void *) (to_close_thread + i));
}
The do_thread_operations can just cast it back to an int * and dereference it directly (under protection of a mutex or other appropriate synchronization object).

Here,
for (int i = 0; i < 99; ++i){
int j = i;
pthread_create(&threads[i], NULL, do_thread_operations, (void *)&j);
}
You are passing the address of j, which has block scope and has auto storage duration. You should something like:
int arr[100] = {0}; /* adjust the number or allocate using malloc as per needs */
for (int i = 0; i < 99; ++i){
arr[i] = i;
pthread_create(&threads[i], NULL, do_thread_operations, &arr[i]);
}
Another problem is your monitor thread doesn't break after sending closing message. As it is, it's running in an infinite loop. You probably need a break; statement when (whatever) condition is met.

Related

Thread access static variable cause segmentation error [duplicate]

This question already has answers here:
initializing a static variable in header
(4 answers)
Closed 5 years ago.
I'm trying to compare performance of methods about adding two matrix.
one method is just to add.
the other method is to use threads.
but I have a trouble about segmentation error when a thread access a static variable!
Here is my code.
main.c
#include "matrixProcessor.h"
void main()
{
time_t s0, e0;
int i;
int status;
inputVec1 = (int*)malloc(sizeof(int)*(SIZE*SIZE));
inputVec2 = (int*)malloc(sizeof(int)*(SIZE*SIZE));
outputVec = (int*)malloc(sizeof(int)*(SIZE*SIZE));
srand(time(NULL));
initializeVector(inputVec1);
initializeVector(inputVec2);
//printf("=== INPUT VECTOR 1 ===\n");
//printVector(inputVec1);
//printf("=== INPUT VECTOR 1===\n");
//printVector(inputVec2);
//s0 = clock();
//addVec(inputVec1, inputVec2, outputVec);
//e0 = clock();
//printf("Basic Method Time : %f (s)\n",(double)(e0-s0)/CLOCKS_PER_SEC);
s0 = clock();
for(i = 0; i < NUM_THREAD; i++)
{
printf("%d-Thread Call\n",i);
pthread_create(&tid[i], NULL, &addProc, (void*)&i);
sleep(1);
}
e0 = clock();
printf("=== OUTPUT VECTOR===\n");
printVector(outputVec);
printf("Thread Method Time : %f (s)\n",(double)(e0-s0)/CLOCKS_PER_SEC);
free(inputVec1);
free(inputVec2);
free(outputVec);
}
matrixProcessor.c
#include "matrixProcessor.h"
void initializeVector(int* matPtr)
{
int i = 0;
for(i = 0; i < SIZE*SIZE ; i++)
{
matPtr[i] = rand()%100;
}
}
void addVec(int* inputVec1, int* inputVec2, int* outputVec)
{
int i = 0;
for(i = 0; i < SIZE * SIZE; i++)
{
outputVec[i] = inputVec1[i] + inputVec2[i];
}
}
void* addProc(void *p)
{
int* idx = (int*)p;
int count = (SIZE * SIZE) / NUM_THREAD;
int i;
printf("idx value : %d\n",*idx);
printf("Test : %d ", inputVec1[0]);
for(i = (*idx) * count ; i < (*idx)*count + count; i++)
{
outputVec[i] = inputVec1[i] + inputVec2[i];
}
return NULL;
}
void printVector(int* vec)
{
int i = 0;
int j = 0;
for(i = 0; i < SIZE ; i++)
{
for(j = 0; j < SIZE; j++)
{
printf("%d\t", vec[SIZE * i + j]);
}
printf("\n");
}
}
matrixProcessor.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#define SIZE 10
#define NUM_THREAD 10
pthread_t tid[NUM_THREAD];
static int* inputVec1;
static int* inputVec2;
static int* outputVec;
void initializeVector(int* matPtr);
void printVector(int* vec);
void addVec(int* inputVec1, int* inputVec2, int* outputVec);
void* addProc(void *p);
when compiling, i use -static - lpthread options.
I'm sure that accessing static variable cause segmentation error,
because this program prints some messages before reaching a code line which access static variable.
Here is result.
0-Thread Call
idx value : 0
Segmentation Error! ./main
Please someone help me..!
There are multiple problems in your code. The two that jump right out to me are listed below.
First, this one:
pthread_create(&tid[i], NULL, &addProc, (void*)&i);
What's the value of i when the child thread accesses it? It can be anything, because it changes as the main thread spawns more threads and continues to run.
Second, what do you think these free() statements do when they're executed while the child threads are still running:
free(inputVec1);
free(inputVec2);
free(outputVec);
When your code makes those calls, the child threads are still running since you don't call pthread_join() to make sure they've all completed.
You likely get the segmentation violation because your threads are accessing free()'d memory.

Deadlock prevent

Need help how to prevent the deadlock for the code in blow i have written. or any suggestion i need to fix the code in order to get rid of deadlock?
also when i run in Linux i got a Segmentation fault (core dumped).
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#include <semaphore.h>
int cnt;
int *bites;
int *old_bites;
sem_t *sticks;
void *roger(void *arg) {
int rog = *(int*)arg;
for(;;) {
sem_wait(&(sticks[rog])); // left
sem_wait(&(sticks[(rog + 1) % cnt])); // right
bites[rog]++;
sem_post(&(sticks[(rog + 1) % cnt])); // right
sem_post(&(sticks[rog])); // left
}
pthread_exit(NULL);
return NULL;
}
int main(int argc, char *argv[]) {
int i;
pthread_t *rogers;
int *pos;
cnt = (int)strtol(argv[1], NULL, 10);
rogers = (pthread_t *)calloc(cnt, sizeof(pthread_t));
pos = (int *)malloc(cnt * sizeof(int));
bites = (int *)calloc(cnt, sizeof(int));
old_bites = (int *)calloc(cnt, sizeof(int));
sticks = (sem_t *)calloc(cnt, sizeof(sem_t));
for(i = 0; i < cnt; i++) {
sem_init(&(sticks[i]), 0, 1);
}
for(i = 0; i < cnt; i++) {
pos[i] = i;
pthread_create(&(rogers[i]), NULL, roger, (void *)&pos[i]);
}
for(;;) {
bool dead = true;
usleep(50000);
for(i = 0; i < cnt; i++) {
if(bites[i] != old_bites[i]) {
dead = false;
}
}
if(dead) {
exit(EXIT_SUCCESS);
}
for(i = 0; i < cnt; i++) {
printf("%8X", bites[i]);
}
printf("\n");
for(i = 0; i < cnt; i++) {
old_bites[i] = bites[i];
}
}
for(i = 0; i < cnt; i++) {
pthread_join(rogers[i], NULL);
}
for(i = 0; i < cnt; i++) {
sem_destroy(&(sticks[i]));
}
exit(EXIT_SUCCESS);
}
yes I would expect this to deadlock. I don't know what you're using for cnt, but let's pretend it's 1. In this case, only 1 thread will get created. This thread will sem_wait(&(sticks[0]));. Then in the very next line it will sem_wait(&(sticks[(0+1) % 1 == 0]));. Since the initial value of your semaphores are 1, you can't wait on the same semaphore twice without a sem_post first. Thus, this thread will wait forever for a sem_post that it can't reach because it's sem_waiting.
Now consider the case where cnt > 1 (let's just say cnt == 2 to make it simpler). This will spawn thread0 and thread1 with 0 and 1 passed as arguments to their functions. This situation could happen:
Thread0 executes sem_wait(&(sticks[0]));
Context switch: thread1 executes sem_wait(&(sticks[1]));
thread1 executes sem_wait(&(sticks[(1+1) % 2 == 0])); // this blocks because thread0 has already sem_wait'ed this semaphore to 0
Context switch: thread0 executes sem_wait(&(sticks[(0+1) % 2 == 1])); // this blocks because thread1 has already sem_wait'ed this semaphore to 0
Now you have each thread waiting for a sem_post from the other before you can continue ==> deadlock. I would expect this scenario to scale for increasing values of cnt, although the situations that would lead to deadlocks would become more complex.
Why are you using 2 semaphores to protect a single resource? This theory sounds wrong to me. You lose your atomicity with that approach (correct me if I'm wrong obviously).
Also, you have a race condition with your bites array. The main thread isn't observing synchronization before it reads from it. This may be related to the seg fault.

Calling a void* function from main in C

Currently I am working on a program that uses threads to calculate the sum of square roots. My program works, however one of the requirements is to use the main thread to find the initial value, and as soon as I call the function Void *calc from main, the program breaks. Is there a certain way to make such a function call? Is this because the function is a pointer? Any help is appreciated.
#include <pthread.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#define NUM_THREADS 3
int ARGV;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
double total = 0;
void *calc(void* t){
int ph = (int)t + 1;
int start, stop, interval_size;
interval_size = ARGV/(NUM_THREADS + 1);
start = ((ph) * interval_size) + 1;
stop = (ph * interval_size) + 1;
double ttl;
int i;
for (i = start; i <= stop; i++){
ttl = ttl + sqrt(i);
printf("Total Thread %i %lf\n", ph, ttl);
}
pthread_mutex_lock(&m);
total = total + ttl;
pthread_mutex_unlock(&m);
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
int i;
double ttl;
ARGV = atoi(argv[1]);
pthread_t ti[NUM_THREADS];
calc(0);
for (i = 0; i < NUM_THREADS; i++) {
pthread_create(&ti[i], NULL, calc,(void *)i);
}
/*for (i = 1; i <= (ARGV / 4) ; i++){
ttl = ttl + sqrt(i);
}*/
for (i = 0; i < NUM_THREADS; i++) {
pthread_join(ti[i], NULL);
}
total = total + ttl;
printf("Result: %lf\n", total);
}
The program breaks as in the function seems to only be called once, instead of each thread using the function. The only value printed out is some vague incorrect number.
Your calc function does pthread_exit. Now pthread_exit can and should be called from the main thread, so that's fine
To allow other threads to continue execution, the main thread
should terminate by calling pthread_exit() rather than exit(3).
But since this happens before any other thread has been created, the program just exits straight away, without ever starting other threads.

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.

pthread_join() and frozen execution

I was trying to build a system (in Linux) with a simulated time execution, coordinating threads with semaphores, the idea was to make them all work cycles of one second, to have a accurate simulation the threads must wait for every other thread to end its execution, on the current simulated second.
I had a really annoying memory leak, because the main thread finished the work without joining the other threads (newbie mistake), so to solve it I added pthread_join() instructions for every thread, supposing they were finishing its work, since every thread execution was inside a while loop with a global condition to check, which was changed by the main thread before finishing. Sadly even with that, now, most of the executions of the program, it gets frozen waiting for the thread to finish.
I need to find a way to end every thread execution, even ignoring its full work, but making sure the join is made (and so the memory is freed).
Now I post a compilable code with the error, you can compile it with gcc -o sample -pthread sample.c -lm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
#include <math.h>
#define SIZE 100
#define READY 12345
#define END 99
#define TIME 3600
int *advicer;
int *td;
pthread_t *phones;
sem_t *counter;
int ready;
int end;
void cycle(int cycles){
int i,j,k;
for(i = 0; i < cycles; i++){
k = 1;
while(k){
k = 0;
for(j = 0; j < SIZE; j++){
if(advicer[j] == 0){
k = 1;
break;
}
}
}
for(j = 0; j < SIZE; j++){
advicer[j] = 0;
sem_post(&counter[j]);
}
}
}
void *do_something(void *td){
int t;
t = *((int *) td);
while(end != END){
if(end == END)
break;
t += t;
advicer[t] = 1;
sem_wait(&counter[t]);
}
pthread_exit(NULL);
}
void all_free(){
int i,j;
end = END;
printf("reach %d\n",end);
for(i = 0; i < SIZE; i++)
sem_post(&counter[i]);
printf("reach2\n");
for(i = 0; i < SIZE; i++){
pthread_join(phones[i],NULL);
}
free(phones);
printf("reach3\n");
for(i = 0; i < SIZE; i++)
sem_destroy(&counter[i]);
free(counter);
free(td);
free(advicer);
}
void main(){
int i,my_count;
counter = (sem_t *)malloc(sizeof(sem_t)*SIZE);
advicer = (int *)malloc(sizeof(int)*SIZE);
td = (int *)malloc(sizeof(int)*SIZE);
phones = (pthread_t *)malloc(sizeof(pthread_t)*SIZE);
for(i = 0; i < SIZE; i++){
sem_init(&counter[i], 0, 0);
advicer[i] = 0;
}
ready = READY;
my_count = 0;
end = 0;
for(i = 0; i < SIZE; i++){
td[i] = i;
pthread_create(&(phones[i]), NULL, do_something, (void *)(&td[i]));
}
printf("starting simulation\n");
while(my_count < TIME){
cycle(60);
printf("hello\n");
my_count += 60;
}
printf("simulation ended\n");
all_free();
}
The following section could lead to the lock:
for(i = 0; i < m->pp; i++)
sem_post(&counter[i]);
for(i = 0; i < m->pp; i++){
if(m->ppl[i] != NULL){
phone_free(m->ppl[i]);
}
...
}
You call sem_post() for one thread only (which unlocks it) then call pthread_join() (via phone_free()) for all threads, which would block for all but the one you called sem_post() for, as the others do not terminate, because stuck in sem_wait().
Although you called sem_post() during main execution (cycle()) the value might have been fetched by the thread prior to your call to the end-execution code (map_free()) pthread_join() (via phone_free()).
To cancel a thread you could use pthread_cancel().
To avoid the memory leak when having left a thread and not calling pthread_join() on it, you could detach the thread using pthread_detach(). The OS then frees all of the thread's resouce when the thread terminates.

Resources