0

thanks for reading! I am using C PThreads library to experiment with threading. Basically what I am doing is reading in a text file that the first line has two numbers: amount of threads, and amount of rounds. What this will do is create threads and loop them a rounds amount of time to generate random numbers.

What happens is that I get the correct numbers based off a function for the first round but then the function never gets called after that.

This is the code

int main(){
    FILE *fp = fopen(argv[1], "r");
    //Print the name of the file
    printf("%s\n", argv[1]);
    if(fp == NULL){
        printf("Error opening file\n");
        return 1;
    }
    int num_threads, num_rounds;
    fscanf(fp, "%d %d", &num_threads, &num_rounds);
    struct thread_args *args = malloc(sizeof(struct thread_args) * num_threads);
    for(int i = 0; i < num_threads; i++){
        fscanf(fp, "%d %d %d %d", &args[i].a, &args[i].c, &args[i].m, &args[i].x);
        args[i].points = 0;
    }
    //close the file
    fclose(fp);
    //Create the threads. Each thread will be assigned a number from 0 to num_threads-1.
    pthread_t tid[num_threads];
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    //Create the threads
    for(int i = 0; i < num_threads; i++){
        pthread_create(&tid[i], &attr, runner, &args[i]);
    }
    //For each round
    for (int i = 1; i<num_rounds;i++ ){
        for (int j = 0;j<num_threads;j++){
            pthread_cond_signal(&cVar);
            run = 1;
            sleep(1);
        }
        printf("\n");
    }
    //Join the threads
    for(int i = 0; i < num_threads; i++){
        pthread_join(tid[i], NULL);
    }
    //Free the memory
    free(args);
    return 0;
}

This is main ^

This is the runner function:

void *runner(void *param){
    
    struct thread_args *args = (struct thread_args *)param;
    int x = args->x;
    int a = args->a;
    int c = args->c;
    int m = args->m;
    int points = args->points;
    int x_new;
    while(run == -1){
        pthread_mutex_lock(&mVar);
        pthread_cond_wait(&cVar, &mVar);
        x_new = f1(x, a, c, m);
        printf("%d\n", x_new);
        args->x = x_new;
        pthread_mutex_unlock(&mVar);
    }

    pthread_exit(NULL);

}

and this is the function used to create a "random" number:

    long int x1 = x*a+c;
    return (int)(x1%m);
}```

Any explanation for this would be great! Thanks!
  • 3
    A bare `pthread_cond_wait(&cVar, &mVar);` is already a sign of doom. One does not wait on a condition variable without assessing the predicate data *first* (under the protection of the mutex). the condition variable isn't state; it's a *signal mechanic*. – WhozCraig Feb 22 '22 at 04:02
  • The loop in `runner` expects `run` to be -1, but `main` only sets it to 1. See [mcve]. – user3386109 Feb 22 '22 at 04:05
  • Sorry I should have been more specific, run is a global variable intialized to -1 – SeeMort Feb 22 '22 at 04:06
  • And `main` sets it to 1 after the first call `pthread_cond_signal`. – user3386109 Feb 22 '22 at 04:08
  • Okay, this makes sense, so should I ever change run or just keep it set to -1 then? – SeeMort Feb 22 '22 at 04:10
  • 2
    You need to refactor the usage of your condvar+mutex for what they should be designated: predicate protection and change signaling. I know, it seems complicated, and frankly, it's the hardest thing to understand about the purpose of cvars. At the risk of seeming dreadfully self-gratifying, [see this answer](https://stackoverflow.com/questions/14924469/does-pthread-cond-waitcond-t-mutex-unlock-and-then-lock-the-mutex/14925150#14925150) to a thinly related question. It was a long-winded answer to what was actually a basic question, but has been popular as a general how-to as well. – WhozCraig Feb 22 '22 at 04:36

0 Answers0