The following is the DCE Threads example:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
/*
* Constants used by the example.
*/
#define workers 5 /* Threads to perform prime check */
#define request 110 /* Number of primes to find */
/*
* Macros
*/
#define check(status,string) \ if (status == -1) perror (string)
/*
* Global data
*/
pthread_mutex_t prime_list; /* Mutex for use in accessing the prime */
pthread_mutex_t current_mutex; /* Mutex associated with current number */
pthread_mutex_t cond_mutex; /* Mutex used for ensuring CV integrity */
pthread_cond_t cond_var; /* Condition variable for thread start */
int current_num= -1;/* Next number to be checked, start odd */
int thread_hold= 1; /* Number associated w/condition state */
int count=0; /* Prime numbers count;/index to primes */
int primes[request];/* Store primes; synchronize access */
pthread_t threads[workers]; /* Array of worker threads */
/*
* Worker thread routine.
*
* Worker threads start with this routine, which begins with a condition
* wait designed to synchronize the workers and the parent. Each worker
* thread then takes a turn taking a number for which it will determine
* whether or not it is prime.
*
*/
void
prime_search (pthread_addr_t arg)
{
div_t div_results; /* DIV results: quot and rem */
int numerator; /* Used for determing primeness */
int denominator; /* Used for determing primeness */
int cut_off; /* Number being checked div 2 */
int notifiee; /* Used during a cancellation */
int prime; /* Flag used to indicate primeness */
int my_number; /* Worker thread identifier */
int status; /* Hold status from pthread calls */
int not_done=1; /* Work loop predicate */
my_number = (int)arg;
/*
* Synchronize threads and the parent using a condition variable,
* for which the predicate (thread_hold) will be set by the parent.
*/
status = pthread_mutex_lock (&cond_mutex);
check(status,"1:Mutex_lock bad status\n");
while (thread_hold) {
status = pthread_cond_wait (&cond_var, &cond_mutex);
check(status,"3:Cond_wait bad status\n");
}
status = pthread_mutex_unlock (&cond_mutex);
check(status,"4:Mutex_unlock bad status\n");
/*
* Perform checks on ever larger integers until the requested
* number of primes is found.
*/
while (not_done) {
/* cancellation point */
pthread_testcancel ();
/* Get next integer to be checked */
status = pthread_mutex_lock (¤t_mutex);
check(status,"6:Mutex_lock bad status\n");
current_num = current_num + 2; /* Skip even numbers */
numerator = current_num;
status = pthread_mutex_unlock (¤t_mutex);
check(status,"9:Mutex_unlock bad status\n");
/* Only need to divide in half of number to verify not prime */
cut_off = numerator/2 + 1;
prime = 1;
/* Check for prime; exit if something evenly divides */
for (denominator = 2; ((denominator < cut_off) && (prime));
denominator++) {
prime = numerator % denominator;
}
if (prime != 0) {
/* Explicitly turn off all cancels */
pthread_setcancel(CANCEL_OFF);
/*
* Lock a mutex and add this prime number to the list. Also,
* if this fulfills the request, cancel all other threads.
*/
status = pthread_mutex_lock (&prime_list);
check(status,"10:Mutex_lock bad status\n");
if (count < request) {
primes[count] = numerator;
count++;
}
else if (count == request) {
not_done = 0;
count++;
for (notifiee = 0; notifiee < workers; notifiee++) {
if (notifiee != my_number) {
status = pthread_cancel ( threads[notifiee] );
check(status,"12:Cancel bad status\n");
}
}
}
status = pthread_mutex_unlock (&prime_list);
check(status,"13:Mutex_unlock bad status\n");
/* Reenable cancels */
pthread_setcancel(CANCEL_ON);
}
pthread_testcancel ();
}
pthread_exit (my_number);
}
main()
{
int worker_num; /* Counter used when indexing workers */
int exit_value; /* Individual worker's return status */
int list; /* Used to print list of found primes */
int status; /* Hold status from pthread calls */
int index1; /* Used in sorting prime numbers */
int index2; /* Used in sorting prime numbers */
int temp; /* Used in a swap; part of sort */
int not_done; /* Indicates swap made in sort */
* Create mutexes
*/
status = pthread_mutex_init (&prime_list, pthread_mutexattr_default);
check(status,"15:Mutex_init bad status\n");
status = pthread_mutex_init (&cond_mutex, pthread_mutexattr_default);
check(status,"16:Mutex_init bad status\n");
status = pthread_mutex_init (¤t_mutex, pthread_mutexattr_default);
check(status,"17:Mutex_init bad status\n");
/*
* Create conditon variable
*/
status = pthread_cond_init (&cond_var, pthread_condattr_default);
check(status,"45:Cond_init bad status\n");
/*
* Create the worker threads.
*/
for (worker_num = 0; worker_num < workers; worker_num++) {
status = pthread_create (
&threads[worker_num],
pthread_attr_default,
prime_search,
(pthread_addr_t)worker_num);
check(status,"19:Pthread_create bad status\n");
}
/*
* Set the predicate thread_hold to zero, and broadcast on the
* condition variable that the worker threads may proceed.
*/
status = pthread_mutex_lock (&cond_mutex);
check(status,"20:Mutex_lock bad status\n");
thread_hold = 0;
status = pthread_cond_broadcast (&cond_var);
check(status,"20.5:cond_broadcast bad status\n");
status = pthread_mutex_unlock (&cond_mutex);
check(status,"21:Mutex_unlock bad status\n");
/*
* Join each of the worker threads inorder to obtain their
* summation totals, and to ensure each has completed
* successfully.
*
* Mark thread storage free to be reclaimed upon termination by
* detaching it.
*/
for (worker_num = 0; worker_num < workers; worker_num++) {
status = pthread_join (
threads[worker_num],
&exit_value );
check(status,"23:Pthread_join bad status\n");
if (exit_value == worker_num) printf("thread terminated normally\n");
status = pthread_detach ( &threads[worker_num] );
check(status,"25:Pthread_detach bad status\n");
}
/*
* Take the list of prime numbers found by the worker threads and
* sort them from lowest value to highest. The worker threads work
* concurrently; there is no guarantee that the prime numbers
* will be found in order. Therefore, a sort is performed.
*/
not_done = 1;
for (index1 = 1; ((index1 < request) && (not_done)); index1++) {
for (index2 = 0; index2 < index1; index2++) {
if (primes[index1] < primes[index2]) {
temp = primes[index2];
primes[index2] = primes[index1];
primes[index1] = temp;
not_done = 0;
}
}
}
/*
* Print out the list of prime numbers that the worker threads
* found.
*/
printf ("The list of %d primes follows:\n", request);
printf("%d",primes[0]);
for (list = 1; list < request; list++) {
printf (",\t%d", primes[list]);
}
printf ("\n");
}