Deadlock prevent - c

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.

Related

Printing in order with c threads

Given this code:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
void *findPrimes(void *arg)
{
int val = *(int *)arg;
for (int i = val * 1000; i < val * 1000 + 1000; i++)
{
int isPrime = 1;
for (int j = 2; j < i; j++)
{
if (i % j == 0)
{
isPrime = 0;
break;
}
}
if (isPrime)
{
printf("%d\n", i);
}
}
pthread_exit(NULL);
}
int main()
{
pthread_t p[3];
int val[3] = {0, 1, 2};
for (int i = 0; i < 3; i++)
{
pthread_create(&p[i], NULL, findPrimes, &val[i]);
}
for (int i = 0; i < 3; i++)
{
pthread_join(p[i], NULL);
}
return 0;
}
Who prints in 3 threads all the prime number between 0 and 3000.
I want to print them in order, how can i do it?
My professor suggest to use an array of semaphore.
In order to synchronize the actions of all the threads I suggest using a pthread_mutex_t and a pthread_cond_t (a condition variable). You also need a way to share data between threads, so I'd create a struct for that:
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
typedef struct {
unsigned whos_turn;
pthread_mutex_t mtx;
pthread_cond_t cv;
} shared_data;
whos_turn will here be used to tell the threads whos turn it is to print the primes found.
Each thread also needs some thread-unique information. You called it val so I'll call it val here too. We can compare val with whos_turn to decide which thread it is that should print its result. In order to pass both the shared data and val to a thread, you can package that in a struct too:
typedef struct {
unsigned val;
shared_data *sd; // will point to the one and only instance of `shared_data`
} work_order;
Now, findPrimes need somewhere to store the primes it calculates before it's time to print them. Since the range to search is hardcoded, I'd just add an array for that:
#define SEARCH_RANGE (1000ULL)
void *findPrimes(void *arg) {
work_order *wo = arg;
uintmax_t primes[SEARCH_RANGE]; // to store the found primes
int found_count = 0;
for (uintmax_t i = wo->val*SEARCH_RANGE+1; i <= (wo->val+1)*SEARCH_RANGE; i += 2) {
bool isPrime = true;
for (uintmax_t j = 3; j < i; j += 2) {
if (i % j == 0) { // note: both i and j are odd
isPrime = false;
break;
}
}
if (isPrime) {
primes[found_count++] = i;
}
}
if(wo->val == 0) { // special case for the first range
primes[0] = 2; // 1 is not a prime, but 2 is.
}
// ... to be continued below ...
So far, nothing spectacular. The thread has now found all primes in its range and has come to the synchronizing part. The thread must
lock the mutex
wait for its turn (called "the predicate")
let other threads do the same
Here's one common pattern:
// ... continued from above ...
// synchronize
pthread_mutex_lock(&wo->sd->mtx); // lock the mutex
// only 1 thread at a time reaches here
// check the predicate: That is's this thread's turn to print
while(wo->val != wo->sd->whos_turn) { // <- the predicate
// if control enters here, it was not this thread's turn
// cond_wait internally "unlocks" the mutex to let other threads
// reach here and wait for the condition variable to get signalled
pthread_cond_wait(&wo->sd->cv, &wo->sd->mtx);
// and here the lock is only held by one thread at a time again
}
// only the thread whos turn it is reaches here
Now, the thread has reached the point where it is its time to print. It has the mutex lock so no other threads can reach this point at the same time.
// print the collected primes
for(int i = 0; i < found_count; ++i)
printf("%ju\n", primes[i]);
And hand over to the next thread in line to print the primes it has found:
// step the "whos_turn" indicator
wo->sd->whos_turn++;
pthread_mutex_unlock(&wo->sd->mtx); // release the mutex
pthread_cond_broadcast(&wo->sd->cv); // signal all threads to check the predicate
pthread_exit(NULL);
}
And it can be tied together quite neatly in main:
#define Size(x) (sizeof (x) / sizeof *(x))
int main() {
shared_data sd = {.whos_turn = 0,
.mtx = PTHREAD_MUTEX_INITIALIZER,
.cv = PTHREAD_COND_INITIALIZER};
pthread_t p[3];
work_order wos[Size(p)];
for (unsigned i = 0; i < Size(p); i++) {
wos[i].val = i; // the thread-unique information
wos[i].sd = &sd; // all threads will point at the same `shared_data`
pthread_create(&p[i], NULL, findPrimes, &wos[i]);
}
for (unsigned i = 0; i < Size(p); i++) {
pthread_join(p[i], NULL);
}
}
Demo

Threads not acting on global variable

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.

Multiple threads increment shared variable without locks but return "unexpected" output

I'm invoking 100 threads, and each threads should increment a shared variable 1000 times. Since I'm doing this without using mutex locks, the expected output should NOT be 100000. However, I'm still getting 100000 every time.
This is what I have
volatile unsigned int count = 0;
void *increment(void *vargp);
int main() {
fprintf(stdout, "Before: count = %d\n", count);
int j;
// run 10 times to test output
for (j = 0; j < 10; j++) {
// reset count every time
count = 0;
int i;
// create 100 theads
for (i = 0; i < 100; i++) {
pthread_t thread;
Pthread_create(&thread, NULL, increment, NULL);
Pthread_join(thread, NULL);
}
fprintf(stdout, "After: count = %d\n", count);
}
return 0;
}
void *increment(void *vargp) {
int c;
// increment count 1000 times
for (c = 0; c < 1000; c++) {
count++;
}
return NULL;
}
The pthread_join() function suspends execution of the calling thread until the target thread terminates (source). After you create each thread, you wait for it to run and terminate. The threads never execute concurrently. Thus, there's no race condition

Peterson's Algorithm in C for Thread concurrency (segment fault)

Hey guys I'm implementing Peterson's algorithm in C. I have two functions that will be executed by the threads created, one that adds 1 to a variable and other that subtracts 1 to that same variable.
The program receives an argument of type int, that integer is the square root of the number of threads I want to create, for example if I execute it in the terminal typing
./algorithm 10, there will be 10*10 (10 000) threads created.
The program runs ok if y type less than 170 as an argument (There would be 28900 threads created) but if I want to create more than that I got a segment fault, tried using "long long int" variables but that wasn't it.
There is a counter named "cont", the variable will be printed each time cont reaches 10 000.
There is another print for the last result of the variable, that should always be 0 because n threads added 1 and n threads subtracted 1.
I want to know why I'm getting a Segment Fault, if there is a limit of threads to be created, or if it is something in my code.
I'm running it using the next command to use only one processor cause Peterson's algorithm only work perfectly on mono-processor systems:
taskset -c 0 ./alg3 100
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
long int n;
long int var = 0;
long int cont = 1;
int flag[] = {0, 0};
int turn = 0;
void* sum(void* data) {
//int n = *((int*)data);
int i;
turn = 2;
flag[0] = 1;
while (turn == 2 && flag[1]);
cont++;
var += 1;
if (cont == 10000) {
printf("varsum=%ld\n", var);
cont = 1;
}
flag[0] = 0;
}
void* rest(void* data) {
//int n = *((int*)data);
int i;
turn = 1;
flag[1] = 1;
while (turn == 1 && flag[0]);
cont++;
var -= 1;
if (cont == 10000) {
printf("varres=%ld\n", var);
cont = 1;
}
flag[1] = 0;
}
main(int argc, char *argv[]) {
long int i;
n = atoi(argv[1]);
n *= n; //n*n is the actual number of threads that will be created
pthread_t tid[n];
for (i = 0; i < n; i++) {
pthread_create(&tid[i], NULL, sum, NULL);
//cont++;
}
for (i = 0; i < n; i++)
pthread_join(tid[i], NULL);
for (i = 0; i < n; i++) {
pthread_create(&tid[i], NULL, rest, NULL);
//cont++;
}
for (i = 0; i < n; i++)
pthread_join(tid[i], NULL);
printf("main() reporting that all %ld threads have terminated\n", i);
printf("variable=%ld\n", var);
} /* main */
First of all, of course there is limit to create threads. It is decided by the stack size of each thread and hardware, details suggest google it...
Segment fault reason:
You didn't check the return value of function pthread_create, when 'n' ls large enough, pthread_create will failed, then pthread_join may use the nonexistent thread_t as the first input parameter. The following code (change from your example) can test how many threads in you can create.
int rc = 0, thread_num = 0;
for (i = 0; i < n; i++) {
rc = pthread_create(&tid[i], NULL, sum, NULL);
if (rc)
{
printf("pthread_crate failed, thread number: %d, error code: %d\n", thread_num, rc);
}
thread_num++;
}
printf("created %d threads.\n", thread_num);
Add error checking at least to pthread_create() to avoid passing an invalid pthread_t variable to pthread_join():
int main(int arc, char ** argv)
{
...
pthread_t tid[n];
int result[n];
for (i = 0; i < n; i++) {
result[i] = errno = pthread_create(&tid[i], NULL, sum, NULL);
if (0 != errno) {
perror("pthread_create() failed");
}
}
for (i = 0; i < n; i++) {
if (0 == result(i]) {
errno = pthread_join(tid[i], NULL);
if (0 != errno) {
perror("pthread_join() failed");
}
}
}
...
Also always protect concurrent access to variables wich are written to, count here. To do so use a pthread_mutex_t variable.

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