This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Implement fma correctly


On Wed, Oct 13, 2010 at 12:21:03PM -0400, Ulrich Drepper wrote:
> On Wed, Oct 13, 2010 at 11:30, Richard Henderson <rth@twiddle.net> wrote:
> > The x86 kernel doesn't set up a known fpu state on signal entry?
> > That seems like a bug to be fixed to me.
> 
> I don't know when it changed and whether it works in all situations,
> but it seems at least on recent kernels the signal handler is always
> run with FE_TONEAREST.  On x86-64.

Yeah, it seems for async signals (or sync signals too?) the FPU state is
reinitialized at least on x86_64 and i686, so we should be fine doing
this in libm.

#define _GNU_SOURCE
#include <fenv.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

pthread_barrier_t b;

void
print_fenv (int i)
{
  fenv_t env;
  fegetenv (&env);
#ifdef __x86_64__
  printf ("%d %08x %08x %08x\n", i, env.__control_word, env.__status_word, env.__mxcsr);
#elif defined __i386__
  printf ("%d %08x %08x\n", i, env.__control_word, env.__status_word);
#endif
}

volatile double d1 = 0x1p100;
volatile double d2 = 0x1p-100;
volatile double d3;
volatile long double l1 = 0x1p100L;
volatile long double l2 = 0x1p-100L;
volatile long double l3;

void
sig (int signum, siginfo_t *info, void *context)
{
  print_fenv (0);
}

void *
tf (void *arg)
{
  fenv_t env;
  print_fenv (1);
  d3 = d1 + d2;
  print_fenv (2);
  l3 = l1 + l2;
  print_fenv (3);
  feholdexcept (&env);
  fesetround (FE_TOWARDZERO);
  d3 = d1 + d2;
  l3 = l1 + l2;
  print_fenv (4);
  pthread_barrier_wait (&b);
  pthread_barrier_wait (&b);
  print_fenv (5);
  feenableexcept (FE_DIVBYZERO | FE_INVALID);
  print_fenv (6);
  pthread_barrier_wait (&b);
  pthread_barrier_wait (&b);
  print_fenv (7);
  return NULL;
}

int
main (void)
{
  struct sigaction sa;
  sigemptyset (&sa.sa_mask);
  sa.sa_sigaction = sig;
  sa.sa_flags = SA_SIGINFO;
  sigaction (SIGUSR1, &sa, NULL);
  pthread_barrier_init (&b, NULL, 2);
  pthread_t th;
  pthread_create (&th, NULL, tf, NULL);
  pthread_barrier_wait (&b);
  pthread_kill (th, SIGUSR1);
  pthread_barrier_wait (&b);
  pthread_barrier_wait (&b);
  pthread_kill (th, SIGUSR1);
  pthread_barrier_wait (&b);
  pthread_join (th, NULL);
  return 0;
}


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]