CSCI 4630
Spring 2000
Programming assignment 2

Due: Wed, Mar 22, 5:00pm. Turn in your program by mailing the source code to karl@cs.ecu.edu, with heading
CSCI 4630 program 2, your name
where you write your name, not literally "your name". If you have an inquiry about the assignment, do not use this subject, since I will just file it away if you do.

The assignment

Write a program that creates two POSIX threads. Each thread should repeatedly perform a modification of a shared variable or variables. You can select the operation to use, but make it one that is unsafe when done outside a critical section.

After the threads have done enough operations, you should expect your shared data to become corrupted. Design your threads to detect the corruption, report it and stop. Only report a situation where the data has become inconsistent because the update was not done in a critical section.

Run your program. Time it to see how long it takes before the data becomes corrupted.

When you turn in your program, say in the body of the email message how long your program ran until the data was bad.

POSIX threads

This describes only the most basic aspects of how to create and manage POSIX threads. It is assumed that you are writing your program in C or C++, and using a POSIX compliant system. (Solaris 2.x and Windows NT 4.0 both have POSIX interfaces.) I have tested this under Solaris 2.x.

Use function pthread_create to create a new thread. Create a variable attr of type pthread_attr_t, and initialize it as follows. Statements

      pthread_attr_init(&attr);
      pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
Then create the thread as follows.
      stat = pthread_create(&tid, &attr, func, NULL);
where tid is a variable of type pthread_t (typically another name for unsigned int) and func is a function that the thread will run. The prototype for func should be
      void* func(void*);
although you can call the function anything that you like. This creates and starts the new thread, and puts its thread id into variable tid.

You will need to wait for the threads to terminate. (If you don't wait, and you let the main program terminate, the threads that it created will be destroyed prematurely.) Function pthread_join allows one thread to wait for another one. use

      pthread_join(tid,NULL);
to wait for thread number tid to terminate before continuing. Since you will have created two threads, you will have to wait for both of them. You will have to wait for them in a specific order. It does not matter which one finishes first. A terminated thread waits until another thread joins with it.

There are several options for creating thread. They are described in the manual page for pthread_create. The options that have been given here (in the creation of the attr structure) will work for your purposes. Read the manual page for others.

Compiling and Linking

You will need to include header file pthread.h to use POSIX threads. Also, when you link your program, you will need to use the pthread library. If you compile using gcc, you write
   gcc myprog.c -lpthread
When using threads, it is a good idea to include directive
#define _REENTRANT
to force the compiler to generate reentrant code. (Most compilers do this anyway.) Reentrant code has a read-only TEXT segment (where the program is stored) so that it can be run simultaneously by more than one thread.

Timing your program

You can get your program to print the current time of day as follows.
      time_t tloc;
      time(&tloc);
      printf("%s", ctime(&tloc));
Include header file time.h to use these. You can also use the POSIX function ctime_r, which is just a little more complex. See the manual page.