Bug 80617 - floating point registers seem not to be saved after thread preemption.
Summary: floating point registers seem not to be saved after thread preemption.
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 6.0-CURRENT
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-05-04 16:40 UTC by Marc Olzheim
Modified: 2005-05-25 12:40 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marc Olzheim 2005-05-04 16:40:02 UTC
	Floating point exception take place where they shouldn't when
	running with KSE threads (-pthread).

How-To-Repeat: # This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	fpu
#	fpu/Makefile
#	fpu/fpu5.c
#
echo c - fpu
mkdir -p fpu > /dev/null 2>&1
echo x - fpu/Makefile
sed 's/^X//' >fpu/Makefile << 'END-of-fpu/Makefile'
Xall: fpu5 fpu5th
X
Xfpu5th:	fpu5.c
X	cc -O3 -Wall -W -Werror -g -Wcast-qual -DWITH_THR -fstrict-aliasing -pthread fpu5.c -o fpu5th -lm
X
Xfpu5:	fpu5.c
X	cc -O3 -Wall -W -Werror -g -Wcast-qual -fstrict-aliasing fpu5.c -o fpu5 -lm
X
Xclean:
X	rm -f fpu5 fpu5th fpu5th.core core
END-of-fpu/Makefile
echo x - fpu/fpu5.c
sed 's/^X//' >fpu/fpu5.c << 'END-of-fpu/fpu5.c'
X/* Blame it in Marc Olzheim (Zlo) */
X
X#ifdef		WITH_THR
X#include	<pthread.h>
X#endif		/* WITH_THR */
X
X#include	<err.h>
X#include	<math.h>
X#include	<stdio.h>
X#include	<stdlib.h>
X#include	<sysexits.h>
X#include	<unistd.h>
X
Xvoid *
Xcalc_thread(void *arg)
X{
X	long		i;
X	unsigned char	c;
X
X	i = (long)arg + 1;
X
X	for (;;)
X	{
X		i = (i + 1) % 736;
X		if (i > 0)
X		{
X			/* ln(2.0) =~ 0.69 */
X			if (logf((float)1.0 + (float)i) < (float)0.65)
X			{
X				/* Never happens */
X				printf("\n\n\n\ni: %ld\n\n\n\n", i);
X				fflush(NULL);
X			}
X
X			/* Then why does _this_ go wrong ? */
X			c = floorf((float)(1.0 / logf((float)1.0 + (float)i)));
X
X			if (c > 1)	/* Never true, just to use c. */
X				printf("\r%hhu", c);
X		}
X	}
X
X	/* NOTREACHED */
X	return NULL;
X}
X
Xint
Xmain(int argc, char *argv[])
X{
X#ifdef		WITH_THR
X	pthread_t	thread;
X#endif		/* WITH_THR */
X
X	if (1 != argc)
X	{
X		fprintf(stderr, "Usage: %s\n", argv[0]);
X		return(EX_USAGE);
X	}
X
X#ifdef		WITH_THR
X	if (pthread_create(&thread , NULL, calc_thread, (void *)1L))
X		err(1, "pthread_create()");
X#else		/* ! WITH_THR */
X	(void)calc_thread((void *)1L);
X#endif		/* ! WITH_THR */
X
X	for (;;)
X		sleep(60);
X
X	return(EX_OK);
X}
END-of-fpu/fpu5.c
exit

Just compare the th version with the non-th version. The th version will
crash.

This happens on 6-CURRENT and on 5.4-STABLE and I've only been able to
reproduce it on i386, not on amd64. I don't have other test machines atm.

5.3-RELEASE seems unaffected.
Comment 1 Marc Olzheim 2005-05-04 20:56:28 UTC
It seems to have to do something with floorf(). Leaving it out, I can't
get it to crash atm.
Comment 2 Marc Olzheim 2005-05-04 21:28:39 UTC
floorf() and ceilf() are the only functions where this happens. When
replacing the code with doubles and using floor() and ceil() no problems
arise.

Both floorf() and ceilf() crash in "flds   0x8(%ebp)".
Comment 3 Marc Olzheim 2005-05-04 23:58:25 UTC
The following probably fixes it (thanks to the hint das@ provided).
For FreeBSD 5.4, just ignore the truncf() part, since that file hasn't
been MFC'd yet.

--- lib/msun/i387/s_ceilf.S	Thu Jan 13 19:58:25 2005
+++ lib/msun/i387/s_ceilf.S	Thu May  5 00:54:18 2005
@@ -13,17 +13,17 @@
 	movl	%esp,%ebp
 	subl	$8,%esp
 
-	fstcw	-12(%ebp)		/* store fpu control word */
-	movw	-12(%ebp),%dx
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
 	orw	$0x0800,%dx		/* round towards +oo */
 	andw	$0xfbff,%dx
-	movw	%dx,-16(%ebp)
-	fldcw	-16(%ebp)		/* load modfied control word */
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
 
 	flds	8(%ebp);		/* round */
 	frndint
 
-	fldcw	-12(%ebp)		/* restore original control word */
+	fldcw	-4(%ebp)		/* restore original control word */
 
 	leave
 	ret
--- lib/msun/i387/s_floorf.S	Thu Jan 13 19:58:25 2005
+++ lib/msun/i387/s_floorf.S	Thu May  5 00:54:29 2005
@@ -13,17 +13,17 @@
 	movl	%esp,%ebp
 	subl	$8,%esp
 
-	fstcw	-12(%ebp)		/* store fpu control word */
-	movw	-12(%ebp),%dx
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
 	orw	$0x0400,%dx		/* round towards -oo */
 	andw	$0xf7ff,%dx
-	movw	%dx,-16(%ebp)
-	fldcw	-16(%ebp)		/* load modfied control word */
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
 
 	flds	8(%ebp);		/* round */
 	frndint
 
-	fldcw	-12(%ebp)		/* restore original control word */
+	fldcw	-4(%ebp)		/* restore original control word */
 
 	leave
 	ret
--- lib/msun/i387/s_truncf.S	Sat Apr 16 23:12:55 2005
+++ lib/msun/i387/s_truncf.S	Thu May  5 00:54:35 2005
@@ -11,16 +11,16 @@
 	movl	%esp,%ebp
 	subl	$8,%esp
 
-	fstcw	-12(%ebp)		/* store fpu control word */
-	movw	-12(%ebp),%dx
+	fstcw	-4(%ebp)		/* store fpu control word */
+	movw	-4(%ebp),%dx
 	orw	$0x0c00,%dx		/* round towards -oo */
-	movw	%dx,-16(%ebp)
-	fldcw	-16(%ebp)		/* load modfied control word */
+	movw	%dx,-8(%ebp)
+	fldcw	-8(%ebp)		/* load modfied control word */
 
 	flds	8(%ebp)			/* round */
 	frndint
 
-	fldcw	-12(%ebp)		/* restore original control word */
+	fldcw	-4(%ebp)		/* restore original control word */
 
 	leave
 	ret
Comment 4 Daniel Eischen freebsd_committer freebsd_triage 2005-05-06 16:51:40 UTC
State Changed
From-To: open->closed

The problem was in libm (src/lib/msun) and fix was committed in -current.
Comment 5 Marc Olzheim 2005-05-25 12:39:04 UTC
Could this be MFC'd, please, pretty please, with sugar on top ?