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.
Related
I am trying to produce a race condition (assuming that there exists a critical section in the csfunc) with the following sample code:
#include <stdio.h>
#include <pthread.h>
int cs = 0;
void* csfunc(void* arg){
for (int i = 0; i < 1000000; i++){
cs++;
cs--;
if (cs!=0){
printf("cs: %d\n", cs);
}
}
}
int main(){
for (int i = 0; i < 100; i++){
pthread_t t;
pthread_create(&t,NULL,csfunc,NULL);
pthread_join(t,NULL);
}
return 0;
}
I assume that 100 threads with 1000000 iterations are enough to do a lot of race conditions. Nonetheless, my code is not producing even one single printing of the value of cs. Any ideas? Or am I missing something?
PS> Please note that I am using the gcc compiler with the following command
gcc cs.c -lpthread -o cs
When you do join, it waits until that thread is finished then continues the loop. So you should put thread handles in an array and wait for all of them.
pthread_t handles[100];
for (int i = 0; i < 100; i++){
pthread_create(&handles[i],NULL,csfunc,NULL);
}
for (int i = 0; i < 100; ++i)
pthread_join(handes[i],NULL);
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.
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.
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
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.