This is prime.c in view mode; [Download] [Up]
/* * DECthreads example program conducting a prime number search */ #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <utils.h> /* * Constants used by the example. */ #define workers 5 /* Threads to perform prime check */ #define request 200 /* 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 with condition state */ int count = 0; /* Count of prime numbers - index to primes */ int primes[request]; /* Store prime numbers - synchronize access */ pthread_t threads[workers]; /* Array of worker threads */ static void unlock_cond(pthread_addr_t arg) { int status; /* Hold status from pthread calls */ status = pthread_mutex_unlock(&cond_mutex); check(status, "3:Mutex_unlock bad status\n"); } /* * 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) { 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 cancelation */ 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, of * 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"); pthread_cleanup_push(unlock_cond, NULL); while (thread_hold) { status = pthread_cond_wait(&cond_var, &cond_mutex); check(status, "2:Cond_wait bad status\n"); } pthread_cleanup_pop(1); /* * Perform checks on ever larger integers until the requested * number of primes is found. */ while (not_done) { /* Cancelation point */ pthread_testcancel(); /* Get next integer to be checked */ status = pthread_mutex_lock(¤t_mutex); check(status, "4:Mutex_lock bad status\n"); current_num = current_num + 2; /* Skip even numbers */ numerator = current_num; status = pthread_mutex_unlock(¤t_mutex); check(status, "5: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, "6: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((pthread_addr_t) my_number); } int main(int argc, char *argv[]) { int worker_num; /* Counter used when indexing workers */ void *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, "7:Mutex_init bad status\n"); status = pthread_mutex_init(&cond_mutex, pthread_mutexattr_default); check(status, "8:Mutex_init bad status\n"); status = pthread_mutex_init(¤t_mutex, pthread_mutexattr_default); check(status, "9:Mutex_init bad status\n"); /* * Create conditon variable */ status = pthread_cond_init(&cond_var, pthread_condattr_default); check(status, "10: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, (thread_proc_t) prime_search, (pthread_addr_t) worker_num); check(status, "11: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, "12:Mutex_lock bad status\n"); thread_hold = 0; status = pthread_cond_broadcast(&cond_var); status = pthread_mutex_unlock(&cond_mutex); check(status, "13: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, "14:Pthread_join bad status\n"); if (exit_value == (pthread_addr_t) worker_num) printf("Thread terminated normally\n"); /* * Upon normal termination the exit_value is equivalent to * worker_num. */ status = pthread_detach(&threads[worker_num]); check(status, "15: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"); return (EXIT_SUCCESS); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.