NetBSD-5.0.2/regress/lib/libpthread/fpu/fpu.c

Compare this file to the similar file:
Show the results in this format:

/* $NetBSD: fpu.c,v 1.2 2005/12/02 16:44:54 is Exp $ */

/*
 * This is adapted from part of csw/cstest of the MPD implementation by
 * the University of Arizona CS department (http://www.cs.arizona.edu/sr/)
 * which is in the public domain:
 *
 * "The MPD system is in the public domain and you may use and distribute it
 *  as you wish.  We ask that you retain credits referencing the University
 *  of Arizona and that you identify any changes you make.
 *  
 *  We can't provide a warranty with MPD; it's up to you to determine its
 *  suitability and reliability for your needs.  We would like to hear of
 *  any problems you encounter but we cannot promise a timely correction."
 *
 * It was changed to use pthread_create() and sched_yield() instead of
 * the internal MPD context switching primitives by Ignatios Souvatzis
 * <is@netbsd.org>.
 */

#include <math.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define N_RECURSE 10

double mul3(double, double, double);
void *stir(void *);
void *bar(void *);
void dotest(void);

#define RCTEST(code, mess) if (rc) {fprintf(stderr, "%s\n", mess); exit(1);}
#define YIELD() if (sched_yield()) {fprintf(stderr, "sched_yield"); exit(1);}
#define LOCK(l) if (pthread_mutex_lock(l)) {fprintf(stderr, "lock"); exit(1);}
#define UNLOCK(l) if (pthread_mutex_unlock(l)) {fprintf(stderr, "unlock"); exit(1);}

int recursion_depth = 0;
pthread_mutex_t recursion_depth_lock;
pthread_t s5;
double stirseed[] = {1.7, 3.2, 2.4};
int verbose = 0;

#define Dprintf(x) if(verbose) printf(x)

int
main(int argc, char *argv[]) {

	int rc;

	printf("Testing threaded floating point computations...");
	if (argc > 1  && argv[1][0] == '-' && argv[1][1] == 'v') {
		verbose = 1;
		printf("\n");
	}
	rc = pthread_mutex_init(&recursion_depth_lock, 0);
	if (0 != rc) {
		fprintf(stderr, "pthread_mutex_init");
		exit(1);
	}
	pthread_create(&s5, 0, stir, stirseed);
	dotest();

	fprintf(stderr, "\n exiting from main\n");
	exit(1);
}

void *
stir(void *p) {
	double *q = (double *)p;
	double x = *q++;
	double y = *q++;
	double z = *q++;
	for (;;) {
		Dprintf("stirring...");
		x = sin ((y = cos (x + y + .4)) - (z = cos (x + z + .6)));
		YIELD();
	}
}

double mul3(double x, double y, double z) {
	Dprintf("mul3...");
	YIELD();
	Dprintf("returning...\n");
	return x * y * z;
}

void *bar(void *p) {
	double d;
	int rc;

	d = mul3(mul3(2., 3., 5.), mul3(7., 11., 13.),
	    mul3(17., 19., 23.));

	if (d != 223092870.) {
		printf("\noops - product returned was %.20g\nFAILED\n", d);
		exit(1);
	}

	LOCK(&recursion_depth_lock);
	rc = recursion_depth++;
	UNLOCK(&recursion_depth_lock);
	if (rc < N_RECURSE) {
		dotest();
	}
	Dprintf("\n");
	printf("OK\n");
	exit(0);
}

void dotest() {
	pthread_t s2;
	Dprintf("recursing...");
	pthread_create(&s2, 0, bar, 0);
	sleep(20); /* XXX must be long enough for our slowest machine */
}