bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

query: pthread_cond_timedwait and FPU state loss.


From: dtc
Subject: query: pthread_cond_timedwait and FPU state loss.
Date: Fri, 12 Oct 2001 17:27:03 +1000

The pthread_cond_timedwait function currently loses the floating
point control register state (linux/i386 port), so that an application
that has setup particular handling of floating point exceptions will
give unexpected results.  There is an example below.  This seems due
to the use of setjmp/longjmp which do not save the FPU state, so is
probably a more general issue.

Should an application expect that the C library could modify the
floating point control register settings?  The application could save
and restore the settings across calls to any code linked to the C
library.  Or is this a bug in the C library?

Regards
Douglas Crosher

-=-=-=-

/*
 * Demonstration of the loss of FPU state in pthread based numerical code.
 *
 * This can lead to the failure of numerical code, and results in an
 * unexpected state for signal handlers that could reasonably expect to be
 * able to examine the FPU state after FPU operations.
 */

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <asm/sigcontext.h>

#define getfpucw(cw) asm("fstcw %0" : "=m" (cw) :)
#define setfpucw(cw) asm("fldcw %0" : : "m" (cw))

int cond_done;
pthread_cond_t cond;
pthread_mutex_t cond_lock;

pthread_t thread1;

int sigtrap_handler(int signal, struct sigcontext contextstruct)
{
  printf("sigtrap: fpstate %p\n", contextstruct.fpstate);
}

void  test(void *fn)
{
  double  x = 0.0;
  int cw = 0;
  struct timeval now;
  struct timespec abstime;

  gettimeofday (&now, NULL);
  abstime.tv_nsec = now.tv_usec * 1000;
  abstime.tv_sec = now.tv_sec + 20;

  getfpucw(cw); printf("fpucw: %x\n", cw);

  setfpucw(cw & ~4);  /* For example, catch division by zero. */

  asm(" int3"); getfpucw(cw); printf("fpucw: %x\n", cw);

  pthread_mutex_lock(&cond_lock);
  while (!cond_done)
    pthread_cond_timedwait(&cond, &cond_lock, &abstime);
  pthread_mutex_unlock(&cond_lock);

  asm(" int3"); getfpucw(cw); printf("fpucw: %x\n", cw);

  /*
   * Could expect an exception after setting the state above.
   */

  x = 1.0 / x;

  printf("FPCW lost.\n");
}

main()
{
  struct sigaction sa;

  sa.sa_handler = sigtrap_handler;
  sa.sa_flags = SA_RESTART;
  sigaction(SIGTRAP, &sa, NULL);

  pthread_mutex_init(&cond_lock, NULL);
  pthread_cond_init(&cond, NULL);

  pthread_create(&thread1, NULL, test, NULL);

  sleep(1);

  cond_done = 1;
  pthread_cond_broadcast(&cond);

  pthread_join(thread1, NULL);
}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]