Subject: port-mips/29698: floating point context not saved in pthread/mips
To: None <port-mips-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: Ignatios Souvatzis <ignatios@sinus.cs.uni-bonn.de>
List: netbsd-bugs
Date: 03/15/2005 14:35:00
	Note: There was a bad value `' for the field `Class'.
	It was set to the default value of `sw-bug'.

>Number:         29698
>Category:       port-mips
>Synopsis:       floating context not saved in pthread/mips
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-mips-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Mar 15 14:35:00 +0000 2005
>Originator:     ignatios@sinus.cs.uni-bonn.de
>Release:        NetBSD 2.99.14
>Organization:
computer science department, university of Bonn, Germany
>Environment:
NetBSD tequila-sunrise.duskware.de 2.99.14 NetBSD 2.99.14 (TEQUILA) #0:
Fri Jan 14 09:54:37 CET 2005
martin@night-porter.duskware.de:/usr/src/sys/arch/sgimips/compile/TEQUILA
sgimips
>Description:

Running part of the regression test for context switches from the SR
library, roughly translated to using pthread only, shows wrong FP results.

> ===== checking floating point =====
> mul3...stirring...returning
> mul3...stirring...returning
> mul3...stirring...returning
> mul3...stirring...returning
> oops -- product returned was 0.97504285672921098271

The expected result is 223092870.


(cstest.c shows wrong FP results, too, but I wanted a non-SR program to
 demonstrate them to avoid being accused of abusing libpthread internals.)

>How-To-Repeat:
Compile this code (cc -o threadtest threadtest.c -lpthread -lm),
then run it.

#include <stdio.h>
#include <math.h>
#include <pthread.h>

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

pthread_cond_t s2, s5;
pthread_mutex_t m2, m5;
pthread_t thread2, thread5;
pthread_barrier_t startup;

int
main() {
	int rc;

	rc = pthread_mutex_init(&m2, 0);
	if (rc) 
		err("pthread_mutex_init");

	rc = pthread_mutex_init(&m5, 0);
	if (rc) 
		err("pthread_mutex_init");

	rc = pthread_cond_init(&s2, 0);
	if (rc) 
		err("pthread_cond_init");

	rc = pthread_cond_init(&s5, 0);
	if (rc) 
		err("pthread_cond_init");

	rc = pthread_create(&thread5, 0, stir, 0);
	if (rc) 
		err("pthread_create");

	rc = pthread_barrier_init(&startup, 0, 2);
	if (rc) 
		err("pthread_barrier_init");

	pthread_barrier_wait(&startup);
	pthread_join(thread2, 0);
	exit(0);
}


double
mul3(double x, double y, double z, pthread_cond_t *ctx) {
	printf("mul3...");

	pthread_cond_signal(&s5);
	pthread_cond_wait(ctx,&m2);

	printf("returning\n");
	return x*y*z;
}

void *
stir(void *arg) {
	double x = 1.7, y = 3.2, z = 2.4;
	int rc;

	pthread_mutex_lock(&m5);

	rc = pthread_create(&thread2, 0, bar, 0);
	if (rc) 
		err("pthread_create");

	for (;;) {
		pthread_cond_wait(&s5,&m5);
		printf("stirring...");
		x = sin ((y = cos (x + y + .4)) - (z = cos (x + z + .6)));
		pthread_cond_signal(&s2);
	}
}

void *
bar(void *arg) {
	double d;


	pthread_barrier_wait(&startup);
	pthread_mutex_lock(&m2);

	puts ("===== checking floating point =====");
	d = mul3 (mul3 (2., 3., 5., &s2), mul3 (7., 11., 13., &s2),
        	mul3 (17., 19., 23., &s2), &s2);
	if (d != 223092870.)
       		printf ("oops -- product returned was %.20g\n", d); 

	return(0);
}

>Fix:
Idea: save/restore fp regs in lib/libpthread/arch/mips/