Computer Science 354
Operating Systems
Dickinson College
Spring Semester 2000
Grant Braught
/*
* terror.c
* Example program that demonstrates
* critical sections and the existence
* of a race condition.
*
* Compile with:
* cc tlockfix.c -o tlockfix -lpthread -lm
*
* Grant Braught
* Dickinson College
* (c) 2000
*/
#define _REENTRANT
#include
#include
#include
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 lock that will be used to ensure synchronization.
// Locks are called mutexes because they ensure mutually exclusive
// access to code or data. It is defined here so that it is
// shared by both threads.
pthread_mutex_t TheLock;
int main()
{
pthread_t tid1, tid2;
void *arg;
int i;
printf("\ntlockfix.c\n\n");
printf("Demonstrate a fix to thread synchronization problem using lock.\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 lock.
pthread_mutex_init(&TheLock, NULL);
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++)
{
// Acquire the lock before doing the addition.
pthread_mutex_lock(&TheLock);
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 lock when finished so that the
// subtraction might have a chance to run.
pthread_mutex_unlock(&TheLock);
}
}
void *Thread_Func2(void *junk)
{
int i;
for (i=1; i<=10000; i++)
{
pthread_mutex_lock(&TheLock);
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;
pthread_mutex_unlock(&TheLock);
}
}