Implement a set of thread synchronizers for use in POSIX threads applications.
A reentrant lock is a mechanism for providing exclusive access to a resource shared by a set of threads. The mechanism is similar to a pthread mutex, but it is reentrant, meaning that a thread that holds the lock can re-lock the lock. The lock is not made available to another thread until the holder of the lock has unlocked the lock the same number of times as it locked it.
Implement the reentrant lock by implementing these functions:
void *createLock(void);
Create and initialize a reentrant lock. Initialize the lock so that no thread holds it. Return a handle for manipulating the lock.
void lockLock(void *lock);
Lock the lock. If the lock is locked by another thread, the calling thread is blocked until the lock is available. If a bad handle is passed to this routine, the behavior is undefined.
int unlockLock(void *lock);
Unlock the lock. If the calling thread does not have the lock locked, the function returns 0, else it returns 1. If a bad handle is passed to this routine, the behavior is undefined.
void freeLock(void *lock);
Destroy the lock and reclaim its memory. If a bad handle is passed to this routine, the behavior is undefined.
A countdown latch is a mechanism for coordinating the exeuction of a set of threads. The latch is created with a non-negative count. The latch remains closed until its count is driven down to zero. Threads that wait on the latch will be blocked until the latch opens when its count reaches zero.
Implement the countdown latch by implementing these functions:
void *createCountdownLatch(unsigned int count);
Create and initialize a countdown latch. Return a handle for manipulating the latch.
void countdown(void *latch);
If the latch's count is greater than zero, decrement the latch's count. If the count is zero, release any threads waiting on the latch. If a bad handle is passed to this routine, the behavior is undefined.
void await(void *latch);
Wait on the latch. If its count is zero, the calling thread continues executing; otherwise it blocks until the latch opens. If a bad handle is passed to this routine, the behavior is undefined.
void freeCountdownLatch(void *latch);
Destroy the latch and reclaim its memory. If a bad handle is passed to this routine, the behavior is undefined.
A reentrant readers-writers lock is a mechanism for controlling access to a resource shared by a set of threads. The mechanism provides two locks, one for threads that want to read the resource and one for threads that want to write the resource. Multiple readers can hold the readers lock, but only if no thread holds the writers lock. Only one thread can hold the writers lock.
Priority is given to writers, meaning that when the writers lock is unlocked, if there are waiting writers, one of them is given the writers lock, even if there have been readers waiting longer. Writers must wait for all readers to release the lock, but once there is a writer waiting no additional readers will be given the readers lock. However, if a thread already holds the readers lock, wants to re-lock it, and there is a writer waiting, the thread holding the readers lock will be allowed to re-lock it.
Implement the reentrant readers-writers lock by implementing these functions:
void *createRWLock(void);
Create and initialize a reentrant readers-writers lock. Initialize the internal locks so that no thread holds them. Return a handle for manipulating the lock.
void lockRLock(void *lock);
Lock the readers lock of the readers-writers lock. If the lock is not available, the calling thread is blocked until the lock becomes available. If a bad handle is passed to this routine, the behavior is undefined.
void lockWLock(void *lock);
Lock the writers lock of the readers-writers lock. If the lock is not available, the calling thread is blocked until the lock becomes available. If a bad handle is passed to this routine, the behavior is undefined.
int unlockRLock(void *lock);
Unlock the readers lock of the readers-writers lock. If the lock is not held by the calling thread, return 0; otherwise return 1. If a bad handle is passed to this routine, the behavior is undefined.
int unlockWLock(void *lock);
Unlock the writers lock of the readers-writers lock. If the lock is not held by the calling thread, return 0; otherwise return 1. If a bad handle is passed to this routine, the behavior is undefined.
void freeRWLock(void *lock);
Destroy the lock and reclaim its memory. If a bad handle is passed to this routine, the behavior is undefined.
You may only use normal pthread mutexes for this assignment.
When you pass NULL to pthread_mutex_init
for the attribute parameter, you get a normal mutex.
Use pthread_equal
to test whether two pthreads are the same.
You should, of course, test all library function calls for success
or failure.
If any of these functions fail, treat it as a catastrophic error
by using perror
to report the error and
exit(-1)
to terminate the program.
Check the man page for perror
for more information.
When implementing the reentrant readers-writers lock, you will need to
use pthread_key_create
,
pthread_getspecific
and
pthread_setspecific
for
managing thread-specific data.
As well as pthread_cond_wait
and
pthread_cond_signal
, you will need to use
pthread_cond_broadcast
.
The directory ~cs520/public/prog5
contains
a header file for the synchronizer functions as well as some tests and
a Makefile for building and executing the tests.
When compiling programs that use POSIX threads, you must provide
the -pthread flag.
You should put all your source code in the file
sync.c
.
Your program will be graded primarily by testing it for correct functionality:
Remember, you may lose points if your program is not properly structured or adequately documented. Coding guidelines are given on the course overview webpage.
Your programs will be graded using agate.cs.unh.edu so be sure to test in that environment. Your programs will be compiled using these gcc flags: -g -Wall -std=c99 -pthread.
Your programs should be submitted for grading from
agate.cs.unh.edu.
To turn in this assignment, type:
~cs520/bin/submit prog5 sync.c
Submissions can be checked by typing:
~cs520/bin/scheck prog5
This assignment is due Wednesday April 17. The standard late policy concerning late submissions will be in effect. See the course overview webpage.
Remember: as always you are expected to do your own work on this assignment. Copying code from another student or from sites on the internet is explicitly forbidden!
Comments and questions should be directed to pjh@cs.unh.edu