Newsgroup: it.comp.os.linux.development
Titolo: Chiedo aiuto su mutex e semafori in C

Ciao mes amis,
sto cercando di imparare ad utilizzare i threads, utilizzando le librerie 
pthread.h in unix.
I concetti che mi servono credo che siano os indipendenti.
Non capisco bene come utilizzare i semafori e i mutex. 
Pongo alcuni quesiti:
1) I thread condividono di default le variabili globali?
2)   in righe di codice come quelle seguenti, quando faccio il lock di 
mutex, quali variabile vengono "bloccate"? solo quella che precede la 
dichiarazione di mutex o tutte quelle che lo precedono?
 char buffer;
  int buffer_has_item = 0;
  pthread_mutex_t mutex;
main()
 {
 .... 
pthread_mutex_lock( &mutex );
....
}
3) cosa succede se un altro thread cerca di fare lock su una mutex bloccata 
da un altro? rimane fermo finche' la variabile non viene sbloccata o va 
avanti restituendo un qualche segnale di errore?
4) per i mutex ho delle mezze idee, mentre con i semafori sono alla frutta. 
Ho trovato un piccolo codice esplicativo, ma non e' in pratica commentato. 
Dato che sono un tipo in gamba :P se qualcuno mi mette dei commenti su cio' 
che riguarda i semafori poi posso fare delle prove per capire bene come 
funzionano. (mi andrebbe benissimo anche un altro programmino ad hoc o un 
link ove trovare spiegazioni)
------------------------------------
  void reader_function(void);
  void writer_function(void);
 
  char buffer;
  Semaphore writers_turn;
  Semaphore readers_turn;
 
  main()
  {
     pthread_t reader;
 
     semaphore_init( &readers_turn );
     semaphore_init( &writers_turn );
 
     /* writer must go first */
     semaphore_down( &readers_turn );
 
     pthread_create( &reader, pthread_attr_default,
                    (void *)&reader_function, NULL);
     writer_function();
  }
 
  void writer_function(void)
  {
     while(1)
     {
          semaphore_down( &writers_turn );
          buffer = make_new_item();
          semaphore_up( &readers_turn );
     }
  }
 
  void reader_function(void)
  {
     while(1)
     {
          semaphore_down( &readers_turn );
          consume_item( buffer );
          semaphore_up( &writers_turn );
     }
  }
-------------------------------------------------
n.b. ovviamente ho gia' dato un'occhiata su google (sez. newsgroup) e su 
comp.programming.threads (li' non mi sono ancora impeganto a fondo)
Grazie mille a tutti,
Riccardo

 link ove trovare spiegazioni)
Un semaforo  e` un po'  piu` di  una mutex. Il chiamante  viene bloccato
quando il contatore e` a zero.
void lock_init(sem_t *sem) {
        sem_init(sem, 0, 1);
}
void lock(sem_t *sem) {
        sem_wait(sem);
}
void unlock(sem_t *sem) {
        sem_post(sem);
}
Queste  tre  funzioni  forniscono  un surrogato  di  una  mutex. Volendo
sfruttare  meglio  il semaforo  si  puo`  pensare al  classico  problema
producer/consumer. Il semaforo viene  inizialmente settato a zero. Prima
di ogni lettura dal buffer condiviso il consumer esegue una sem_wait (un
'down',  per intenderci),  dopo ogni  scrittura il  producer esegue  una
sem_post  (una  'up'). Supponi che  il  producer  metta 3  elementi  nel
buffer:  a questo  punto  il contatore  del semaforo  sara`  a 3. Se  lo
scheduler passa il controllo al consumer questo effettuera` 3 iterazioni
complete (iterazione:  down + rimozione  dell'elemento dal buffer)  e si
blocchera` all'inizio della  quarta, perche` il contatore  e` arrivato a
zero.
Nell'esempio qui` sotto il semaforo viene utilizzato come una mutex.
Volendo questa potrebbe essere l'implementazione di un semaforo:
typedef struct {
        pthread_mutex_t lock;
        pthread_cond_t not_zero;
        int count;
} sem_t;
void sem_init(sem_t *sem) {
        sem->count = 0;
        pthread_mutex_init(&sem->lock, NULL);
        pthread_cond_init(&sem->not_zero, NULL);
}
void sem_post(sem_t *sem) {
        pthread_mutex_lock(&sem->lock);
        sem->count++;
        /* Segnalo la condizione not_zero */
        pthread_cond_signal(&sem->not_zero);
        pthread_mutex_unlock(&sem->lock);
}
void sem_wait(sem_t *sem) {
        pthread_mutex_lock(&sem->lock);
        if (sem->count == 0)
                /* Rilascio il lock ed aspetto che qualcuno segnali la
                 * condizione not_zero. Prima di ritornare
                 * pthread_cond_wait riacquisisce la mutex
                 */
                 pthread_cond_wait(&sem->not_zero, &sem->lock);
        sem->count--;
        pthread_mutex_unlock(&sem->lokc);
}
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Al termine di un pranzo di nozze mi hanno dato un
amaro alle erbe cosi' schifoso che perfino sull'etichetta
c'era un frate che vomitava.

 Kronos
Grazie Kronos per la risposta precisa, come sempre.
Inizio a fare un po' di prove,
Riccardo

 alla frutta.
passo
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.19. C, C++ and ASM developers
                              and beta testers are welcome!


Ciao, scusa se non rispondo a tutte le tue domande, ti do' solo un
hyperlink che dovrebbe esserti utile
http://www.cs.cf.ac.uk/Dave/C/CE.html
E' un "corso" di C e UNIX in cui ci sono (spero) gli esempi che ti
servono.
Cesare

 link ove trovare spiegazioni)
Vedilo come  un semaforo multivalore. Quando fai una wait mentre ha il
count a 0 blocca, altrimenti decrementa il contatore.
Nel sito in firma c'e' una libreria produttore/consumatore con qualcosina di
carino che utilizza pthread.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! *Real* programmers use cat > a.out! No way, /real/ ones
        use zcat > a.out 'cause you can type faster that way. !>-
                -- from a Slashdot discussion