Floating point exceptions with -pthread

Daniel Eischen deischen at freebsd.org
Wed May 4 08:06:36 PDT 2005


On Wed, 4 May 2005, Marc Olzheim wrote:

> On Tue, May 03, 2005 at 09:54:23AM -0400, Daniel Eischen wrote:
> > > Hi.
> > >
> > > I was wondering whether it was safe to use floating point calculations /
> > > libm functions with 5.4-STABLE's pthread library on HT+SMP. I keep
> > > getting floating point exceptions on places where they should not
> > > happen... :-(
> >
> > Yes, it should work fine.  If you can verify the problem exists
> > (or doesn't) on -current, that might help.  It sounds like FPU
> > context isn't getting saved/restored correctly in the kernel.
>
> Should I file a PR ?

Yes, it happens also on a UP system with a few month old -current.
Is there a similar test you can use that doesn't use floor()?

This one seems to work but doesn't use libm.

-- 
DE

-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----

#include <err.h>
#include <stdlib.h>
#include <limits.h>
#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

void *foo(void *);

typedef struct
{
	int number;
	int loops;
} arg_t;


/*
 * Simple test case for the thread system.  Start "n" threads,
 * and join them afterwards.
 */
int
main( int argc, char** argv)
{
	struct sched_param param;
	pthread_t* threads;
	pthread_attr_t attr;
	arg_t* args;
	void* ret;
	int policy;
	int n;
	int i;

	if (argc > 1) {
		n = strtoimax(argv[1], NULL, 10);
		printf("Using %d threads (parameter)\n", n);
	} else {
		n = 5;
		printf("Using %d threads (default)\n", n);
	}

	// initialize random number generator
	srandomdev();

	threads = (pthread_t *)malloc(sizeof(pthread_t) * n);
	args = (arg_t *)malloc(sizeof(arg_t) * n);

	// start n threads
	pthread_attr_init(&attr);
	//pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
	for (i = 0; i < n; i++) {
		args[i].number = i;
		if (pthread_create(&threads[i], &attr, foo, &args[i]) != 0) {
			err(1, NULL);
		}
	}

	pthread_getschedparam(pthread_self(), &policy, &param);
	param.sched_priority++;
	pthread_setschedparam(pthread_self(), policy, &param);

	// join threads
	for (i = 0; i < n; i++) {
		if (pthread_join(threads[i], &ret) != 0) {
			err(1, NULL);
		}
		printf("Joined bar %d, loops %d\n",
		    args[i].number, args[i].loops);
	}

	free(threads);
	sleep(1);
	return (0);
}

void *
foo(void *v)
{
	arg_t *arg;
	float a, b, c;
	float d __unused;
	int i;
	int loops;

	arg = (arg_t *)v;

	printf("bar %d running\n", arg->number);
	/* Simulate some CPU-intensive calculations. */
#if 1
	while (1) {
#else
	loops = 5000000;
	for (i = 1; i < loops; i++) {
#endif
		a = (float)i * ((float)random() / 11.0);
		b = a * ((float)random() / 13.0);
		c = b * ((float)random() / 17.0);
		d = c * ((float)random() / 23.0);
	}
	arg->loops = loops;
	//printf("bar %d, loops %d\n", arg->number, arg->loops);
	return (NULL);
}




More information about the freebsd-threads mailing list