15

Semaphore

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4.  
  5. #include <pthread.h>
  6.  
  7. typedef struct {
  8.     int count;
  9.     pthread_mutex_t mutex;
  10.     pthread_cond_t cond;
  11. } semaphore;
  12.  
  13. void sema_init( semaphore *sp, int count ) {
  14.     sp->count = count;
  15.     pthread_mutex_init( &sp->mutex, 0 );
  16.     pthread_cond_init( &sp->cond, 0 );
  17. }
  18.  
  19. void sema_destroy( semaphore *sp ) {
  20.     pthread_mutex_destroy( &sp->mutex );
  21.     pthread_cond_destroy( &sp->cond );
  22. }
  23.  
  24. void sema_acquire( semaphore *sp ) {
  25.     pthread_mutex_lock( &sp->mutex );
  26.     while ( sp->count == 0 )
  27.         pthread_cond_wait( &sp->cond, &sp->mutex );
  28.     --sp->count;
  29.     pthread_mutex_unlock( &sp->mutex );
  30. }
  31.  
  32. void sema_release( semaphore *sp ) {
  33.     pthread_mutex_lock( &sp->mutex );
  34.     ++sp->count;
  35.     pthread_cond_broadcast( &sp->cond );
  36.     pthread_mutex_unlock( &sp->mutex );
  37. }
  38.  
  39. typedef struct {
  40.     int id;
  41.     semaphore *sema;
  42.     pthread_t thread;
  43. } user;
  44.  
  45. void *work( void *p ) {
  46.     int id = ((user *) p)->id;
  47.     semaphore *sp = ((user *) p)->sema;
  48.  
  49.     int i, n;
  50.  
  51.     printf( "%d - Acquiring resource\n", id );
  52.     sema_acquire( sp );
  53.     printf( "%d - Resource is locked\n", id );
  54.     n = (double) rand() / RAND_MAX * 10000000;
  55.     printf( "%d * Busy(%d)...\n", id, n );
  56.     for ( i = 0; i < n; i++ )
  57.         (void) rand();
  58.     printf( "%d - Releasing resource\n", id );
  59.     sema_release( sp );
  60.  
  61.     pthread_exit( 0 );
  62. }
  63.  
  64. #define NUSERS      7
  65.  
  66. int main( int argc, char *argv[] ) {
  67.     pthread_attr_t attr;
  68.  
  69.     void *status;
  70.  
  71.     user people[NUSERS];
  72.  
  73.     semaphore sema;
  74.  
  75.     int i;
  76.  
  77.     srand( time( 0 ) );
  78.  
  79.     sema_init( &sema, 2 );
  80.  
  81.     pthread_attr_init( &attr );
  82.     pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
  83.  
  84.     for ( i = 0; i < NUSERS; i++ ) {
  85.         user *p = &people[i];
  86.         p->id = i + 1;
  87.         p->sema = &sema;
  88.         pthread_create( &p->thread, &attr, work, (void *) p );
  89.     }
  90.  
  91.     // MUST be in a separate loop!
  92.     for ( i = 0; i < NUSERS; i++ )
  93.         pthread_join( people[i].thread, &status );
  94.  
  95.     pthread_attr_destroy( &attr );
  96.  
  97.     sema_destroy( &sema );
  98.  
  99.     pthread_exit( 0 );
  100. }
$ gcc -Wall -lpthread sema.c -o sema
$ ./sema
1 - Acquiring resource
1 - Resource is locked
2 - Acquiring resource
6 - Acquiring resource
4 - Acquiring resource
4 - Resource is locked
4 * Busy(6893328)...
5 - Acquiring resource
7 - Acquiring resource
1 * Busy(5600318)...
3 - Acquiring resource
1 - Releasing resource
5 - Resource is locked
5 * Busy(4001876)...
4 - Releasing resource
3 - Resource is locked
3 * Busy(6268161)...
5 - Releasing resource
6 - Resource is locked
6 * Busy(9453382)...
3 - Releasing resource
7 - Resource is locked
7 * Busy(5335524)...
7 - Releasing resource
2 - Resource is locked
2 * Busy(5401617)...
6 - Releasing resource
2 - Releasing resource

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].