PreviousNext

DCE Threads Example Body

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 (&current_mutex);

check(status,"6:Mutex_lock bad status\n");

current_num = current_num + 2; /* Skip even numbers */

numerator = current_num;

status = pthread_mutex_unlock (&current_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 (&current_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");

}