简体   繁体   中英

C linux sem_wait doesn't work (sometimes) in threads

I paste only model, which shows the problem. In function:
int get_random_prime(mpz_t number) I've got: sem_wait(&prime_count); and it doesn't work properrly.It waits and waits and waits even if semaphore is greater that 0.

#include<gmp.h>
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>

size_t number_of_cores=2;   
pthread_mutex_t mutex_queue;    
sem_t prime_count;              
sem_t threads_count;                    
size_t last_length=0;           
size_t prime_got=0;             
char manager_on=0;              

mpz_t prime;


get_random_odd(mpz_t output,size_t length){

    size_t i;
    size_t dev_random;
    int randomFile= open("/dev/urandom", O_RDONLY);

    read(randomFile,&dev_random,8);
    mpz_set_ui(output,dev_random);

    for(i=1;i<(length/64);i++){
        read(randomFile,&dev_random,8);
        mpz_mul_2exp (output,output, 64);
        mpz_add_ui(output,output,dev_random);
    }

    close(randomFile);

    mpz_setbit(output,length-1);
    mpz_setbit(output,0);
}

void* get_random_prime_thread(void* ptr_length){
    size_t result = 0;
    size_t i;
    size_t length = *((size_t*)ptr_length);
    mpz_t number;
    mpz_init(number);

    //do{
        get_random_odd(number, length);
        i=0;
    /*  do{
            result=miller_rabin_test(number);
            i++;
        }while(result==1 && i<prime_precision);*/
    //}while(result==0);

    pthread_mutex_lock(&mutex_queue);
    mpz_set(prime,number);
    pthread_mutex_unlock(&mutex_queue);

    sem_post(&prime_count);
    mpz_clear(number);  
    pthread_exit(NULL);

};

void* get_random_prime_manager_start(void* length){
    size_t i;
    size_t size=32;
    pthread_t *threads=malloc(sizeof(pthread_t)*size);
    manager_on =1;

    pthread_t rc;

    pthread_mutex_init(&mutex_queue,NULL);
    sem_init(&threads_count,0,number_of_cores);
    sem_init(&prime_count,0,0);

    i=-1;

    do{
        sem_wait(&threads_count);
        i++;
                printf("PROCES:%d\n",i);
        if(i>=size){
            threads=realloc(threads,size*2);
        }
        rc=pthread_create(&threads[i],NULL,get_random_prime_thread,length);
        if(rc){
            printf("%s\n",strerror(errno));
            pthread_exit((void*)-1);
        }
    }while(manager_on);

    for(i;i>0;i--){
        pthread_cancel(threads[i]);
    }

    free(threads);

    pthread_mutex_destroy(&mutex_queue);
    sem_destroy(&threads_count);
    sem_destroy(&prime_count);
    pthread_exit(NULL);
}

void* get_random_prime_manager_stop(){
    manager_on=0;
}

int get_random_prime(mpz_t number){

    sem_wait(&prime_count);
    printf("GET\n");
    pthread_mutex_lock(&mutex_queue);
    mpz_set(number,prime);
    pthread_mutex_unlock(&mutex_queue);
    sem_post(&threads_count);
    return 0;
};

int main(){
    mpz_init(prime);
    size_t rc;
    size_t length=1024;
    pthread_t thread;
    mpz_t p,q,n;
    mpz_init(p);
    mpz_init(q);
    mpz_init(n);

    size_t half_length=length/2;
    rc=pthread_create(&thread,NULL,get_random_prime_manager_start,(void*)&half_length); 
    if(rc){
        printf("%s\n",strerror(errno));
        return -1;
    }

    do{
        get_random_prime(p);
        get_random_prime(q);

        mpz_mul(n,p,q);
    }while( mpz_sizeinbase(n,2)==length);

    get_random_prime_manager_stop();

    mpz_clear(p);
    mpz_clear(q);
    mpz_clear(n);
}

Is it possible that thread wait on semaphore that hasn't been initiated yet?

You need to make sure the sem_init calls complete before you try to use any of the semaphores. The best way to do this is to call get_random_prime_manager_start normally and let it initialize the semaphores, start a thread, and then return. That way, you are assured that the manager is sufficiently started for it to be safe to use it when the function returns.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM