Protecting a Shared Counter

The following program creates a number of threads running concurrently. All of them share the same global counter variable. They lock the counter and update and display the value of the counter. The lock mechanism is done by a semaphore. This shows the first use of semaphores: a lock!

Click here to download a copy of this program.

#include  <stdio.h>
#include  <stdlib.h>
#include  <thread.h>
#include  <synch.h>

#define   NO_THREADS    5                /* current, no more than 5  */

sema_t    Lock;                          /* the protecting semaphore */

int       Counter, Max_Run;              /* the shared counter       */

void  *Counting(void *voidPTR)
{
     int   *intPTR = (int *) voidPTR;
     int   Name    = *intPTR;
     char  filler[20];
     int   i;

     for (i = 0; i < Name*2; i++)
          filler[i] = ' ';
     filler[i] = '\0';

     printf("%sThread %d started\n", filler, Name);
     for (i = 0; i < Max_Run; i++) {
          thr_yield();                   /* rest for unspecified time*/
          sema_wait(&Lock);              /* enter critical section   */
               Counter++;                /* do updating and printing */
               printf("%sThread %d reports: new counter value = %d\n",
                       filler, Name, Counter);
          sema_post(&Lock);              /* leaving critical section */
     }
     printf("%sThread %d ends\n", filler, Name);
     thr_exit(0);
}

void  main(int  argc,  char *argv[])
{
     thread_t   ID[NO_THREADS];          /* thread IDs               */
     size_t     Status[NO_THREADS];      /* thread status            */
     int        Argument[NO_THREADS];    /* thread argument          */
     int        i;

     if (argc != 2) {
          printf("Use %s #-of-iterations\n", argv[0]);
          exit(0);
     }
     Max_Run = abs(atoi(argv[1]));

     printf("Parent started ...\n");

     Counter = 0;
     sema_init(&Lock, 1, USYNC_THREAD, (void *) NULL);  /* init sem. */

     printf("Parent is about to create %d threads\n", NO_THREADS);

     for (i = 0; i < NO_THREADS; i++) {  /* create all threads       */
          Argument[i] = i;
          thr_create(NULL, 0, Counting, (void *) &(Argument[i]),
                     0, (void *) &(ID[i]));
     }

     for (i = 0; i < NO_THREADS; i++) {  /* wait for all threads     */
          thr_join(ID[i], 0, (void *) &(Status[i]));
          printf("Parent found thread %d done\n", i);
     }
     printf("Parent exits ...\n");
}