[c] Programmazione concorrente

di il
9 risposte

[c] Programmazione concorrente

Salve a tutti sono alle prime armi nella programmazione
ho un problema nell'implementazione del codice (dopo 10 cicli riga 68) il programma crasha dandomi il seguente errore

/nptl/pthread_mutex_lock.c:352: __pthread_mutex_lock_full: Assertion `INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust' failed.
Aborted
ps non penso sia il solo errore
grazie in anticipo per qualsiasi consiglio suggerimento
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

#include<pthread.h>
#include<semaphore.h>

#define carta 0
#define contanti 1
#define contanti_e_carta 2
#define biglietti_tot 2000 //numero di biglietti totati disponibili per l'evento
#define rivenditori_n 10   //numero di rivenditori disponibili
#define lotto_l 20         // numero di biglietti disponibile presso ogni rivenditore
#define acquisto_max 8     //numero massimo di biglietti acquistabili per ogni cliente
#define numero_clienti 200 // numero di clienti
typedef struct Rivenditore{
               int n_biglietti;
               int pagamento;
               int id;
               int count;
               pthread_t tid;
              pthread_mutex_t lock;
              pthread_cond_t disponibili;
              pthread_cond_t ultimati;
} Rivenditore;




typedef struct Cliente{
               int n_biglietti;
               int pagamento;
               int id;
               pthread_t tid;
            Rivenditore* r;
}Cliente;


int biglietti_posseduti_rivenditore;
sem_t lockrivenditori;
int counter_cliente;


Cliente* set_cliente(int n_biglietti,  int id, Rivenditore* r );
void* acquista(void*arg);
void check(int x);
void init(Rivenditore* r);
void* vendita(void* arg);
void transazione(Cliente c);

int main(){
Rivenditore r[rivenditori_n];

init(r);




for(int i=0;i<rivenditori_n;i++){

 pthread_create(&r[i].tid,NULL,vendita,(void*) &r[i]);

}



while(counter_cliente<numero_clienti){
  Cliente *c;
  c=set_cliente(rand()%acquisto_max+1,counter_cliente,&r[rivenditori_n%counter_cliente]);
  if(c->pagamento!=carta)
   pthread_setschedprio(c->tid,120);
 else pthread_setschedprio(c->tid,90);
  pthread_create(&c->tid,NULL,acquista,(void*) c);


 sleep(1);
 printf("contatore clienti %d\n",counter_cliente);
 printf("\ntest %d\n",rivenditori_n%counter_cliente);
 counter_cliente++;

}






for(int i=0;i<rivenditori_n;i++)
 pthread_join(r[i].tid,NULL);


printf("biglietti totali rivenditore %d\n",biglietti_posseduti_rivenditore);

return 0;
}

void* acquista(void* arg){
Cliente* c;
c=(Cliente*) arg;

check(pthread_mutex_lock(&c->r->lock));

 while(c->r->n_biglietti==0)
 pthread_cond_wait(&c->r->ultimati,&c->r->lock); // se i biglietti disponibili sono finiti aspetta

while(c->r->n_biglietti<c->n_biglietti){ // se i biglietti disponibili sono inferiori a quelli richiesti diminuisco la richiesta
c->n_biglietti--;

}
  c->r->n_biglietti-= c->n_biglietti; //aggiorno i biglietti disponibili
transazione(*c);
printf("%lu sta acquistando %d biglietti dal venditore %d ed gli sono rimasti %d\n",pthread_self(),c->n_biglietti,c->r->id,c->r->n_biglietti);

if(c->r->n_biglietti==0 && c->r->count!=rivenditori_n) // se i biglietti sono finiti faccio una signal
pthread_cond_signal(&c->r->disponibili);

check(pthread_mutex_unlock(&c->r->lock));
return NULL;
}


void* vendita(void * arg){
Rivenditore* r;
r=(Rivenditore*)arg;

while(biglietti_posseduti_rivenditore<biglietti_tot && r->count<rivenditori_n){ //ogni rivenditore non puo acquistare piu di un tot biglietti
 sem_wait(&lockrivenditori);

 check(pthread_mutex_lock(&r->lock));
 while(r->n_biglietti>0) //se i biglietti non sono stati completamente venduti mi metto in attesa
 pthread_cond_wait(&r->disponibili,&r->lock);

 r->count++;
 r->n_biglietti+=lotto_l;
 biglietti_posseduti_rivenditore+=lotto_l;// il rivenditore acquistano solo lotti di biglietti
 printf("il rivenditore %d ha acquistato un lotto di biglietti biglietti disponibili %d\n",r->id,r->n_biglietti);

//if(r->count!=0)
 pthread_cond_broadcast(&r->ultimati); //risveglio i clienti in attessa
 check(pthread_mutex_unlock(&r->lock)); //rilascio il mutex tra rivenditore e cliente

sem_post(&lockrivenditori);
}

return NULL;
}


void transazione(Cliente c){
if(c.pagamento==carta)
 sleep(rand()%2);
else sleep(rand()%3+1);

}

void init(Rivenditore* r){
for(int i=0;i<rivenditori_n;i++){
 r[i].n_biglietti=0;
 r[i].id=i;
 r[i].count=0;
 pthread_mutex_init(&r[i].lock,NULL);
 pthread_cond_init(&r[i].ultimati,NULL);
 pthread_cond_init(&r[i].disponibili,NULL);
}
sem_init(&lockrivenditori,0,1);
counter_cliente=1;
biglietti_posseduti_rivenditore=0;

}




Cliente* set_cliente(int n,int id, Rivenditore* r){
Cliente* x=malloc(sizeof(Cliente));
if(x==NULL){
fprintf(stderr,"errore malloc /n");
exit(-1);
}

if(r->pagamento==contanti_e_carta)
x->pagamento=rand()%2;
else x->pagamento=r->pagamento;

x->id=id;
x->n_biglietti=n;

x->r=r;

return x;
}



void check(int x){

if(x!=0){
fprintf(stderr," errore %d\n",x);
exit(-1);}

}

9 Risposte

  • Re: [c] Programmazione concorrente

    A parte l'errore descrivi un po' il tuo programma, cosa dovrebbe fare, come hai tentato di risolvere, quale sarebbe questa riga 68 ...
  • Re: [c] Programmazione concorrente

    Si scusami sono stato molto sintetico nella spiegazione del problema:
    il programma dovrebbe modellare la gestine di una biglietteria, per ogni evento vengono messi a disponizione dei biglietti(biglietti_tot) questi ultimi possono essere acquistati presso n rivenditori(rivenditori_n) ciascun cliente puo' acquistare fino al un max di biglietti(acquisto_max) e decidere se pagare con carta oppure contanti (per la prima e' prevista una transazione piu' rapida e una priorita' alta). alcuni rivenditori accettano solo carta altri entrambi. Ad ogni rivenditore viene assegnato un lotto di biglietti (lotto_l)<<(biglietti_tot).

    riga 68 while(counter_cliente<numero_clienti) dopo 10 iterazioni il programma si ferma e mi da questo errore
    /nptl/pthread_mutex_lock.c:352: __pthread_mutex_lock_full: Assertion `INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust' failed.
    Aborted
    ide usato codeblock ambiente linux 64bit
  • Re: [c] Programmazione concorrente

    A me ha dato un " errore 22 ".

    (codice compilato con gcc)
  • Re: [c] Programmazione concorrente

    vuott ha scritto:


    A me ha dato un " errore 22 ".

    (codice compilato con gcc)
    intendi durante la compilazione? con quale sistema operativo?

    ps per compilare/linkare ho usato gcc -Wall -pthread -o nomefile nomesorgente
  • Re: [c] Programmazione concorrente

    screative ha scritto:


    intendi durante la compilazione?
    No, durante l'esecuzione dopo una decina di "test".

    In particolare ti riporto le ultime righe stampate in Terminale:
    " test 1
    contatore clienti 10

    test 0
    139939811411712 sta acquistando 3 biglietti dal venditore 0 ed gli sono rimasti 4
    errore 22
    "


    screative ha scritto:


    con quale sistema operativo?
    Linux
  • Re: [c] Programmazione concorrente

    vuott ha scritto:


    screative ha scritto:


    intendi durante la compilazione?
    No, durante l'esecuzione dopo una decina di "test".

    In particolare ti riporto le ultime righe stampate in Terminale:
    " test 1
    contatore clienti 10

    test 0
    139939811411712 sta acquistando 3 biglietti dal venditore 0 ed gli sono rimasti 4
    errore 22
    "


    screative ha scritto:


    con quale sistema operativo?
    Linux
    dovrebbe essere invalid argument comunque a me non stampava nulla escudedo il messaggio che ho postato


    ho modificato il codice
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/types.h>
    
    #include<pthread.h>
    #include<semaphore.h>
    
    #define carta 0
    #define contanti 1
    #define contanti_e_carta 2
    #define biglietti_tot 2000 //numero di biglietti totati disponibili per l'evento
    #define rivenditori_n 10   //numero di rivenditori disponibili
    #define lotto_l 20         // numero di biglietti disponibile presso ogni rivenditore
    #define acquisto_max 8     //numero massimo di biglietti acquistabili per ogni cliente
    #define numero_clienti 200 // numero di clienti
    typedef struct Rivenditore{
                   int n_biglietti;
                   int pagamento;
                   int id;
                   int count;
                   pthread_t tid;
                  pthread_mutex_t lock;
                  pthread_cond_t disponibili;
                  pthread_cond_t ultimati;
    } Rivenditore;
    
    
    
    
    typedef struct Cliente{
                   int n_biglietti;
                   int pagamento;
                   int id;
                   pthread_t tid;
                Rivenditore* r;
    }Cliente;
    
    
    int biglietti_posseduti_rivenditore;
    sem_t lockrivenditori;
    int counter_cliente;
    
    
    Cliente* set_cliente(int n_biglietti, Rivenditore* r );
    void* acquista(void*arg);
    void check(int x);
    void init(Rivenditore* r);
    void* vendita(void* arg);
    void transazione(Cliente c);
    
    int main(){
    Rivenditore r[rivenditori_n];
    
    init(r);
    
    
    for(int i=0;i<rivenditori_n;i++){
    
     pthread_create(&r[i].tid,NULL,vendita,(void*) &r[i]);
    
    }
    
    
    
    
    
    while(counter_cliente<numero_clienti){
      Cliente *c;
     srand(time(NULL));
     c=set_cliente(rand()%acquisto_max+1,&r[rand()%10]);
    
      pthread_create(&c->tid,NULL,acquista,(void*) c);
    
    
     sleep(2);
     printf("contatore clienti %d\n",counter_cliente);
    
    }
    
    
    
    
    
    
    for(int i=0;i<rivenditori_n;i++)
     pthread_join(r[i].tid,NULL);
    
    
    printf("biglietti totali rivenditore %d\n",biglietti_posseduti_rivenditore);
    
    return 0;
    }
    
    void* acquista(void* arg){
    Cliente* c;
    c=(Cliente*) arg;
    
    check(pthread_mutex_lock(&c->r->lock));
    
     while(c->r->n_biglietti<=0 && c->r->count<rivenditori_n)
     pthread_cond_wait(&c->r->ultimati,&c->r->lock); // se i biglietti disponibili sono finiti aspetta
    
    while(c->r->n_biglietti<c->n_biglietti){ // se i biglietti disponibili sono inferiori a quelli richiesti diminuisco la richiesta
    c->n_biglietti--;
    
    }
      c->r->n_biglietti-= c->n_biglietti; //aggiorno i biglietti disponibili
    transazione(*c);
    printf("%lu sta acquistando %d biglietti dal venditore %d ed gli sono rimasti %d\n",pthread_self(),c->n_biglietti,c->r->id,c->r->n_biglietti);
    printf(" il venditore %d ha chiesto n%d volte di acuistare i biglietti \n",c->r->id,c->r->count);
    //if(c->r->n_biglietti==0 && c->r->count!=rivenditori_n) // se i biglietti sono finiti faccio una signal
    pthread_cond_signal(&c->r->disponibili);
    
    check(pthread_mutex_unlock(&c->r->lock));
    return NULL;
    }
    
    
    
    
    
    
    void* vendita(void * arg){
    Rivenditore* r;
    r=(Rivenditore*)arg;
    
    while(biglietti_posseduti_rivenditore<biglietti_tot && r->count<rivenditori_n){ //ogni rivenditore non puo acquistare piu di un tot biglietti
     sem_wait(&lockrivenditori);
    
     check(pthread_mutex_lock(&r->lock));
     while(r->n_biglietti>0) //se i biglietti non sono stati completamente venduti mi metto in attesa
     pthread_cond_wait(&r->disponibili,&r->lock);
    
     r->count++;
     r->n_biglietti+=lotto_l;
     biglietti_posseduti_rivenditore+=lotto_l;// il rivenditore acquistano solo lotti di biglietti
     printf("il rivenditore %d ha acquistato un lotto di biglietti biglietti disponibili %d\n",r->id,r->n_biglietti);
    
    //if(r->count!=0)
     pthread_cond_broadcast(&r->ultimati); //risveglio i clienti in attessa
     check(pthread_mutex_unlock(&r->lock)); //rilascio il mutex tra rivenditore e cliente
    
    sem_post(&lockrivenditori);
    }
    
    return NULL;
    }
    
    
    void transazione(Cliente c){
    if(c.pagamento==carta)
     sleep(rand()%2);
    else sleep(rand()%3+1);
    
    }
    
    void init(Rivenditore* r){
    for(int i=0;i<rivenditori_n;i++){
     r[i].n_biglietti=lotto_l;
     r[i].id=i;
     r[i].count=1;
    biglietti_posseduti_rivenditore+=lotto_l;
     pthread_mutex_init(&r[i].lock,NULL);
     pthread_cond_init(&r[i].ultimati,NULL);
     pthread_cond_init(&r[i].disponibili,NULL);
    
    }
    sem_init(&lockrivenditori,0,1);
    counter_cliente=1;
    biglietti_posseduti_rivenditore=0;
    
    }
    
    
    
    
    Cliente* set_cliente(int n, Rivenditore* r){
    Cliente* x=malloc(sizeof(Cliente));
    if(x==NULL){
    fprintf(stderr,"errore malloc /n");
    exit(-1);
    }
    if(r->pagamento==contanti_e_carta){
    x->pagamento=rand()%2;
    pthread_setschedprio(x->tid,90);
    
    }
    else {x->pagamento=r->pagamento;
       pthread_setschedprio(x->tid,120);
    
    }
    
    
    x->id=counter_cliente;
    
    x->n_biglietti=n;
    
    x->r=r;
    counter_cliente++;
    return x;
    }
    
    
    
    void check(int x){
    
    if(x!=0){
    fprintf(stderr," errore %d\n",x);
    exit(-1);}
    
    }
    ma continua a non funzionare la funzione rivenditori va in starvation
  • Re: [c] Programmazione concorrente

    screative ha scritto:


    ho modificato il codice
    ma continua a non funzionare la funzione rivenditori va in starvation
    L'errore ora a me è sparito, ma delle volte non ottengo - appunto - informazioni dal programma.

    Esempio:
    " 139646134126336 sta acquistando 3 biglietti dal venditore 9 ed gli sono rimasti 0
    il venditore 9 ha chiesto n1 volte di acuistare i biglietti
    contatore clienti 68
    contatore clienti 69
    contatore clienti 70
    contatore clienti 71
    contatore clienti 72
    contatore clienti 73
    contatore clienti 74
    contatore clienti 75
    contatore clienti 76
    contatore clienti 77
    contatore clienti 78
    "
  • Re: [c] Programmazione concorrente

    Ho eliminato il semaforo lockriventori posto il codice che sembrerebbe funzionare ovviamente accetto ogni tipo di suggerminto che possa migliorare/semplificare il codice

    ps non capisco se elimninando il semaforo lockrivenditori la variabile biglietti_posseduti_rivenditore viene modificata correttamente (dalle prove empiriche sembra di si)
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/types.h>
    
    #include<pthread.h>
    #include<semaphore.h>
    
    #define carta 0
    #define contanti 1
    #define contanti_e_carta 2
    #define biglietti_tot 2000 //numero di biglietti totati disponibili per l'evento
    #define rivenditori_n 10   //numero di rivenditori disponibili
    #define lotto_l 20         // numero di biglietti disponibile presso ogni rivenditore
    #define acquisto_max 8     //numero massimo di biglietti acquistabili per ogni cliente
    #define numero_clienti 200 // numero di clienti
    typedef struct Rivenditore{
                   int n_biglietti;
                   int pagamento;
                   int id;
                   int count;
                   pthread_t tid;
                  pthread_mutex_t lock;
                  pthread_cond_t disponibili;
                  pthread_cond_t ultimati;
    } Rivenditore;
    
    
    
    
    typedef struct Cliente{
                   int n_biglietti;
                   int pagamento;
                   int id;
                   pthread_t tid;
                Rivenditore* r;
    }Cliente;
    
    
    int biglietti_posseduti_rivenditore;
    sem_t lockrivenditori;
    int counter_cliente;
    
    
    Cliente* set_cliente(int n_biglietti, Rivenditore* r );
    void* acquista(void*arg);
    void check(int x);
    void init(Rivenditore* r);
    void* vendita(void* arg);
    void transazione(Cliente c);
    int biglietti_venduti=0;
    int main(){
    Rivenditore r[rivenditori_n];
    
    init(r);
    
    
    for(int i=0;i<rivenditori_n;i++){
    
     pthread_create(&r[i].tid,NULL,vendita,(void*) &r[i]);
    
    }
    
    
    
    
    
    while(counter_cliente<rand()%numero_clienti+50){
      Cliente *c;
     srand(time(NULL));
     c=set_cliente(rand()%acquisto_max+1,&r[rand()%10]);
    
      pthread_create(&c->tid,NULL,acquista,(void*) c);
    
    
     sleep(1);
     printf("contatore clienti %d\n",counter_cliente);
    
    }
    
    
    
    
    
    
    for(int i=0;i<rivenditori_n;i++)
     pthread_join(r[i].tid,NULL);
    
    
    printf("biglietti totali rivenditore %d\n",biglietti_posseduti_rivenditore);
    printf("biglietti venduti %d\n",biglietti_venduti);
    return 0;
    }
    
    void* acquista(void* arg){
    Cliente* c;
    c=(Cliente*) arg;
    
    check(pthread_mutex_lock(&c->r->lock));
    
     while(c->r->n_biglietti<=0 && c->r->count<rivenditori_n)
     pthread_cond_wait(&c->r->ultimati,&c->r->lock); // se i biglietti disponibili sono finiti aspetta
    
    while(c->r->n_biglietti<c->n_biglietti){ // se i biglietti disponibili sono inferiori a quelli richiesti diminuisco la richiesta
    c->n_biglietti--;
    
    }
    if(c->n_biglietti!=0 ){
    c->r->n_biglietti-= c->n_biglietti; //aggiorno i biglietti disponibili
    transazione(*c);
    printf("%d sta acquistando %d biglietti dal venditore %d ed gli sono rimasti %d\n",c->id,c->n_biglietti,c->r->id,c->r->n_biglietti);
    printf(" il venditore %d ha chiesto n%d volte di acuistare i biglietti \n i venditori possiedono %d\n",c->r->id,c->r->count,biglietti_posseduti_rivenditore);
    }
    else printf("il venditore non ha attualmente biglietti disponibili\n");
    biglietti_venduti+=c->n_biglietti;
    if(c->r->n_biglietti==0 && c->r->count!=rivenditori_n) // se i biglietti sono finiti faccio una signal
    pthread_cond_signal(&c->r->disponibili);
    
    check(pthread_mutex_unlock(&c->r->lock));
    return NULL;
    }
    
    
    
    
    
    
    void* vendita(void * arg){
    Rivenditore* r;
    r=(Rivenditore*)arg;
    
    while(biglietti_posseduti_rivenditore<biglietti_tot && r->count<rivenditori_n){ //ogni rivenditore non puo acquistare piu di un tot biglietti
    // sem_wait(&lockrivenditori);
    
     check(pthread_mutex_lock(&r->lock));
     while(r->n_biglietti>0) //se i biglietti non sono stati completamente venduti mi metto in attesa
     pthread_cond_wait(&r->disponibili,&r->lock);
    
     r->count++;
     r->n_biglietti+=lotto_l;
     biglietti_posseduti_rivenditore+=lotto_l;// il rivenditore acquistano solo lotti di biglietti
     printf("il rivenditore %d ha acquistato un lotto di biglietti biglietti disponibili %d\n",r->id,r->n_biglietti);
     printf("biglietti posseduti rivenditore %d\n",biglietti_posseduti_rivenditore);
    //if(r->count!=0)
     pthread_cond_broadcast(&r->ultimati); //risveglio i clienti in attessa
     check(pthread_mutex_unlock(&r->lock)); //rilascio il mutex tra rivenditore e cliente
    
    //sem_post(&lockrivenditori);
    }
    
    return NULL;
    }
    
    
    void transazione(Cliente c){
    if(c.pagamento==carta)
     sleep(rand()%2);
    else sleep(rand()%3+1);
    
    }
    
    void init(Rivenditore* r){
    for(int i=0;i<rivenditori_n;i++){
     r[i].n_biglietti=lotto_l;
     r[i].id=i;
     r[i].count=1;
    biglietti_posseduti_rivenditore+=lotto_l;
     pthread_mutex_init(&r[i].lock,NULL);
     pthread_cond_init(&r[i].ultimati,NULL);
     pthread_cond_init(&r[i].disponibili,NULL);
    
    }
    sem_init(&lockrivenditori,0,1);
    counter_cliente=1;
    //biglietti_posseduti_rivenditore=0;
    
    }
    
    
    
    
    Cliente* set_cliente(int n, Rivenditore* r){
    Cliente* x=malloc(sizeof(Cliente));
    if(x==NULL){
    fprintf(stderr,"errore malloc /n");
    exit(-1);
    }
    if(r->pagamento==contanti_e_carta){
    x->pagamento=rand()%2;
    pthread_setschedprio(x->tid,90);
    
    }
    else {x->pagamento=r->pagamento;
       pthread_setschedprio(x->tid,120);
    
    }
    
    
    x->id=counter_cliente;
    
    x->n_biglietti=n;
    
    x->r=r;
    counter_cliente++;
    return x;
    }
    
    
    
    void check(int x){
    
    if(x!=0){
    fprintf(stderr," errore %d\n",x);
    exit(-1);}
    
    }
    
  • Re: [c] Programmazione concorrente

    Up
Devi accedere o registrarti per scrivere nel forum
9 risposte