about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-08-10 06:34:46 +0000
committerJakub Jelinek <jakub@redhat.com>2006-08-10 06:34:46 +0000
commit256926546643ba909661c83e7a7d24d733b9b390 (patch)
tree71942c1328ec0cd2dc910d9443124ad2ee0539fc
parent503d6a958581777473c31f73113d0fa6cff19b30 (diff)
downloadglibc-256926546643ba909661c83e7a7d24d733b9b390.tar.gz
glibc-256926546643ba909661c83e7a7d24d733b9b390.tar.xz
glibc-256926546643ba909661c83e7a7d24d733b9b390.zip
Updated to fedora-glibc-20060810T0627 cvs/fedora-glibc-2_4_90-19
-rw-r--r--ChangeLog37
-rw-r--r--fedora/branch.mk4
-rw-r--r--fedora/glibc.spec.in8
-rw-r--r--malloc/malloc.c82
-rw-r--r--malloc/memusagestat.c25
-rw-r--r--nis/nis_xdr.c48
-rw-r--r--stdio-common/bug16.c35
-rw-r--r--stdlib/strtol_l.c27
-rw-r--r--sysdeps/s390/fpu/libm-test-ulps36
-rw-r--r--sysdeps/unix/sysv/linux/i386/fchownat.c42
-rw-r--r--sysdeps/unix/sysv/linux/ia64/bits/fcntl.h2
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/fchownat.c48
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c30
-rw-r--r--sysdeps/unix/sysv/linux/sh/fchownat.c30
14 files changed, 346 insertions, 108 deletions
diff --git a/ChangeLog b/ChangeLog
index dc3e0391b9..a356c15e3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2006-08-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* malloc/memusagestat.c: Silence warnings.
+
+	* malloc/malloc.c: Dynamically size mmap treshold if the program
+	frees mmaped blocks.
+	Patch by Valerie Henson and Arjan van de Ven.
+
+2006-08-08  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/ia64/bits/fcntl.h (O_DIRECT): Protect with
+	__USE_GNU.
+
+	* stdlib/strtol_l.c (__strtol_ul_max_tab, __strtol_ul_rem_tab,
+	__strtol_ull_max_tab, __strtol_ull_rem_tab): Declare.
+	(DEF): Don't put the var into .gnu.linkonce.r.* section.
+	Only provide var definitions in strtol_l (or for *ull*
+	in strtoll_l).
+
+	* stdio-common/bug16.c (tests): New array.
+	(do_tests): Allow the first hexadecimal digit
+	to be 1, 2, 4 or 8.  Do 3 additional tests.
+
+	* sysdeps/s390/fpu/libm-test-ulps: Update.
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c (fchownat): Use
+	fchownat syscall if available.
+	* sysdeps/unix/sysv/linux/powerpc/fchownat.c (fchownat): Likewise.
+	* sysdeps/unix/sysv/linux/sh/fchownat.c (fchownat): Likewise.
+	* sysdeps/unix/sysv/linux/i386/fchownat.c (fchownat): Likewise.
+
+2006-08-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* nis/nis_xdr.c: Avoid some function calls.
+
 2006-08-07  Jakub Jelinek  <jakub@redhat.com>
             Ulrich Drepper  <drepper@redhat.com>
 
@@ -7,7 +42,7 @@
 2006-08-07  Ulrich Drepper  <drepper@redhat.com>
 
 	* nis/nis_call.c: Minor cleanups throughout.
-	(rec_dirsearch) [HIGHER_NAME]: Correctly size ndomain array.
+	(rec_dirsearch) [case HIGHER_NAME]: Correctly size ndomain array.
 	(first_shoot): Add search_parent_first parameter.  Only if it is set
 	search parent server first.
 	If directory for table found through cold start cache is not the same
diff --git a/fedora/branch.mk b/fedora/branch.mk
index 5c2c1cdbd4..4a26c92c8e 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -3,5 +3,5 @@ glibc-branch := fedora
 glibc-base := HEAD
 DIST_BRANCH := devel
 COLLECTION := dist-fc4
-fedora-sync-date := 2006-08-07 18:59 UTC
-fedora-sync-tag := fedora-glibc-20060807T1859
+fedora-sync-date := 2006-08-10 06:27 UTC
+fedora-sync-tag := fedora-glibc-20060810T0627
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index ba46724e32..3ae97585c2 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,4 +1,4 @@
-%define glibcrelease 18
+%define glibcrelease 19
 %define auxarches i586 i686 athlon sparcv9 alphaev6
 %define xenarches i686 athlon
 %ifarch %{xenarches}
@@ -1438,6 +1438,12 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Thu Aug 10 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-19
+- adaptive malloc brk/mmap threshold
+- fix fchownat to use kernel syscall (if available) on many arches (#201870)
+- only define O_DIRECT with -D_GNU_SOURCE on ia64 to match all
+  other arches (#201748)
+
 * Mon Aug  7 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-18
 - NIS+ fixes
 - fix memusage and xtrace scripts (#200736)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index da230d3493..890d3669e2 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1415,6 +1415,19 @@ int      __posix_memalign(void **, size_t, size_t);
 #endif
 
 /*
+  MMAP_THRESHOLD_MAX and _MIN are the bounds on the dynamically
+  adjusted MMAP_THRESHOLD.
+*/
+
+#ifndef DEFAULT_MMAP_THRESHOLD_MIN
+#define DEFAULT_MMAP_THRESHOLD_MIN (128 * 1024)
+#endif
+
+#ifndef DEFAULT_MMAP_THRESHOLD_MAX
+#define DEFAULT_MMAP_THRESHOLD_MAX (8 * 1024 * 1024 * sizeof(long))
+#endif
+
+/*
   M_MMAP_THRESHOLD is the request size threshold for using mmap()
   to service a request. Requests of at least this size that cannot
   be allocated using already-existing space will be serviced via mmap.
@@ -1453,12 +1466,63 @@ int      __posix_memalign(void **, size_t, size_t);
   "large" chunks, but the value of "large" varies across systems.  The
   default is an empirically derived value that works well in most
   systems.
+
+
+  Update in 2006:
+  The above was written in 2001. Since then the world has changed a lot.
+  Memory got bigger. Applications got bigger. The virtual address space
+  layout in 32 bit linux changed.
+
+  In the new situation, brk() and mmap space is shared and there are no
+  artificial limits on brk size imposed by the kernel. What is more,
+  applications have started using transient allocations larger than the
+  128Kb as was imagined in 2001.
+
+  The price for mmap is also high now; each time glibc mmaps from the
+  kernel, the kernel is forced to zero out the memory it gives to the
+  application. Zeroing memory is expensive and eats a lot of cache and
+  memory bandwidth. This has nothing to do with the efficiency of the
+  virtual memory system, by doing mmap the kernel just has no choice but
+  to zero.
+
+  In 2001, the kernel had a maximum size for brk() which was about 800
+  megabytes on 32 bit x86, at that point brk() would hit the first
+  mmaped shared libaries and couldn't expand anymore. With current 2.6
+  kernels, the VA space layout is different and brk() and mmap
+  both can span the entire heap at will.
+
+  Rather than using a static threshold for the brk/mmap tradeoff,
+  we are now using a simple dynamic one. The goal is still to avoid
+  fragmentation. The old goals we kept are
+  1) try to get the long lived large allocations to use mmap()
+  2) really large allocations should always use mmap()
+  and we're adding now:
+  3) transient allocations should use brk() to avoid forcing the kernel
+     having to zero memory over and over again
+
+  The implementation works with a sliding threshold, which is by default
+  limited to go between 128Kb and 32Mb (64Mb for 64 bitmachines) and starts
+  out at 128Kb as per the 2001 default.
+
+  This allows us to satisfy requirement 1) under the assumption that long
+  lived allocations are made early in the process' lifespan, before it has
+  started doing dynamic allocations of the same size (which will
+  increase the threshold).
+
+  The upperbound on the threshold satisfies requirement 2)
+
+  The threshold goes up in value when the application frees memory that was
+  allocated with the mmap allocator. The idea is that once the application
+  starts freeing memory of a certain size, it's highly probable that this is
+  a size the application uses for transient allocations. This estimator
+  is there to satisfy the new third requirement.
+
 */
 
 #define M_MMAP_THRESHOLD      -3
 
 #ifndef DEFAULT_MMAP_THRESHOLD
-#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
+#define DEFAULT_MMAP_THRESHOLD DEFAULT_MMAP_THRESHOLD_MIN
 #endif
 
 /*
@@ -2251,6 +2315,10 @@ struct malloc_par {
   int              n_mmaps;
   int              n_mmaps_max;
   int              max_n_mmaps;
+  /* the mmap_threshold is dynamic, until the user sets
+     it manually, at which point we need to disable any
+     dynamic behavior. */
+  int              no_dyn_threshold;
 
   /* Cache malloc_getpagesize */
   unsigned int     pagesize;
@@ -3428,6 +3496,14 @@ public_fREe(Void_t* mem)
 #if HAVE_MMAP
   if (chunk_is_mmapped(p))                       /* release mmapped memory. */
   {
+    /* see if the dynamic brk/mmap threshold needs adjusting */
+    if (!mp_.no_dyn_threshold
+	&& p->size > mp_.mmap_threshold
+        && p->size <= DEFAULT_MMAP_THRESHOLD_MAX)
+      {
+	mp_.mmap_threshold = chunksize (p);
+	mp_.trim_threshold = 2 * mp_.mmap_threshold;
+      }
     munmap_chunk(p);
     return;
   }
@@ -5418,10 +5494,12 @@ int mALLOPt(param_number, value) int param_number; int value;
 
   case M_TRIM_THRESHOLD:
     mp_.trim_threshold = value;
+    mp_.no_dyn_threshold = 1;
     break;
 
   case M_TOP_PAD:
     mp_.top_pad = value;
+    mp_.no_dyn_threshold = 1;
     break;
 
   case M_MMAP_THRESHOLD:
@@ -5432,6 +5510,7 @@ int mALLOPt(param_number, value) int param_number; int value;
     else
 #endif
       mp_.mmap_threshold = value;
+      mp_.no_dyn_threshold = 1;
     break;
 
   case M_MMAP_MAX:
@@ -5441,6 +5520,7 @@ int mALLOPt(param_number, value) int param_number; int value;
     else
 #endif
       mp_.n_mmaps_max = value;
+      mp_.no_dyn_threshold = 1;
     break;
 
   case M_CHECK_ACTION:
diff --git a/malloc/memusagestat.c b/malloc/memusagestat.c
index 91e00af6d4..5d35ee0236 100644
--- a/malloc/memusagestat.c
+++ b/malloc/memusagestat.c
@@ -1,5 +1,5 @@
 /* Generate graphic from memory profiling data.
-   Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -277,16 +277,16 @@ main (int argc, char *argv[])
 
   gdImageString (im_out, gdFontSmall, 38, ysize - 14, (unsigned char *) "0",
 		 blue);
-  snprintf(buf, sizeof (buf), heap_format, 0);
+  snprintf (buf, sizeof (buf), heap_format, 0);
   gdImageString (im_out, gdFontSmall, maxsize_heap < 1024 ? 32 : 26,
-		 ysize - 26, buf, red);
-  snprintf(buf, sizeof (buf), stack_format, 0);
+		 ysize - 26, (unsigned char *) buf, red);
+  snprintf (buf, sizeof (buf), stack_format, 0);
   gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26,
-		 buf, green);
+		 (unsigned char *) buf, green);
 
   if (string != NULL)
     gdImageString (im_out, gdFontLarge, (xsize - strlen (string) * 8) / 2,
-		   2, (char *) string, green);
+		   2, (unsigned char *) string, green);
 
   gdImageStringUp (im_out, gdFontSmall, 1, ysize / 2 - 10,
 		   (unsigned char *) "allocated", red);
@@ -299,9 +299,11 @@ main (int argc, char *argv[])
 		   (unsigned char *) "stack", green);
 
   snprintf (buf, sizeof (buf), heap_format, maxsize_heap / heap_scale);
-  gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14, buf, red);
+  gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14,
+		 (unsigned char *) buf, red);
   snprintf (buf, sizeof (buf), stack_format, maxsize_stack / stack_scale);
-  gdImageString (im_out, gdFontSmall, xsize - 37, 14, buf, green);
+  gdImageString (im_out, gdFontSmall, xsize - 37, 14,
+		 (unsigned char *) buf, green);
 
   for (line = 1; line <= 3; ++line)
     {
@@ -312,7 +314,7 @@ main (int argc, char *argv[])
       snprintf (buf, sizeof (buf), heap_format, maxsize_heap / 4 * line /
 		heap_scale);
       gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6,
-		     ysize - 26 - cnt, buf, red);
+		     ysize - 26 - cnt, (unsigned char *) buf, red);
 
       cnt2 = ((ysize - 40) * (maxsize_stack / 4 * line / stack_scale)) /
 	(maxsize_stack / stack_scale);
@@ -322,11 +324,12 @@ main (int argc, char *argv[])
       snprintf (buf, sizeof (buf), stack_format, maxsize_stack / 4 * line /
 		stack_scale);
       gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26 - cnt2,
-		     buf, green);
+		     (unsigned char *) buf, green);
     }
 
   snprintf (buf, sizeof (buf), "%llu", (unsigned long long) total);
-  gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14, buf, blue);
+  gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14,
+		 (unsigned char *) buf, blue);
 
   if (!time_based)
     {
diff --git a/nis/nis_xdr.c b/nis/nis_xdr.c
index bcb396a509..0c6452a6a7 100644
--- a/nis/nis_xdr.c
+++ b/nis/nis_xdr.c
@@ -35,10 +35,16 @@ xdr_nis_attr (XDR *xdrs, nis_attr *objp)
   return res;
 }
 
+static __always_inline bool_t
+xdr_nis_name (XDR *xdrs, nis_name *objp)
+{
+  return xdr_string (xdrs, objp, ~0);
+}
+
 bool_t
 _xdr_nis_name (XDR *xdrs, nis_name *objp)
 {
-  return xdr_string (xdrs, objp, ~0);
+  return xdr_nis_name (xdrs, objp);
 }
 
 static __always_inline bool_t
@@ -78,7 +84,7 @@ xdr_endpoint (XDR *xdrs, endpoint *objp)
 bool_t
 _xdr_nis_server (XDR *xdrs, nis_server *objp)
 {
-  bool_t res = _xdr_nis_name (xdrs, &objp->name);
+  bool_t res = xdr_nis_name (xdrs, &objp->name);
   if (__builtin_expect (res, TRUE))
     {
       res = xdr_array (xdrs, (char **) &objp->ep.ep_val, &objp->ep.ep_len,
@@ -96,7 +102,7 @@ _xdr_nis_server (XDR *xdrs, nis_server *objp)
 bool_t
 _xdr_directory_obj (XDR *xdrs, directory_obj *objp)
 {
-  bool_t res = _xdr_nis_name (xdrs, &objp->do_name);
+  bool_t res = xdr_nis_name (xdrs, &objp->do_name);
   if (__builtin_expect (res, TRUE))
     {
       res = xdr_nstype (xdrs, &objp->do_type);
@@ -161,7 +167,7 @@ xdr_link_obj (XDR *xdrs, link_obj *objp)
 		       &objp->li_attrs.li_attrs_len, ~0,
 		       sizeof (nis_attr), (xdrproc_t) xdr_nis_attr);
       if (__builtin_expect (res, TRUE))
-	res = _xdr_nis_name (xdrs, &objp->li_name);
+	res = xdr_nis_name (xdrs, &objp->li_name);
     }
   return res;
 }
@@ -245,16 +251,16 @@ _xdr_nis_object (XDR *xdrs, nis_object *objp)
   bool_t res = xdr_nis_oid (xdrs, &objp->zo_oid);
   if (__builtin_expect (res, TRUE))
     {
-      res = _xdr_nis_name (xdrs, &objp->zo_name);
+      res = xdr_nis_name (xdrs, &objp->zo_name);
       if (__builtin_expect (res, TRUE))
 	{
-	  res = _xdr_nis_name (xdrs, &objp->zo_owner);
+	  res = xdr_nis_name (xdrs, &objp->zo_owner);
 	  if (__builtin_expect (res, TRUE))
 	    {
-	      res = _xdr_nis_name (xdrs, &objp->zo_group);
+	      res = xdr_nis_name (xdrs, &objp->zo_group);
 	      if (__builtin_expect (res, TRUE))
 		{
-		  res = _xdr_nis_name (xdrs, &objp->zo_domain);
+		  res = xdr_nis_name (xdrs, &objp->zo_domain);
 		  if (__builtin_expect (res, TRUE))
 		    {
 		      res = xdr_u_int (xdrs, &objp->zo_access);
@@ -272,16 +278,22 @@ _xdr_nis_object (XDR *xdrs, nis_object *objp)
   return res;
 }
 
+static __always_inline bool_t
+xdr_nis_error (XDR *xdrs, nis_error *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+
 bool_t
 _xdr_nis_error (XDR *xdrs, nis_error *objp)
 {
-  return xdr_enum (xdrs, (enum_t *) objp);
+  return xdr_nis_error (xdrs, objp);
 }
 
 bool_t
 _xdr_nis_result (XDR *xdrs, nis_result *objp)
 {
-  bool_t res = _xdr_nis_error (xdrs, &objp->status);
+  bool_t res = xdr_nis_error (xdrs, &objp->status);
   if (__builtin_expect (res, TRUE))
     {
       res = xdr_array (xdrs, (char **) &objp->objects.objects_val,
@@ -313,7 +325,7 @@ libnsl_hidden_def (_xdr_nis_result)
 bool_t
 _xdr_ns_request (XDR *xdrs, ns_request *objp)
 {
-  bool_t res = _xdr_nis_name (xdrs, &objp->ns_name);
+  bool_t res = xdr_nis_name (xdrs, &objp->ns_name);
   if (__builtin_expect (res, TRUE))
     res = xdr_array (xdrs, (char **) &objp->ns_object.ns_object_val,
 		     &objp->ns_object.ns_object_len, 1,
@@ -324,7 +336,7 @@ _xdr_ns_request (XDR *xdrs, ns_request *objp)
 bool_t
 _xdr_ib_request (XDR *xdrs, ib_request *objp)
 {
-  bool_t res = _xdr_nis_name (xdrs, &objp->ibr_name);
+  bool_t res = xdr_nis_name (xdrs, &objp->ibr_name);
   if (__builtin_expect (res, TRUE))
     {
       res = xdr_array (xdrs, (char **) &objp->ibr_srch.ibr_srch_val,
@@ -363,7 +375,7 @@ libnsl_hidden_def (_xdr_ib_request)
 bool_t
 _xdr_ping_args (XDR *xdrs, ping_args *objp)
 {
-  bool_t res = _xdr_nis_name (xdrs, &objp->dir);
+  bool_t res = xdr_nis_name (xdrs, &objp->dir);
   if (__builtin_expect (res, TRUE))
     res = xdr_uint32_t (xdrs, &objp->stamp);
   return res;
@@ -372,7 +384,7 @@ _xdr_ping_args (XDR *xdrs, ping_args *objp)
 bool_t
 _xdr_cp_result (XDR *xdrs, cp_result *objp)
 {
-  bool_t res = _xdr_nis_error (xdrs, &objp->cp_status);
+  bool_t res = xdr_nis_error (xdrs, &objp->cp_status);
   if (__builtin_expect (res, TRUE))
     {
       res = xdr_uint32_t (xdrs, &objp->cp_zticks);
@@ -402,19 +414,19 @@ _xdr_nis_taglist (XDR *xdrs, nis_taglist *objp)
 bool_t
 _xdr_fd_args (XDR *xdrs, fd_args *objp)
 {
-  bool_t res = _xdr_nis_name (xdrs, &objp->dir_name);
+  bool_t res = xdr_nis_name (xdrs, &objp->dir_name);
   if (__builtin_expect (res, TRUE))
-    res = _xdr_nis_name (xdrs, &objp->requester);
+    res = xdr_nis_name (xdrs, &objp->requester);
   return res;
 }
 
 bool_t
 _xdr_fd_result (XDR *xdrs, fd_result *objp)
 {
-  bool_t res = _xdr_nis_error (xdrs, &objp->status);
+  bool_t res = xdr_nis_error (xdrs, &objp->status);
   if (__builtin_expect (res, TRUE))
     {
-      res = _xdr_nis_name (xdrs, &objp->source);
+      res = xdr_nis_name (xdrs, &objp->source);
       if (__builtin_expect (res, TRUE))
 	{
 	  res = xdr_bytes (xdrs, (char **) &objp->dir_data.dir_data_val,
diff --git a/stdio-common/bug16.c b/stdio-common/bug16.c
index 42e37fa8b6..84269f3b6d 100644
--- a/stdio-common/bug16.c
+++ b/stdio-common/bug16.c
@@ -1,19 +1,42 @@
 #include <stdio.h>
 #include <string.h>
 
+struct
+{
+  long double val;
+  const char str[4][7];
+} tests[] =
+{
+  { 0x0.FFFFp+0L, { "0X1P+0", "0X2P-1", "0X4P-2", "0X8P-3" } },
+  { 0x0.FFFFp+1L, { "0X1P+1", "0X2P+0", "0X4P-1", "0X8P-2" } },
+  { 0x0.FFFFp+2L, { "0X1P+2", "0X2P+1", "0X4P+0", "0X8P-1" } },
+  { 0x0.FFFFp+3L, { "0X1P+3", "0X2P+2", "0X4P+1", "0X8P+0" } }
+};
+
 static int
 do_test (void)
 {
   char buf[100];
-  snprintf (buf, sizeof (buf), "%.0LA", 0x0.FFFFp+0L);
+  int ret = 0;
+
+  for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+    {  
+      snprintf (buf, sizeof (buf), "%.0LA", tests[i].val);
+
+      size_t j;
+      for (j = 0; j < 4; ++j)
+	if (strcmp (buf, tests[i].str[j]) == 0)
+	  break;
 
-  if (strcmp (buf, "0X1P+0") != 0)
-    {
-      printf ("got \"%s\", expected \"0X1P+0\"\n", buf);
-      return 1;
+      if (j == 4)
+	{
+	  printf ("%zd: got \"%s\", expected \"%s\" or equivalent\n",
+		  i, buf, tests[i].str[0]);
+	  ret = 1;
+	}
     }
 
-  return 0;
+  return ret;
 }
 
 #define TEST_FUNCTION do_test ()
diff --git a/stdlib/strtol_l.c b/stdlib/strtol_l.c
index 156083c748..e02a2747d0 100644
--- a/stdlib/strtol_l.c
+++ b/stdlib/strtol_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -168,10 +168,15 @@
 /* Define tables of maximum values and remainders in order to detect
    overflow.  Do this at compile-time in order to avoid the runtime
    overhead of the division.  */
+extern const unsigned long __strtol_ul_max_tab[] attribute_hidden;
+extern const unsigned char __strtol_ul_rem_tab[] attribute_hidden;
+#if defined(QUAD) && __WORDSIZE == 32
+extern const unsigned long long __strtol_ull_max_tab[] attribute_hidden;
+extern const unsigned char __strtol_ull_rem_tab[] attribute_hidden;
+#endif
 
 #define DEF(TYPE, NAME)							   \
-  const TYPE NAME[] attribute_hidden					   \
-	__attribute__((section(".gnu.linkonce.r." #NAME))) =		   \
+  const TYPE NAME[] attribute_hidden =					   \
   {									   \
     F(2), F(3), F(4), F(5), F(6), F(7), F(8), F(9), F(10), 		   \
     F(11), F(12), F(13), F(14), F(15), F(16), F(17), F(18), F(19), F(20),  \
@@ -179,20 +184,22 @@
     F(31), F(32), F(33), F(34), F(35), F(36)				   \
   }
 
-#define F(X)	ULONG_MAX / X
+#if !UNSIGNED && !defined (USE_WIDE_CHAR) && !defined (QUAD)
+# define F(X)	ULONG_MAX / X
   DEF (unsigned long, __strtol_ul_max_tab);
-#undef F
-#if defined(QUAD) && __WORDSIZE == 32
+# undef F
+# define F(X)	ULONG_MAX % X
+  DEF (unsigned char, __strtol_ul_rem_tab);
+# undef F
+#endif
+#if !UNSIGNED && !defined (USE_WIDE_CHAR) && defined (QUAD) \
+    && __WORDSIZE == 32
 # define F(X)	ULONG_LONG_MAX / X
   DEF (unsigned long long, __strtol_ull_max_tab);
 # undef F
 # define F(X)	ULONG_LONG_MAX % X
   DEF (unsigned char, __strtol_ull_rem_tab);
 # undef F
-#else
-# define F(X)	ULONG_MAX % X
-  DEF (unsigned char, __strtol_ul_rem_tab);
-# undef F
 #endif
 #undef DEF
 
diff --git a/sysdeps/s390/fpu/libm-test-ulps b/sysdeps/s390/fpu/libm-test-ulps
index 7fbed3caf9..989722e651 100644
--- a/sysdeps/s390/fpu/libm-test-ulps
+++ b/sysdeps/s390/fpu/libm-test-ulps
@@ -513,16 +513,16 @@ ifloat: 1
 # j0
 Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 Test "j0 (0.75) == 0.864242275166648623555731103820923211":
 float: 1
 ifloat: 1
 Test "j0 (10.0) == -0.245935764451348335197760862485328754":
-double: 2
+double: 3
 float: 1
-idouble: 2
+idouble: 3
 ifloat: 1
 ildouble: 2
 ldouble: 2
@@ -533,9 +533,9 @@ ildouble: 2
 ldouble: 2
 Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 Test "j0 (8.0) == 0.171650807137553906090869407851972001":
 float: 1
 ifloat: 1
@@ -569,16 +569,16 @@ ldouble: 4
 # jn
 Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 Test "jn (0, 0.75) == 0.864242275166648623555731103820923211":
 float: 1
 ifloat: 1
 Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
-double: 2
+double: 3
 float: 1
-idouble: 2
+idouble: 3
 ifloat: 1
 ildouble: 2
 ldouble: 2
@@ -589,9 +589,9 @@ ildouble: 2
 ldouble: 2
 Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
 float: 1
 ifloat: 1
@@ -661,9 +661,9 @@ idouble: 1
 ifloat: 1
 Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
 double: 3
-float: 1
+float: 2
 idouble: 3
-ifloat: 1
+ifloat: 2
 ildouble: 2
 ldouble: 2
 Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
@@ -925,9 +925,9 @@ ildouble: 1
 ldouble: 1
 Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
 double: 2
-float: 1
+float: 2
 idouble: 2
-ifloat: 1
+ifloat: 2
 ildouble: 2
 ldouble: 2
 Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
@@ -1228,9 +1228,9 @@ float: 1
 ifloat: 1
 
 Function: "j0":
-double: 2
+double: 3
 float: 2
-idouble: 2
+idouble: 3
 ifloat: 2
 ildouble: 2
 ldouble: 2
diff --git a/sysdeps/unix/sysv/linux/i386/fchownat.c b/sysdeps/unix/sysv/linux/i386/fchownat.c
index e5306db6ee..db5481705a 100644
--- a/sysdeps/unix/sysv/linux/i386/fchownat.c
+++ b/sysdeps/unix/sysv/linux/i386/fchownat.c
@@ -61,6 +61,24 @@ extern int __libc_missing_32bit_uids;
 int
 fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 {
+  int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+  if (__have_atfcts >= 0)
+# endif
+    {
+      result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+      if (result == -1 && errno == ENOSYS)
+	__have_atfcts = -1;
+      else
+# endif
+	return result;
+    }
+#endif
+
+#ifndef __ASSUME_ATFCTS
   if (flag & ~AT_SYMLINK_NOFOLLOW)
     {
       __set_errno (EINVAL);
@@ -87,14 +105,13 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
       file = buf;
     }
 
-  int result;
   INTERNAL_SYSCALL_DECL (err);
 
-#if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0
-# if __ASSUME_LCHOWN_SYSCALL == 0
+# if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0
+#  if __ASSUME_LCHOWN_SYSCALL == 0
   static int __libc_old_chown;
 
-#  ifdef __NR_chown32
+#   ifdef __NR_chown32
   if (__libc_missing_32bit_uids <= 0)
     {
       if (flag & AT_SYMLINK_NOFOLLOW)
@@ -111,7 +128,7 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 
       __libc_missing_32bit_uids = 1;
     }
-#  endif /* __NR_chown32 */
+#   endif /* __NR_chown32 */
 
   if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
       || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
@@ -135,13 +152,13 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 
   result = INTERNAL_SYSCALL (lchown, err, 3, CHECK_STRING (file), owner,
 			     group);
-# elif __ASSUME_32BITUIDS
+#  elif __ASSUME_32BITUIDS
   /* This implies __ASSUME_LCHOWN_SYSCALL.  */
   result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
 			     group);
-# else
+#  else
   /* !__ASSUME_32BITUIDS && ASSUME_LCHOWN_SYSCALL  */
-#  ifdef __NR_chown32
+#   ifdef __NR_chown32
   if (__libc_missing_32bit_uids <= 0)
     {
       result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
@@ -153,7 +170,7 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 
       __libc_missing_32bit_uids = 1;
     }
-#  endif /* __NR_chown32 */
+#   endif /* __NR_chown32 */
   if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
       || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
     {
@@ -162,10 +179,10 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
     }
 
   result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner, group);
-# endif
-#else
+#  endif
+# else
   result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner, group);
-#endif
+# endif
 
   if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
     goto fail;
@@ -175,4 +192,5 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
  fail:
   __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
   return -1;
+#endif
 }
diff --git a/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h b/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h
index 1ddb4e349f..ef66d465de 100644
--- a/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h
+++ b/sysdeps/unix/sysv/linux/ia64/bits/fcntl.h
@@ -43,9 +43,9 @@
 #define O_SYNC		010000
 #define O_FSYNC		O_SYNC
 #define O_ASYNC		020000
-#define O_DIRECT	040000
 
 #ifdef __USE_GNU
+# define O_DIRECT	040000
 # define O_DIRECTORY	0200000	/* must be a directory */
 # define O_NOFOLLOW	0400000 /* don't follow links */
 # define O_NOATIME	01000000 /* Do not set atime.  */
diff --git a/sysdeps/unix/sysv/linux/powerpc/fchownat.c b/sysdeps/unix/sysv/linux/powerpc/fchownat.c
index 1fbae5c448..f1b9b4db4a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/fchownat.c
+++ b/sysdeps/unix/sysv/linux/powerpc/fchownat.c
@@ -37,6 +37,24 @@
 int
 fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 {
+  int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+  if (__have_atfcts >= 0)
+# endif
+    {
+      result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+      if (result == -1 && errno == ENOSYS)
+	__have_atfcts = -1;
+      else
+# endif
+	return result;
+    }
+#endif
+
+#ifndef __ASSUME_ATFCTS
   if (flag & ~AT_SYMLINK_NOFOLLOW)
     {
       __set_errno (EINVAL);
@@ -63,15 +81,14 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
       file = buf;
     }
 
-  int result;
   INTERNAL_SYSCALL_DECL (err);
 
-#if __ASSUME_LCHOWN_SYSCALL
+# if __ASSUME_LCHOWN_SYSCALL
   if (flag & AT_SYMLINK_NOFOLLOW)
     result = INTERNAL_SYSCALL (lchown, err, 3, file, owner, group);
   else
     result = INTERNAL_SYSCALL (chown, err, 3, file, owner, group);
-#else
+# else
   char link[PATH_MAX + 2];
   char path[2 * PATH_MAX + 4];
   int loopct;
@@ -89,7 +106,7 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
       goto out;
     }
 
-# ifdef __NR_lchown
+#  ifdef __NR_lchown
   if (flag & AT_SYMLINK_NOFOLLOW)
     {
       result = INTERNAL_SYSCALL (lchown, err, 3, __ptrvalue (file), owner,
@@ -110,25 +127,25 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 	}
       libc_old_chown = -1;
     }
-# else
+#  else
   if (flag & AT_SYMLINK_NOFOLLOW)
     {
       result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
 				 group);
       goto out;
     }
-# endif
+#  endif
 
   result = __readlink (file, link, PATH_MAX + 1);
   if (result == -1)
     {
-# ifdef __NR_lchown
+#  ifdef __NR_lchown
       result = INTERNAL_SYSCALL (lchown, err, 3, __ptrvalue (file), owner,
 				 group);
-# else
+#  else
       result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
 				 group);
-# endif
+#  endif
       goto out;
     }
 
@@ -178,11 +195,11 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 
       if (result == -1)
 	{
-# ifdef __NR_lchown
+#  ifdef __NR_lchown
 	  result = INTERNAL_SYSCALL (lchown, err, 3, path, owner, group);
-# else
+#  else
 	  result = INTERNAL_SYSCALL (chown, err, 3, path, owner, group);
-# endif
+#  endif
 	  goto out;
 	}
     }
@@ -190,16 +207,17 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
   return -1;
 
  out:
-#endif
+# endif
 
   if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
     {
-#if !__ASSUME_LCHOWN_SYSCALL
+# if !__ASSUME_LCHOWN_SYSCALL
     fail:
-#endif
+# endif
       __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
       result = -1;
     }
 
   return result;
+#endif
 }
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c b/sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c
index d927d7ca0d..abc06b07d9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c
@@ -53,6 +53,24 @@ extern int __libc_missing_32bit_uids;
 int
 fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 {
+  int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+  if (__have_atfcts >= 0)
+# endif
+    {
+      result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+      if (result == -1 && errno == ENOSYS)
+	__have_atfcts = -1;
+      else
+# endif
+	return result;
+    }
+#endif
+
+#ifndef __ASSUME_ATFCTS
   if (flag & ~AT_SYMLINK_NOFOLLOW)
     {
       __set_errno (EINVAL);
@@ -79,16 +97,15 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
       file = buf;
     }
 
-  int result;
   INTERNAL_SYSCALL_DECL (err);
 
-#if __ASSUME_32BITUIDS > 0
+# if __ASSUME_32BITUIDS > 0
   result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
 			     group);
-#else
+# else
   static int __libc_old_chown;
 
-# ifdef __NR_chown32
+#  ifdef __NR_chown32
   if (__libc_missing_32bit_uids <= 0)
     {
       if (flag & AT_SYMLINK_NOFOLLOW)
@@ -105,7 +122,7 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 
       __libc_missing_32bit_uids = 1;
     }
-# endif /* __NR_chown32 */
+#  endif /* __NR_chown32 */
   if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
       || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
     {
@@ -128,7 +145,7 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 
   result = INTERNAL_SYSCALL (lchown, err, 3, CHECK_STRING (file), owner,
 			     group);
-#endif
+# endif
 
   if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
     {
@@ -138,4 +155,5 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
     }
 
   return result;
+#endif
 }
diff --git a/sysdeps/unix/sysv/linux/sh/fchownat.c b/sysdeps/unix/sysv/linux/sh/fchownat.c
index 6cc093222d..61df787c2a 100644
--- a/sysdeps/unix/sysv/linux/sh/fchownat.c
+++ b/sysdeps/unix/sysv/linux/sh/fchownat.c
@@ -40,6 +40,24 @@ extern int __libc_missing_32bit_uids;
 int
 fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 {
+  int result;
+
+#ifdef __NR_fchownat
+# ifndef __ASSUME_ATFCTS
+  if (__have_atfcts >= 0)
+# endif
+    {
+      result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+      if (result == -1 && errno == ENOSYS)
+	__have_atfcts = -1;
+      else
+# endif
+	return result;
+    }
+#endif
+
+#ifndef __ASSUME_ATFCTS
   if (flag & ~AT_SYMLINK_NOFOLLOW)
     {
       __set_errno (EINVAL);
@@ -66,18 +84,17 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
       file = buf;
     }
 
-  int result;
   INTERNAL_SYSCALL_DECL (err);
 
-#if __ASSUME_32BITUIDS > 0
+# if __ASSUME_32BITUIDS > 0
   if (flag & AT_SYMLINK_NOFOLLOW)
     result = INTERNAL_SYSCALL (lchown32, err, 3, CHECK_STRING (file), owner,
 			       group);
   else
     result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
 			       group);
-#else
-# ifdef __NR_chown32
+# else
+#  ifdef __NR_chown32
   if (__libc_missing_32bit_uids <= 0)
     {
       if (flag & AT_SYMLINK_NOFOLLOW)
@@ -94,7 +111,7 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
 
       __libc_missing_32bit_uids = 1;
     }
-# endif /* __NR_chown32 */
+#  endif /* __NR_chown32 */
 
   if (((owner + 1) > (gid_t) ((__kernel_uid_t) -1U))
       || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
@@ -109,7 +126,7 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
   else
     result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner,
 			       group);
-#endif
+# endif
 
   if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
     {
@@ -119,4 +136,5 @@ fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
     }
 
   return result;
+#endif
 }