Computer Science 354
Operating Systems

Dickinson College
Spring Semester 2000
Grant Braught

/* * tsemfix.c * Example program that demonstrates * how to fix the critical section * problem of terror.c using semaphores. * * Compile with: * cc tsemfix.c -o tsemfix -lpthread -lm * * Grant Braught * Dickinson College * (c) 2000 */ #define _REENTRANT #include <stdio.h> #include <math.h> #include <pthread.h> #include <semaphore.h> void *Thread_Func1(void *); void *Thread_Func2(void *); // Define some global variables that the threads will use. int Global_Var; double Global_Var2 = 7.6789; double Global_Var3 = 3.21234; double Global_Var4 = 7.6789; double Global_Var5 = 3.21234; // Define the semaphore that will be used to ensure synchronization. // It is defined here so that it is shared by both threads. // see "man sem_init" for more information on semaphores. sem_t TheSem; int main() { pthread_t tid1, tid2; void *arg; int i; printf("\ntsemfix.c\n\n"); printf("Demonstrate a fix to thread synchronization problem using sempahores.\n"); printf("Create 2 threads:\n"); printf("\tOne adds 1 to a global variable 10,000 times.\n"); printf("\tOne subtracts 1 from the same globla variable 10,000 times.\n"); printf("Each thread acquires the lock before adding or subtracting\n"); printf("from the global variable thus ensuring a correct result.\n"); printf("The process is repeated 40 times.\n"); printf("If the threads are synchronized the value should always\n"); printf("be zero.\n\n"); printf("Global Variable Values\n"); printf("-----------------------------------------------------------------------\n"); // Initialize the semaphore. // 0 = Do not share with other processes (but do with threads.) // 1 = Initial value of 1. sem_init(&TheSem,0,1); for (i=1; i<=40; i++) { // Initialize the global variable. Global_Var = 0; // Create the two threads... pthread_create(&tid1, NULL, Thread_Func1, arg); pthread_create(&tid2, NULL, Thread_Func2, arg); // Wait for the threads to finish... pthread_join(tid1,NULL); pthread_join(tid2,NULL); // Write out the value of the global variable. printf("%d\t\t",Global_Var); if (i % 5 == 0) printf("\n"); } } void *Thread_Func1(void *junk) { int i; // Each thread will do the addition or subtraction 10,000 times. // Before each addition a lock is acquired. It is released after // each addition. This ensures that the addition will not be // interrupted midstream by the subtraction. Thus proper synchronization // is ensured and the answer should always be zero. // The pow instructions are included to make the addition and // subtraction operations take more time. This increases the // likelyhood of a thread being interrupted. for (i=1; i<=10000; i++) { // Wait on the semaphore before doing the addition. sem_wait(&TheSem); Global_Var = Global_Var + (int) pow(Global_Var2,Global_Var3) - (int) pow(Global_Var4,Global_Var5) + (int) pow(Global_Var3,Global_Var2) - (int) pow(Global_Var5,Global_Var4) + 1; // Release the semaphore when finished so that the // subtraction might have a chance to run. sem_post(&TheSem); } } void *Thread_Func2(void *junk) { int i; for (i=1; i<=10000; i++) { sem_wait(&TheSem); Global_Var = Global_Var + (int) pow(Global_Var2,Global_Var3) - (int) pow(Global_Var4,Global_Var5) + (int) pow(Global_Var3,Global_Var2) - (int) pow(Global_Var5,Global_Var4) - 1; sem_post(&TheSem); } }