ead> [commits] r2181 - in /fsf/trunk/libc: ./ elf/ nptl/ posix/ stdio-common/ sysdeps/powerpc/bits/ sysdeps/powerpc/fpu/ sysdeps/unix/sysv/...
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r2181 - in /fsf/trunk/libc: ./ elf/ nptl/ posix/ stdio-common/ sysdeps/powerpc/bits/ sysdeps/powerpc/fpu/ sysdeps/unix/sysv/...



Author: eglibc
Date: Mon May  7 00:01:58 2007
New Revision: 2181

Log:
Import glibc-mainline for 2007-05-07

Added:
    fsf/trunk/libc/sysdeps/powerpc/fpu/fe_mask.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c
Removed:
    fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fe_nomask.c
Modified:
    fsf/trunk/libc/ChangeLog
    fsf/trunk/libc/elf/dl-addr.c
    fsf/trunk/libc/nptl/ChangeLog
    fsf/trunk/libc/nptl/tst-cancel-wrappers.sh
    fsf/trunk/libc/nptl/tst-cancel4.c
    fsf/trunk/libc/posix/unistd.h
    fsf/trunk/libc/stdio-common/vfprintf.c
    fsf/trunk/libc/sysdeps/powerpc/bits/fenv.h
    fsf/trunk/libc/sysdeps/powerpc/fpu/Makefile
    fsf/trunk/libc/sysdeps/powerpc/fpu/fe_nomask.c
    fsf/trunk/libc/sysdeps/powerpc/fpu/fedisblxcpt.c
    fsf/trunk/libc/sysdeps/powerpc/fpu/feholdexcpt.c
    fsf/trunk/libc/sysdeps/powerpc/fpu/fesetenv.c
    fsf/trunk/libc/sysdeps/powerpc/fpu/feupdateenv.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/syscalls.list

Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Mon May  7 00:01:58 2007
@@ -1,3 +1,52 @@
+2007-04-30  Steven Munroe  <sjmunroe@xxxxxxxxxx>
+            Peter Bergner  <bergner@xxxxxxxxxx>
+
+	* sysdeps/powerpc/bits/fenv.h: Declare __fe_mask_env extern.
+	Define FE_NOMASK_ENV as FE_EANBLED_ENV.  Define FE_MASK_ENV.
+	* sysdeps/powerpc/fpu/Makefile: Add fe_mask to libm-support.
+	* sysdeps/powerpc/fpu/fe_mask.c: New file.
+	* sysdeps/powerpc/fpu/fe_nomask.c: Correct comment.
+	* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept):
+	Call __fe_mask_env() if all FP exceptions disabled.
+	* sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Copy high 32-bits
+	from old FPSCR to new fenv to propagate DFP rounding modes.
+	Call __fe_mask_env() if FP exceptions previously enabled.
+	* sysdeps/powerpc/fpu/fesetenv.c (fesetenv): Change mask to merge
+	exceptions from env.  Use __fe_nomask_env() or __fe_mask_env() when
+	transitioning from all exceptions disabled to any exception enabled
+	or visa versa.
+	* sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Change mask to
+	merge exceptions from env.  Call __fe_nomask_env or __fe_mask_env
+	when transitioning from all exceptions disabled to any exception
+	enabled or visa versa.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c: Moved to...
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c: ...here.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fe_nomask.c: Moved to...
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c: ...here.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c: New file.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c: New file.
+
+2007-05-06  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	[BZ #4465]
+	* posix/unistd.h: Remove __THROW from fdatasync.
+
+2007-05-06  Mike Frysinger  <vapier@xxxxxxxxxx>
+
+	[BZ #4465]
+	* sysdeps/unix/sysv/linux/syscalls.list (fdatasync): Add "C" to args.
+
+2007-05-06  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* stdio-common/vfprintf.c (process_string_arg): Optimize
+	ridiculous precision in wide char code printing multi-byte string.
+	Reported by Jim Meyering <jim@xxxxxxxxxxxx>.
+
+	[BZ #4131]
+	* elf/dl-addr.c (_dl_addr): Compare address with actual segment
+	boundaries to work around systems with overlapping binary loading.
+	Based on a patch by Suzuki <suzuki@xxxxxxxxxx>.
+
 2007-05-04  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	* stdio-common/vfprintf.c (process_string_arg): Adjust call to

Modified: fsf/trunk/libc/elf/dl-addr.c
==============================================================================
--- fsf/trunk/libc/elf/dl-addr.c (original)
+++ fsf/trunk/libc/elf/dl-addr.c Mon May  7 00:01:58 2007
@@ -1,5 +1,5 @@
 /* Locate the shared object symbol nearest a given address.
-   Copyright (C) 1996-2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1996-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -22,137 +22,137 @@
 #include <ldsodefs.h>
 
 
+static void
+__attribute ((always_inline))
+determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
+		struct link_map **mapp, const ElfW(Sym) **symbolp)
+{
+  /* Now we know what object the address lies in.  */
+  info->dli_fname = match->l_name;
+  info->dli_fbase = (void *) match->l_map_start;
+
+  /* If this is the main program the information is incomplete.  */
+  if (__builtin_expect (match->l_name[0], 'a') == '\0'
+      && match->l_type == lt_executable)
+    info->dli_fname = _dl_argv[0];
+
+  const ElfW(Sym) *symtab
+    = (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]);
+  const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]);
+
+  ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
+
+  const ElfW(Sym) *matchsym = NULL;
+  if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
+		    + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL)
+    {
+      /* We look at all symbol table entries referenced by the hash
+	 table.  */
+      for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket)
+	{
+	  Elf32_Word symndx = match->l_gnu_buckets[bucket];
+	  if (symndx != 0)
+	    {
+	      const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx];
+
+	      do
+		{
+		  /* The hash table never references local symbols so
+		     we can omit that test here.  */
+		  if ((symtab[symndx].st_shndx != SHN_UNDEF
+		       || symtab[symndx].st_value != 0)
+		      && ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
+		      && DL_ADDR_SYM_MATCH (match, &symtab[symndx],
+					    matchsym, addr)
+		      && symtab[symndx].st_name < strtabsize)
+		    matchsym = (ElfW(Sym) *) &symtab[symndx];
+
+		  ++symndx;
+		}
+	      while ((*hasharr++ & 1u) == 0);
+	    }
+	}
+    }
+  else
+    {
+      const ElfW(Sym) *symtabend;
+      if (match->l_info[DT_HASH] != NULL)
+	symtabend = (symtab
+		     + ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
+      else
+	/* There is no direct way to determine the number of symbols in the
+	   dynamic symbol table and no hash table is present.  The ELF
+	   binary is ill-formed but what shall we do?  Use the beginning of
+	   the string table which generally follows the symbol table.  */
+	symtabend = (const ElfW(Sym) *) strtab;
+
+      for (; (void *) symtab < (void *) symtabend; ++symtab)
+	if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
+	     || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
+	    && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
+	    && (symtab->st_shndx != SHN_UNDEF
+		|| symtab->st_value != 0)
+	    && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
+	    && symtab->st_name < strtabsize)
+	  matchsym = (ElfW(Sym) *) symtab;
+    }
+
+  if (mapp)
+    *mapp = match;
+  if (symbolp)
+    *symbolp = matchsym;
+
+  if (matchsym)
+    {
+      /* We found a symbol close by.  Fill in its name and exact
+	 address.  */
+      lookup_t matchl = LOOKUP_VALUE (match);
+
+      info->dli_sname = strtab + matchsym->st_name;
+      info->dli_saddr = DL_SYMBOL_ADDRESS (matchl, matchsym);
+    }
+  else
+    {
+      /* No symbol matches.  We return only the containing object.  */
+      info->dli_sname = NULL;
+      info->dli_saddr = NULL;
+    }
+}
+
+
 int
 internal_function
 _dl_addr (const void *address, Dl_info *info,
 	  struct link_map **mapp, const ElfW(Sym) **symbolp)
 {
   const ElfW(Addr) addr = DL_LOOKUP_ADDRESS (address);
+  int result = 0;
 
   /* Protect against concurrent loads and unloads.  */
   __rtld_lock_lock_recursive (GL(dl_load_lock));
 
   /* Find the highest-addressed object that ADDRESS is not below.  */
-  struct link_map *match = NULL;
   for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
     for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next)
       if (addr >= l->l_map_start && addr < l->l_map_end)
 	{
-	  /* We know ADDRESS lies within L if in any shared object.
-	     Make sure it isn't past the end of L's segments.  */
-	  size_t n = l->l_phnum;
-	  if (n > 0)
-	    {
-	      do
-		--n;
-	      while (l->l_phdr[n].p_type != PT_LOAD);
-	      if (addr >= (l->l_addr +
-			   l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz))
-		/* Off the end of the highest-addressed shared object.  */
-		continue;
-	    }
-
-	  match = l;
-	  break;
+	  /* Make sure it lies within one of L's segments.  */
+	  int n = l->l_phnum;
+	  const ElfW(Addr) reladdr = addr - l->l_addr;
+	  while (--n >= 0)
+	    if (l->l_phdr[n].p_type == PT_LOAD)
+	      {
+		if (reladdr - l->l_phdr[n].p_vaddr >= 0
+		    && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
+		  {
+		    determine_info (addr, l, info, mapp, symbolp);
+		    result = 1;
+		    goto out;
+		  }
+	      }
 	}
 
-  int result = 0;
-  if (match != NULL)
-    {
-      /* Now we know what object the address lies in.  */
-      info->dli_fname = match->l_name;
-      info->dli_fbase = (void *) match->l_map_start;
-
-      /* If this is the main program the information is incomplete.  */
-      if (__builtin_expect (match->l_name[0], 'a') == '\0'
-	  && match->l_type == lt_executable)
-	info->dli_fname = _dl_argv[0];
-
-      const ElfW(Sym) *symtab
-	= (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]);
-      const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]);
-
-      ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
-
-      const ElfW(Sym) *matchsym = NULL;
-      if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
-			+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL)
-	{
-	  /* We look at all symbol table entries referenced by the
-	     hash table.  */
-	  for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket)
-	    {
-	      Elf32_Word symndx = match->l_gnu_buckets[bucket];
-	      if (symndx != 0)
-		{
-		  const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx];
-
-		  do
-		    {
-		      /* The hash table never references local symbols
-			 so we can omit that test here.  */
-		      if ((symtab[symndx].st_shndx != SHN_UNDEF
-			   || symtab[symndx].st_value != 0)
-			  && ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
-			  && DL_ADDR_SYM_MATCH (match, &symtab[symndx],
-						matchsym, addr)
-			  && symtab[symndx].st_name < strtabsize)
-			matchsym = (ElfW(Sym) *) &symtab[symndx];
-
-		      ++symndx;
-		    }
-		  while ((*hasharr++ & 1u) == 0);
-		}
-	    }
-	}
-      else
-	{
-	  const ElfW(Sym) *symtabend;
-	  if (match->l_info[DT_HASH] != NULL)
-	    symtabend = (symtab
-			 + ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
-	  else
-	    /* There is no direct way to determine the number of symbols in the
-	       dynamic symbol table and no hash table is present.  The ELF
-	       binary is ill-formed but what shall we do?  Use the beginning of
-	       the string table which generally follows the symbol table.  */
-	    symtabend = (const ElfW(Sym) *) strtab;
-
-	  for (; (void *) symtab < (void *) symtabend; ++symtab)
-	    if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
-		 || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
-		&& ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
-		&& (symtab->st_shndx != SHN_UNDEF
-		    || symtab->st_value != 0)
-		&& DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
-		&& symtab->st_name < strtabsize)
-	      matchsym = (ElfW(Sym) *) symtab;
-	}
-
-      if (mapp)
-	*mapp = match;
-      if (symbolp)
-	*symbolp = matchsym;
-
-      if (matchsym)
-	{
-	  /* We found a symbol close by.  Fill in its name and exact
-	     address.  */
-	  lookup_t matchl = LOOKUP_VALUE (match);
-
-	  info->dli_sname = strtab + matchsym->st_name;
-	  info->dli_saddr = DL_SYMBOL_ADDRESS (matchl, matchsym);
-	}
-      else
-	{
-	  /* No symbol matches.  We return only the containing object.  */
-	  info->dli_sname = NULL;
-	  info->dli_saddr = NULL;
-	}
-
-      result = 1;
-    }
-
+ out:
   __rtld_lock_unlock_recursive (GL(dl_load_lock));
 
   return result;

Modified: fsf/trunk/libc/nptl/ChangeLog
==============================================================================
--- fsf/trunk/libc/nptl/ChangeLog (original)
+++ fsf/trunk/libc/nptl/ChangeLog Mon May  7 00:01:58 2007
@@ -1,3 +1,9 @@
+2007-05-06  Mike Frysinger  <vapier@xxxxxxxxxx>
+
+	[BZ #4465]
+	* tst-cancel-wrappers.sh: Set C["fdatasync"] to 1.
+	* tst-cancel4.c (tf_fdatasync): New test.
+
 2007-04-27  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	[BZ #4392]

Modified: fsf/trunk/libc/nptl/tst-cancel-wrappers.sh
==============================================================================
--- fsf/trunk/libc/nptl/tst-cancel-wrappers.sh (original)
+++ fsf/trunk/libc/nptl/tst-cancel-wrappers.sh Mon May  7 00:01:58 2007
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Test whether all cancelable functions are cancelable.
-# Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 # Contributed by Jakub Jelinek <jakub@xxxxxxxxxx>, 2002.
 
@@ -26,6 +26,7 @@
 C["connect"]=1
 C["creat"]=1
 C["fcntl"]=1
+C["fdatasync"]=1
 C["fsync"]=1
 C["msgrcv"]=1
 C["msgsnd"]=1

Modified: fsf/trunk/libc/nptl/tst-cancel4.c
==============================================================================
--- fsf/trunk/libc/nptl/tst-cancel4.c (original)
+++ fsf/trunk/libc/nptl/tst-cancel4.c Mon May  7 00:01:58 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2002.
 
@@ -1565,6 +1565,47 @@
   pthread_cleanup_pop (0);
 
   printf ("%s: fsync returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_fdatasync (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which fdatasync()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  tempfd = open ("Makefile", O_RDONLY);
+  if (tempfd == -1)
+    {
+      printf ("%s: cannot open Makefile\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  fdatasync (tempfd);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: fdatasync returned\n", __FUNCTION__);
 
   exit (1);
 }
@@ -2078,6 +2119,7 @@
   ADD_TEST (pread, 2, 1),
   ADD_TEST (pwrite, 2, 1),
   ADD_TEST (fsync, 2, 1),
+  ADD_TEST (fdatasync, 2, 1),
   ADD_TEST (msync, 2, 1),
   ADD_TEST (sendto, 2, 1),
   ADD_TEST (sendmsg, 2, 1),

Modified: fsf/trunk/libc/posix/unistd.h
==============================================================================
--- fsf/trunk/libc/posix/unistd.h (original)
+++ fsf/trunk/libc/posix/unistd.h Mon May  7 00:01:58 2007
@@ -1062,7 +1062,7 @@
 #if defined __USE_POSIX199309 || defined __USE_UNIX98
 /* Synchronize at least the data part of a file with the underlying
    media.  */
-extern int fdatasync (int __fildes) __THROW;
+extern int fdatasync (int __fildes);
 #endif /* Use POSIX199309 */
 
 

Modified: fsf/trunk/libc/stdio-common/vfprintf.c
==============================================================================
--- fsf/trunk/libc/stdio-common/vfprintf.c (original)
+++ fsf/trunk/libc/stdio-common/vfprintf.c Mon May  7 00:01:58 2007
@@ -1026,10 +1026,11 @@
 	    const char *mbs = (const char *) string;			      \
 	    mbstate_t mbstate;						      \
 									      \
-	    len = prec != -1 ? (size_t) prec : strlen (mbs);		      \
+	    len = prec != -1 ? __strnlen (mbs, (size_t) prec) : strlen (mbs); \
 									      \
 	    /* Allocate dynamically an array which definitely is long	      \
-	       enough for the wide character version.  */		      \
+	       enough for the wide character version.  Each byte in the	      \
+	       multi-byte string can produce at most one wide character.  */  \
 	    if (__libc_use_alloca (len * sizeof (wchar_t)))		      \
 	      string = (CHAR_T *) alloca (len * sizeof (wchar_t));	      \
 	    else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t)))    \

Modified: fsf/trunk/libc/sysdeps/powerpc/bits/fenv.h
==============================================================================
--- fsf/trunk/libc/sysdeps/powerpc/bits/fenv.h (original)
+++ fsf/trunk/libc/sysdeps/powerpc/bits/fenv.h Mon May  7 00:01:58 2007
@@ -137,9 +137,19 @@
 # define FE_NONIEEE_ENV	(&__fe_nonieee_env)
 
 /* Floating-point environment with all exceptions enabled.  Note that
-   just evaluating this value will set the processor into 'FPU
-   exceptions imprecise recoverable' mode, which may cause a significant
-   performance penalty (but have no other visible effect).  */
+   just evaluating this value does not change the processor exception mode.
+   Passing this mask to fesetenv will result in a prctl syscall to change
+   the MSR FE0/FE1 bits to "Precise Mode".  On some processors this will
+   result in slower floating point execution.  This will last until an
+   fenv or exception mask is installed that disables all FP exceptions.  */
 extern const fenv_t *__fe_nomask_env (void);
-# define FE_NOMASK_ENV	(__fe_nomask_env ())
+# define FE_NOMASK_ENV	FE_ENABLED_ENV
+
+/* Floating-point environment with all exceptions disabled.  Note that
+   just evaluating this value does not change the processor exception mode.
+   Passing this mask to fesetenv will result in a prctl syscall to change
+   the MSR FE0/FE1 bits to "Ignore Exceptions Mode".  On most processors
+   this allows the fastest possible floating point execution.*/
+extern const fenv_t *__fe_mask_env (void);
+# define FE_MASK_ENV	FE_DFL_ENV
 #endif

Modified: fsf/trunk/libc/sysdeps/powerpc/fpu/Makefile
==============================================================================
Binary files - no diff available.

Added: fsf/trunk/libc/sysdeps/powerpc/fpu/fe_mask.c
==============================================================================
--- fsf/trunk/libc/sysdeps/powerpc/fpu/fe_mask.c (added)
+++ fsf/trunk/libc/sysdeps/powerpc/fpu/fe_mask.c Mon May  7 00:01:58 2007
@@ -1,0 +1,33 @@
+/* Procedure definition for FE_MASK_ENV.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <fenv.h>
+#include <errno.h>
+
+/* This is a generic stub. An OS specific override is required to clear
+   the FE0/FE1 bits in the MSR.  MSR update is privileged, so this will
+   normally involve a syscall.  */
+
+const fenv_t *
+__fe_mask_env(void)
+{
+  __set_errno (ENOSYS);
+  return FE_DFL_ENV;
+}
+stub_warning (__fe_mask_env)

Modified: fsf/trunk/libc/sysdeps/powerpc/fpu/fe_nomask.c
==============================================================================
--- fsf/trunk/libc/sysdeps/powerpc/fpu/fe_nomask.c (original)
+++ fsf/trunk/libc/sysdeps/powerpc/fpu/fe_nomask.c Mon May  7 00:01:58 2007
@@ -20,8 +20,9 @@
 #include <fenv.h>
 #include <errno.h>
 
-/* This is presently a stub, until it's decided how the kernels should
-   support this.  */
+/* This is a generic stub. An OS specific override is required to set
+   the FE0/FE1 bits in the MSR.  MSR update is privileged, so this will
+   normally involve a syscall.  */
 
 const fenv_t *
 __fe_nomask_env(void)

Modified: fsf/trunk/libc/sysdeps/powerpc/fpu/fedisblxcpt.c
==============================================================================
--- fsf/trunk/libc/sysdeps/powerpc/fpu/fedisblxcpt.c (original)
+++ fsf/trunk/libc/sysdeps/powerpc/fpu/fedisblxcpt.c Mon May  7 00:01:58 2007
@@ -24,7 +24,7 @@
 fedisableexcept (int excepts)
 {
   fenv_union_t fe;
-  int result;
+  int result, new;
 
   result = fegetexcept ();
 
@@ -44,7 +44,11 @@
     fe.l[1] &= ~(1 << (31 - FPSCR_VE));
   fesetenv_register (fe.fenv);
 
-  if ((fegetexcept () & excepts) != 0)
+  new = fegetexcept ();
+  if (new == 0 && result != 0)
+    (void)__fe_mask_env ();
+
+  if ((new & excepts) != 0)
     result = -1;
   return result;
 }

Modified: fsf/trunk/libc/sysdeps/powerpc/fpu/feholdexcpt.c
==============================================================================
--- fsf/trunk/libc/sysdeps/powerpc/fpu/feholdexcpt.c (original)
+++ fsf/trunk/libc/sysdeps/powerpc/fpu/feholdexcpt.c Mon May  7 00:01:58 2007
@@ -22,17 +22,24 @@
 int
 feholdexcept (fenv_t *envp)
 {
-  fenv_union_t u;
+  fenv_union_t old, new;
 
-  /* Get the current state.  */
-  u.fenv = *envp = fegetenv_register ();
+  /* Save the currently set exceptions.  */
+  old.fenv = *envp = fegetenv_register ();
 
-  /* Clear everything except for the rounding mode and non-IEEE arithmetic
+  /* Clear everything except for the rounding modes and non-IEEE arithmetic
      flag.  */
-  u.l[1] = u.l[1] & 7;
+  new.l[1] = old.l[1] & 7;
+  new.l[0] = old.l[0];
+  
+  /* If the old env had any eabled exceptions, then mask SIGFPE in the
+     MSR FE0/FE1 bits.  This may allow the FPU to run faster because it
+     always takes the default action and can not generate SIGFPE. */
+  if ((old.l[1] & 0x000000F8) != 0)
+    (void)__fe_mask_env ();
 
   /* Put the new state in effect.  */
-  fesetenv_register (u.fenv);
+  fesetenv_register (new.fenv);
 
   return 0;
 }

Modified: fsf/trunk/libc/sysdeps/powerpc/fpu/fesetenv.c
==============================================================================
--- fsf/trunk/libc/sysdeps/powerpc/fpu/fesetenv.c (original)
+++ fsf/trunk/libc/sysdeps/powerpc/fpu/fesetenv.c Mon May  7 00:01:58 2007
@@ -1,5 +1,5 @@
 /* Install given floating-point environment.
-   Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc.
+   Copyright (C) 1997,99,2000,01,02,07 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -23,6 +23,26 @@
 int
 __fesetenv (const fenv_t *envp)
 {
+  fenv_union_t old, new;
+
+  /* get the currently set exceptions.  */
+  new.fenv = *envp;
+  old.fenv = fegetenv_register ();
+  
+  /* If the old env has no eabled exceptions and the new env has any enabled
+     exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits.  This will put
+     the hardware into "precise mode" and may cause the FPU to run slower on
+     some hardware.  */
+  if ((old.l[1] & 0x000000F8) == 0 && (new.l[1] & 0x000000F8) != 0)
+    (void)__fe_nomask_env ();
+  
+  /* If the old env had any eabled exceptions and the new env has no enabled
+     exceptions, then mask SIGFPE in the MSR FE0/FE1 bits.  This may allow the
+     FPU to run faster because it always takes the default action and can not 
+     generate SIGFPE. */
+  if ((old.l[1] & 0x000000F8) != 0 && (new.l[1] & 0x000000F8) == 0)
+    (void)__fe_mask_env ();
+    
   fesetenv_register (*envp);
 
   /* Success.  */

Modified: fsf/trunk/libc/sysdeps/powerpc/fpu/feupdateenv.c
==============================================================================
--- fsf/trunk/libc/sysdeps/powerpc/fpu/feupdateenv.c (original)
+++ fsf/trunk/libc/sysdeps/powerpc/fpu/feupdateenv.c Mon May  7 00:01:58 2007
@@ -1,5 +1,5 @@
 /* Install given floating-point environment and raise exceptions.
-   Copyright (C) 1997,99,2000,01 Free Software Foundation, Inc.
+   Copyright (C) 1997,99,2000,01,07 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 1997.
 
@@ -30,8 +30,24 @@
   new.fenv = *envp;
   old.fenv = fegetenv_register ();
 
-  /* Copy the set exceptions from `old' to `new'.  */
-  new.l[1] = (new.l[1] & 0xE00000FF) | (old.l[1] & 0x1FFFFF00);
+  /* Restore rounding mode and exception enable from *envp and merge
+     exceptions.  Leave fraction rounded/inexact and FP result/CC bits
+     unchanged.  */
+  new.l[1] = (old.l[1] & 0x1FFFFF00) | (new.l[1] & 0x1FF80FFF);
+  
+  /* If the old env has no eabled exceptions and the new env has any enabled
+     exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits.  This will put
+     the hardware into "precise mode" and may cause the FPU to run slower on
+     some hardware.  */
+  if ((old.l[1] & 0x000000F8) == 0 && (new.l[1] & 0x000000F8) != 0)
+    (void)__fe_nomask_env ();
+  
+  /* If the old env had any eabled exceptions and the new env has no enabled
+     exceptions, then mask SIGFPE in the MSR FE0/FE1 bits.  This may allow the
+     FPU to run faster because it always takes the default action and can not 
+     generate SIGFPE. */
+  if ((old.l[1] & 0x000000F8) != 0 && (new.l[1] & 0x000000F8) == 0)
+    (void)__fe_mask_env ();
 
   /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
   fesetenv_register (new.fenv);

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c Mon May  7 00:01:58 2007
@@ -1,0 +1,68 @@
+/* Procedure definition for FE_MASK_ENV for Linux/ppc.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <fenv.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+#include <kernel-features.h>
+
+#if __ASSUME_NEW_PRCTL_SYSCALL == 0
+/* This is rather fiddly under Linux.  We don't have direct access,
+   and there is no system call, but we can change the bits
+   in a signal handler's context...  */
+
+static struct sigaction oact;
+
+static void
+fe_mask_handler (int signum, struct sigcontext *sc)
+{
+  sc->regs->msr &= ~0x900ul;  /* FE0 | FE1 */
+  sigaction (SIGUSR1, &oact, NULL);
+}
+#endif
+
+const fenv_t *
+__fe_mask_env (void)
+{
+#if __ASSUME_NEW_PRCTL_SYSCALL == 0
+# if defined PR_SET_FPEXC && defined PR_FP_EXC_DISABLED
+  int result = INLINE_SYSCALL (prctl, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
+
+  if (result == -1 && errno == EINVAL)
+# endif
+    {
+      struct sigaction act;
+
+      act.sa_handler = (sighandler_t) fe_mask_handler;
+      sigemptyset (&act.sa_mask);
+      act.sa_flags = 0;
+
+      sigaction (SIGUSR1, &act, &oact);
+      raise (SIGUSR1);
+    }
+#else
+  INTERNAL_SYSCALL_DECL (err);
+  INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
+#endif
+
+  return FE_DFL_ENV;
+}

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c Mon May  7 00:01:58 2007
@@ -1,0 +1,68 @@
+/* Procedure definition for FE_NOMASK_ENV for Linux/ppc.
+   Copyright (C) 2000, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <fenv.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sysdep.h>
+#include <sys/prctl.h>
+#include <kernel-features.h>
+
+#if __ASSUME_NEW_PRCTL_SYSCALL == 0
+/* This is rather fiddly under Linux.  We don't have direct access,
+   and there is no system call, but we can change the bits
+   in a signal handler's context...  */
+
+static struct sigaction oact;
+
+static void
+fe_nomask_handler (int signum, struct sigcontext *sc)
+{
+  sc->regs->msr |= 0x900ul;  /* FE0 | FE1 */
+  sigaction (SIGUSR1, &oact, NULL);
+}
+#endif
+
+const fenv_t *
+__fe_nomask_env (void)
+{
+#if __ASSUME_NEW_PRCTL_SYSCALL == 0
+# if defined PR_SET_FPEXC && defined PR_FP_EXC_PRECISE
+  int result = INLINE_SYSCALL (prctl, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE);
+
+  if (result == -1 && errno == EINVAL)
+# endif
+    {
+      struct sigaction act;
+
+      act.sa_handler = (sighandler_t) fe_nomask_handler;
+      sigemptyset (&act.sa_mask);
+      act.sa_flags = 0;
+
+      sigaction (SIGUSR1, &act, &oact);
+      raise (SIGUSR1);
+    }
+#else
+  INTERNAL_SYSCALL_DECL (err);
+  INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE);
+#endif
+
+  return FE_ENABLED_ENV;
+}

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c Mon May  7 00:01:58 2007
@@ -1,0 +1,43 @@
+/* Procedure definition for FE_MASK_ENV for Linux/ppc64.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <fenv.h>
+#include <errno.h>
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
+#include <kernel-features.h>
+
+const fenv_t *
+__fe_mask_env (void)
+{
+#if defined PR_SET_FPEXC && defined PR_FP_EXC_DISABLED
+  int result;
+  INTERNAL_SYSCALL_DECL (err);
+  result = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
+# ifndef __ASSUME_NEW_PRCTL_SYSCALL
+  if (INTERNAL_SYSCALL_ERROR_P (result, err)
+      && INTERNAL_SYSCALL_ERRNO (result, err) == EINVAL)
+    __set_errno (ENOSYS);
+# endif
+#else
+  __set_errno (ENOSYS);
+#endif
+  return FE_DFL_ENV;
+}

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c Mon May  7 00:01:58 2007
@@ -1,0 +1,43 @@
+/* Procedure definition for FE_NOMASK_ENV for Linux/ppc64.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <fenv.h>
+#include <errno.h>
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
+#include <kernel-features.h>
+
+const fenv_t *
+__fe_nomask_env (void)
+{
+#if defined PR_SET_FPEXC && defined PR_FP_EXC_PRECISE
+  int result;
+  INTERNAL_SYSCALL_DECL (err);
+  result = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE);
+# ifndef __ASSUME_NEW_PRCTL_SYSCALL
+  if (INTERNAL_SYSCALL_ERROR_P (result, err)
+      && INTERNAL_SYSCALL_ERRNO (result, err) == EINVAL)
+    __set_errno (ENOSYS);
+# endif
+#else
+  __set_errno (ENOSYS);
+#endif
+  return FE_ENABLED_ENV;
+}

Modified: fsf/trunk/libc/sysdeps/unix/sysv/linux/syscalls.list
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/syscalls.list (original)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/syscalls.list Mon May  7 00:01:58 2007
@@ -11,7 +11,7 @@
 epoll_ctl	EXTRA	epoll_ctl	i:iiip	epoll_ctl
 epoll_wait	EXTRA	epoll_wait	Ci:ipii	epoll_wait
 epoll_pwait	EXTRA	epoll_pwait	Ci:ipiipi	epoll_pwait
-fdatasync	-	fdatasync	i:i	fdatasync
+fdatasync	-	fdatasync	Ci:i	fdatasync
 flock		-	flock		i:ii	__flock		flock
 fork		-	fork		i:	__libc_fork	__fork fork
 get_kernel_syms	EXTRA	get_kernel_syms	i:p	get_kernel_syms