Re: nanosleep truncated on 64 bit Linux by 292 billion years

2014-10-28 Thread Thomas Gleixner
On Mon, 27 Oct 2014, Pádraig Brady wrote:
> I noticed that nanosleep() on 64 bit, "only" supports 292 years,
> rather than the full potential 292 billion years with 64 bit time_t, due to:
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/time.h?id=refs/tags/v3.16#n87
> 
> Attached is a program from Paul Eggert that illustrates the bug.
> Running this program on a buggy host outputs something like this:
> 
>   Setting alarm for 1 second from now ...
>   Sleeping for 9223372036854775807.9 seconds...
>   After alarm sent off, remaining time is 9223357678.462306617 seconds;
>   i.e., nanosleep claimed that it slept for about 293079448610.606445 years.

I'm aware of the issue. It's on my ever growing todo list.

Thanks,

tglx

[PATCH] 64-bit obstack support

2014-10-28 Thread Alan Modra
And >2G on 32-bit.

* include/gnu-versions.h (_GNU_OBSTACK_INTERFACE_VERSION): Bump.
* include/obstack.h: Include shlib-compat.h and gnu-versions.h.
(_OBSTACK_ELIDE_CODE, _OBSTACK_NO_ERROR_HANDLER, _OBSTACK_COMPAT,
_OBSTACK_ALIAS): Define.
(_obstack_allocated_p, _obstack_newchunk, _obstack_free,
_obstack_begin, _obstack_begin_1, _obstack_memory_used): Define.
(_obstack_newchunk): Only use libc_hidden_proto on the version
we will use inside glibc.
* malloc/obstack.h: Import from gnulib.
* malloc/obstack.c: Likewise.
* malloc/obstackv1.c: New file.
* malloc/obstackv2.c: New file.
* malloc/Makefile (routines): Remove obstack.  Add obstackv1 and
obstackv2.
(CFLAGS-obstack.c): Don't define.
(CFLAGS-obstackv1.c, CFLAGS-obstackv2.c): Define.
(malloc/Versions): Add GLIBC_2.21 _obstack functions.
* config.h.in (SIZEOF_INT, SIZEOF_SIZE_T): Add.
* configure.in: AC_CHECK_SIZEOF int and size_t.
* configure: Regenerate.
---
 config.h.in|   6 ++
 configure  |  68 +
 configure.ac   |   4 +
 include/gnu-versions.h |   2 +-
 include/obstack.h  |  76 ++
 malloc/Makefile|   5 +-
 malloc/Versions|   4 +
 malloc/obstack.c   | 266 ++--
 malloc/obstack.h   | 271 +
 malloc/obstackv1.c |  59 +++
 malloc/obstackv2.c |  69 +
 11 files changed, 523 insertions(+), 307 deletions(-)
 create mode 100644 malloc/obstackv1.c
 create mode 100644 malloc/obstackv2.c

diff --git a/config.h.in b/config.h.in
index 20c0825..82cd82b 100644
--- a/config.h.in
+++ b/config.h.in
@@ -200,6 +200,12 @@
 /* Define if the linker defines __ehdr_start.  */
 #undef HAVE_EHDR_START
 
+/* The size of "int", as computed by sizeof.  */
+#undef SIZEOF_INT
+
+/* The size of "size_t", as computed by sizeof.  */
+#undef SIZEOF_SIZE_T
+
 /*
  */
 
diff --git a/configure.ac b/configure.ac
index 82d0896..07b4b0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1799,6 +1799,10 @@ AC_CHECK_SIZEOF(long double, 0)
 sizeof_long_double=$ac_cv_sizeof_long_double
 AC_SUBST(sizeof_long_double)
 
+dnl Determine the size of int and size_t for obstack.h.
+AC_CHECK_SIZEOF([int])
+AC_CHECK_SIZEOF([size_t],,[#include ])
+
 CPPUNDEFS=
 dnl Check for silly hacked compilers predefining _FORTIFY_SOURCE.
 dnl Since we are building the implementations of the fortified functions here,
diff --git a/include/gnu-versions.h b/include/gnu-versions.h
index 6ffbd47..99caf5b 100644
--- a/include/gnu-versions.h
+++ b/include/gnu-versions.h
@@ -43,7 +43,7 @@
remember, if any of these versions change, the libc.so major version
number must change too (so avoid it)!  */
 
-#define _GNU_OBSTACK_INTERFACE_VERSION 1 /* vs malloc/obstack.c */
+#define _GNU_OBSTACK_INTERFACE_VERSION 2 /* vs malloc/obstack.c */
 #define _GNU_REGEX_INTERFACE_VERSION   1 /* vs posix/regex.c */
 #define _GNU_GLOB_INTERFACE_VERSION1 /* vs posix/glob.c */
 #define _GNU_GETOPT_INTERFACE_VERSION  2 /* vs posix/getopt.c and
diff --git a/include/obstack.h b/include/obstack.h
index 349d59b..b346fba 100644
--- a/include/obstack.h
+++ b/include/obstack.h
@@ -1,3 +1,79 @@
+/* Control compile of obstackv1.c and obstackv2.c
+   Copyright (C) 2014 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, see
+   .  */
+
+#ifdef _OBSTACK_C
+/* We are compiling obstackv1.c or obstackv2.c.  */
+# include 
+# include 
+
+# if _GNU_OBSTACK_INTERFACE_VERSION == 1
+/* Only build version 1 support.  */
+#   if _OBSTACK_INTERFACE_VERSION != 1
+#define _OBSTACK_ELIDE_CODE
+#   endif
+# elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21)
+#  define _OBSTACK_COMPAT
+#  if (defined SIZEOF_INT && defined SIZEOF_SIZE_T \
+   && SIZEOF_INT == SIZEOF_SIZE_T)
+/* The version 1 code is ABI compatible with version 2, obstackv1.c is
+   redundant.  When compiling obstackv2.c, emit symbols versioned as
+   for version 1 obstacks.  */
+#   if _OBSTACK_INTERFACE_VERSION == 1
+#define _OBSTACK_ELIDE_CODE
+#   else
+#define _OBSTACK_ALIAS
+#   endif
+#  else /* SIZEOF_INT != SIZEOF_SIZE_T */
+/

[PATCH 0/5] obstacks again

2014-10-28 Thread Alan Modra
This is a revised series, adding the SHLIB_COMPAT support Roland
McGrath requested for glibc, and omitting patch 5/5 in the previous
series that Paul Eggert disliked, with reason.

I've also moved as much of the glibc specific code out of gnulib as I
could, and abandoned the idea of renaming version 2 obstack functions.
Renaming was for a theoretical case where a shared library was built
both providing and using version 1 obstacks, then was linked against
an executable using version 2 obstacks, the shared lib obstack use
then being broken by its functions being overridden by the executable.
You'd need to be using a libc other than glibc, or deliberately try to
get into trouble with glibc..

I believe that gnulib is the owning project for obstack.[ch].  At
least, that's what I was told by one of the glibc maintainers.  I hope
that wasn't due to glibc people being uninterested in these patches
since the gnulib people also seem uninterested in reviewing the meat
of the patch series.  I'm unsure who to poke.  Note that these patches
were developed in response to a legitimate use of obstacks in gdb
hitting the current 2G limit with a real-world shared library.  See
gdb pr17133.  Anyway, the patches are against current gnulib sources.
(glibc and gnulib differ in whitespace only.)  BTW, I see gnulib has a
policy of not using tabs for indentation, but the obstack files don't
follow this for macro continuation lines, using tabs before the
backslash.  I've kept to this practice but will happily fix whitespace
if asked.

The first patch renames some union fields and moves code around, and
only that.  Split out to make later patches easy to review.

The second patch is mostly just a tidy, with one perhaps controversial
change, renaming the function obstack_free to _obstack_free for
consistency with other obstack functions.  This will be visible to
users who compile some code using a new obstack.h and try to link
against an old (but not ancient!) relocatable obstack.o.  Not a good
practice, of course.  They will need to recompile their obstack.o.
Users linking against glibc won't see a problem since glibc exports
both _obstack_free and obstack_free.

The third and fourth patch get us to the point where 4G obstacks are
supported without significantly changing the ABI.  At this point some
code will need fixes, due to people wrongly using obstack internals.
See https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00233.html for the
gcc changes, binutils-gdb commit e57e6ddc and 241fd515 for binutils
and gdb changes.  I expect there may be signed/unsigned comparison
warnings too, in other code using obstacks.

The fifth patch switches obstacks to use size_t for sizes and removes
some glibc specific code.  I've also added one more macro test to
allow the obstack error code to be omitted.

The sixth patch is for glibc only.  This provides wrappers for
obstack.c to hold the glibc specific code removed by the fifth patch,
plus machinery to allow obstack.c to be compiled twice.  I've included
obstack.c and obstack.h diff -w there for anyone interested in the
cumulative changes.  Note that this patch requires updating all the
libc abilist files.  I haven't done that.

Prior to this patch series, I see the following obstack symbols
(readelf --dyn-syms --wide libc.so | grep obstack | grep -v printf
then cut symbol number and section columns)
On x86_64
0039eab8 8 OBJECT  GLOBAL DEFAULT _obstack@GLIBC_2.2.5
0007f8b048 FUNCGLOBAL DEFAULT _obstack_allocated_p@@GLIBC_2.2.5
0007f680   181 FUNCGLOBAL DEFAULT _obstack_begin_1@@GLIBC_2.2.5
0007f740   364 FUNCGLOBAL DEFAULT _obstack_newchunk@@GLIBC_2.2.5
0007f96033 FUNCGLOBAL DEFAULT _obstack_memory_used@@GLIBC_2.2.5
0007f8e0   117 FUNCGLOBAL DEFAULT obstack_free@@GLIBC_2.2.5
0039d490 8 OBJECT  GLOBAL DEFAULT 
obstack_alloc_failed_handler@@GLIBC_2.2.5
0039c218 4 OBJECT  GLOBAL DEFAULT obstack_exit_failure@@GLIBC_2.2.5
0007f5d0   173 FUNCGLOBAL DEFAULT _obstack_begin@@GLIBC_2.2.5
0007f8e0   117 FUNCGLOBAL DEFAULT _obstack_free@@GLIBC_2.2.5

On i686
001b0bb0 4 OBJECT  GLOBAL DEFAULT _obstack@GLIBC_2.0
00076c4048 FUNCGLOBAL DEFAULT _obstack_allocated_p@@GLIBC_2.0
00076a10   178 FUNCGLOBAL DEFAULT _obstack_begin_1@@GLIBC_2.0
00076ad0   365 FUNCGLOBAL DEFAULT _obstack_newchunk@@GLIBC_2.0
00076ce033 FUNCGLOBAL DEFAULT _obstack_memory_used@@GLIBC_2.0
00076c70   112 FUNCGLOBAL DEFAULT obstack_free@@GLIBC_2.0
001afc94 4 OBJECT  GLOBAL DEFAULT obstack_alloc_failed_handler@@GLIBC_2.0
001af174 4 OBJECT  GLOBAL DEFAULT obstack_exit_failure@@GLIBC_2.0
00076960   170 FUNCGLOBAL DEFAULT _obstack_begin@@GLIBC_2.0
00076c70   112 FUNCGLOBAL DEFAULT _obstack_free@@GLIBC_2.0

After the patch
On x86_64
0039eab8 8 OBJECT  GLOBAL DEFAULT _obstack@GLIBC_2.2.5
0007f8b048 FUNCGLOBAL DEFAULT _obstack_allocated_p@GLIBC_2.2.5
0

[PATCH 5/5] 64-bit obstack support, part 3

2014-10-28 Thread Alan Modra
This finally enables full 64-bit obstack support.  The glibc shared library
specific code is removed from obstack.c too, and the error handling code
conditionally compiled under control of another macro,
_OBSTACK_NO_ERROR_HANDLER.

* lib/obstack.h: Include string.h earlier.
(_OBSTACK_INTERFACE_VERSION): Define.
(_OBSTACK_SIZE_T, _CHUNK_SIZE_T): Define as size_t for version 2.
* lib/obstack.c: Don't include shlib-compat.h.
(OBSTACK_INTERFACE_VERSION): Delete.
(_OBSTACK_ELIDE_CODE): Rename from ELIDE_CODE.  Define when version 1
glibc code is compatible with version 2.  Don't include stdio.h for
__GNU_LIBRARY.
(obstack_exit_failure, print_and_abort, obstack_alloc_failed_handler):
Omit when _OBSTACK_NO_ERROR_HANDLER defined.  Include stdio.h here.
(_obstack_compat, _obstack, _obstack_newchunk, obstack_free): Delete
glibc shared library specific source.
---
 lib/obstack.c | 83 ---
 lib/obstack.h | 21 +++
 2 files changed, 49 insertions(+), 55 deletions(-)

diff --git a/lib/obstack.c b/lib/obstack.c
index eafb376..183bd0d 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -19,16 +19,14 @@
 
 #ifdef _LIBC
 # include 
-# include 
 #else
 # include 
 # include "obstack.h"
 #endif
 
-/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
-   incremented whenever callers compiled using an old obstack.h can no
-   longer properly call the functions in this obstack.c.  */
-#define OBSTACK_INTERFACE_VERSION 1
+/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
+   obstack.h must be incremented whenever callers compiled using an old
+   obstack.h can no longer properly call the functions in this file.  */
 
 /* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself, and the installed library
@@ -38,18 +36,18 @@
(especially if it is a shared library).  Rather than having every GNU
program understand 'configure --with-gnu-libc' and omit the object
files, it is simpler to just do this in the source for each such file.  */
-
-#include   /* Random thing to get __GNU_LIBRARY__.  */
 #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
 # include 
-# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
-#  define ELIDE_CODE
+# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION   \
+  || (_GNU_OBSTACK_INTERFACE_VERSION == 1\
+  && _OBSTACK_INTERFACE_VERSION == 2 \
+  && defined SIZEOF_INT && defined SIZEOF_SIZE_T \
+  && SIZEOF_INT == SIZEOF_SIZE_T))
+#  define _OBSTACK_ELIDE_CODE
 # endif
 #endif
 
-#ifndef ELIDE_CODE
-
-
+#ifndef _OBSTACK_ELIDE_CODE
 # include 
 # include 
 
@@ -75,16 +73,6 @@ enum
 };
 
 
-# ifdef _LIBC
-#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
-/* A looong time ago (before 1994, anyway; we're not sure) this global variable
-   was used by non-GNU-C macros to avoid multiple evaluation.  The GNU C
-   library still exports it because somebody might use it.  */
-struct obstack *_obstack_compat = 0;
-compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
-#  endif
-# endif
-
 /* Define a macro that either calls functions with the traditional malloc/free
calling interface, or calls functions with the mmalloc/mfree interface
(that adds an extra first argument), based on the state of use_extra_arg.
@@ -238,9 +226,6 @@ _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T 
length)
   /* The new chunk certainly contains no empty object yet.  */
   h->maybe_empty_object = 0;
 }
-# ifdef _LIBC
-libc_hidden_def (_obstack_newchunk)
-# endif
 
 /* Return nonzero if object OBJ has been allocated from obstack H.
This is here for debugging.
@@ -300,11 +285,6 @@ _obstack_free (struct obstack *h, void *obj)
 /* obj is not in any of the chunks! */
 abort ();
 }
-# ifdef _LIBC
-/* Older versions of libc defined both _obstack_free and obstack_free.  */
-#  undef obstack_free
-strong_alias (_obstack_free, obstack_free)
-# endif
 
 _OBSTACK_SIZE_T
 _obstack_memory_used (struct obstack *h)
@@ -319,28 +299,30 @@ _obstack_memory_used (struct obstack *h)
   return nbytes;
 }
 
+# ifndef _OBSTACK_NO_ERROR_HANDLER
 /* Define the error handler.  */
+#  include 
 
 /* Exit value used when 'print_and_abort' is used.  */
-# ifdef _LIBC
+#  ifdef _LIBC
 int obstack_exit_failure = EXIT_FAILURE;
-# else
-#  include "exitfail.h"
-#  define obstack_exit_failure exit_failure
-# endif
+#  else
+#   include "exitfail.h"
+#   define obstack_exit_failure exit_failure
+#  endif
 
-# ifdef _LIBC
-#  include 
-# else
-#  include "gettext.h"
-# endif
-# ifndef _
-#  define _(msgid) gettext (msgid)
-# endif
+#  ifdef _LIBC
+#   include 
+#  else
+#   include "gettext.h"
+#  endif
+#  ifndef _
+#   d

[PATCH 2/5] obstack tidy part 2

2014-10-28 Thread Alan Modra
a) Don't be concerned about "not polluting the namespace with stddef.h
   symbols" in obstack.h, since gnulib string.h includes stddef.h
   anyway, and it seems unlikely that anyone would care.
b) Don't roll our own slow memcpy in _obstack_newchunk.
c) Rename obstack_free to _obstack_free.  This makes the naming
   consistent with other obstack functions and obviates the need for
   __obstack_free.  Ancient obstack.c defined both obstack_free and
   _obstack_free.  We continue to do that for _LIBC via an alias.
d) Miscellaneous macro fixes.  The expression used to test for gcc-2.8
   is clever, but nowadays gcc warns on undefined macros.  You'll get
   an undefined macro warning if simulating an old gcc with -U__GNUC__
   -U__GNUC_MINOR__ -D__GNUC__=1.

* lib/obstack.h: Include stddef.h unconditionally.  Formatting fixes.
(PTR_INT_TYPE): Delete, replace with ptrdiff_t.
(__obstack_free): Delete, update refs.
(_obstack_free): Rename from obstack_free.
(__extension__): Avoid undefined macro warning for __GNUC_MINOR__.
(obstack_object_size, obstack_room): Parenthesise !__GNUC__ versions.
* lib/obstack.c: Don't include stddef.h.
(COPYING_UNIT): Delete.
(_obstack_begin): Formatting fix.
(_obstack_newchunk): Use memcpy to move existing object to new chunk.
(_obstack_free): Rename from __obstack_free, update alias.  Move
undef of obstack_free to where it is needed.
---
 lib/obstack.c | 47 +++
 lib/obstack.h | 53 +++--
 2 files changed, 26 insertions(+), 74 deletions(-)

diff --git a/lib/obstack.c b/lib/obstack.c
index 66573df..2d5dfbc 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -47,8 +47,6 @@
 # endif
 #endif
 
-#include 
-
 #ifndef ELIDE_CODE
 
 
@@ -76,14 +74,6 @@ enum
   DEFAULT_ROUNDING = sizeof (union fooround)
 };
 
-/* When we copy a long block of data, this is the unit to do it with.
-   On some machines, copying successive ints does not work;
-   in such a case, redefine COPYING_UNIT to 'long' (if that works)
-   or 'char' as a last resort.  */
-# ifndef COPYING_UNIT
-#  define COPYING_UNIT int
-# endif
-
 
 # ifdef _LIBC
 #  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
@@ -161,8 +151,7 @@ _obstack_begin (struct obstack *h,
 (*obstack_alloc_failed_handler) ();
   h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
alignment - 1);
-  h->chunk_limit = chunk->limit
- = (char *) chunk + h->chunk_size;
+  h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size;
   chunk->prev = 0;
   /* The initial chunk now contains no empty object.  */
   h->maybe_empty_object = 0;
@@ -231,8 +220,6 @@ _obstack_newchunk (struct obstack *h, int length)
   struct _obstack_chunk *new_chunk;
   long new_size;
   long obj_size = h->next_free - h->object_base;
-  long i;
-  long already;
   char *object_base;
 
   /* Compute size for new chunk.  */
@@ -252,25 +239,8 @@ _obstack_newchunk (struct obstack *h, int length)
   object_base =
 __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
 
-  /* Move the existing object to the new chunk.
- Word at a time is fast and is safe if the object
- is sufficiently aligned.  */
-  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
-{
-  for (i = obj_size / sizeof (COPYING_UNIT) - 1;
-   i >= 0; i--)
-((COPYING_UNIT *) object_base)[i]
-  = ((COPYING_UNIT *) h->object_base)[i];
-  /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
- but that can cross a page boundary on a machine
- which does not do strict alignment for COPYING_UNITS.  */
-  already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
-}
-  else
-already = 0;
-  /* Copy remaining bytes one by one.  */
-  for (i = already; i < obj_size; i++)
-object_base[i] = h->object_base[i];
+  /* Move the existing object to the new chunk.  */
+  memcpy (object_base, h->object_base, obj_size);
 
   /* If the object just copied was the only data in OLD_CHUNK,
  free that chunk and remove it from the chain.
@@ -322,10 +292,8 @@ _obstack_allocated_p (struct obstack *h, void *obj)
 /* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ.  If OBJ is zero, free everything in H.  */
 
-# undef obstack_free
-
 void
-__obstack_free (struct obstack *h, void *obj)
+_obstack_free (struct obstack *h, void *obj)
 {
   struct _obstack_chunk *lp;/* below addr of any objects in this chunk */
   struct _obstack_chunk *plp;   /* point to previous chunk if any */
@@ -353,11 +321,10 @@ __obstack_free (struct obstack *h, void *obj)
 /* obj is not in any of the chunks! */
 abort ();
 }
-
 # ifdef _LIBC
-/* Older versions of libc used a function _obstack_free intended to be
-   called by no

[PATCH 3/5] 64-bit obstack support, part 1

2014-10-28 Thread Alan Modra
a) Correct calls to alloc function, to use a size_t arg.  "long" is
   just wrong on targets like x86_64-mingw64 where "long" is 32 bits
   and "size_t" 64 bits.
b) Consolidate _obstack_begin and _obstack_begin1 code.

* lib/obstack.h (struct obstack ): Correct prototype to
use "size_t" rather than "long".
(_obstack_begin, _obstack_begin1): Likewise.
(obstack_init, obstack_begin, obstack_specify_allocation_with_arg,
obstack_chunkfun): Update alloc function casts.
* lib/obstack.c (CALL_CHUNKFUN): Update chunkfun cast.
(chunkfun_type, freefun_type): New typdefs.
(_obstack_begin_worker): Split out from ..
(_obstack_begin, _obstack_begin_1): ..here.
---
 lib/obstack.c | 77 ++-
 lib/obstack.h | 16 ++---
 2 files changed, 36 insertions(+), 57 deletions(-)

diff --git a/lib/obstack.c b/lib/obstack.c
index 2d5dfbc..d9beb9b 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -94,7 +94,7 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
 # define CALL_CHUNKFUN(h, size) \
   (((h)->use_extra_arg)
  \
? (*(h)->chunkfun)((h)->extra_arg, (size))\
-   : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
+   : (*(struct _obstack_chunk *(*)(size_t))(h)->chunkfun)((size)))
 
 # define CALL_FREEFUN(h, old_chunk) \
   do { \
@@ -113,11 +113,13 @@ compat_symbol (libc, _obstack_compat, _obstack, 
GLIBC_2_0);
Return nonzero if successful, calls obstack_alloc_failed_handler if
allocation fails.  */
 
-int
-_obstack_begin (struct obstack *h,
-int size, int alignment,
-void *(*chunkfun) (long),
-void (*freefun) (void *))
+typedef struct _obstack_chunk * (*chunkfun_type) (void *, size_t);
+typedef void (*freefun_type) (void *, struct _obstack_chunk *);
+
+static int
+_obstack_begin_worker (struct obstack *h,
+   int size, int alignment,
+   chunkfun_type chunkfun, freefun_type freefun)
 {
   struct _obstack_chunk *chunk; /* points to new chunk */
 
@@ -140,11 +142,10 @@ _obstack_begin (struct obstack *h,
   size = 4096 - extra;
 }
 
-  h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
-  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunkfun = chunkfun;
+  h->freefun = freefun;
   h->chunk_size = size;
   h->alignment_mask = alignment - 1;
-  h->use_extra_arg = 0;
 
   chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
   if (!chunk)
@@ -160,51 +161,29 @@ _obstack_begin (struct obstack *h,
 }
 
 int
-_obstack_begin_1 (struct obstack *h, int size, int alignment,
-  void *(*chunkfun) (void *, long),
+_obstack_begin (struct obstack *h,
+int size, int alignment,
+void *(*chunkfun) (size_t),
+void (*freefun) (void *))
+{
+  h->use_extra_arg = 0;
+  return _obstack_begin_worker (h, size, alignment,
+(chunkfun_type) chunkfun,
+(freefun_type) freefun);
+}
+
+int
+_obstack_begin_1 (struct obstack *h,
+  int size, int alignment,
+  void *(*chunkfun) (void *, size_t),
   void (*freefun) (void *, void *),
   void *arg)
 {
-  struct _obstack_chunk *chunk; /* points to new chunk */
-
-  if (alignment == 0)
-alignment = DEFAULT_ALIGNMENT;
-  if (size == 0)
-/* Default size is what GNU malloc can fit in a 4096-byte block.  */
-{
-  /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
- Use the values for range checking, because if range checking is off,
- the extra bytes won't be missed terribly, but if range checking is on
- and we used a larger request, a whole extra 4096 bytes would be
- allocated.
-
- These number are irrelevant to the new GNU malloc.  I suspect it is
- less sensitive to the size of the request.  */
-  int extra = 12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
-+ 4 + DEFAULT_ROUNDING - 1)
-   & ~(DEFAULT_ROUNDING - 1));
-  size = 4096 - extra;
-}
-
-  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
-  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
-  h->chunk_size = size;
-  h->alignment_mask = alignment - 1;
   h->extra_arg = arg;
   h->use_extra_arg = 1;
-
-  chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
-  if (!chunk)
-(*obstack_alloc_failed_handler) ();
-  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
-   alignment - 1);
-  h->chunk_limit = chunk->limit
- = (char *) chunk + h->chunk_size;
-  chunk->prev = 0;
-  /* The initial chunk now contains no empty object.  */
-  h->m

[PATCH 4/5] 64-bit obstack support, part 2

2014-10-28 Thread Alan Modra
This gets us 4G obstack support, without changing ABI compatibility,
apart from possibly introducing some signed/unsigned comparison
warnings in code that uses obstack.h.

a) Replace "int" size parameters, return values, and macro local vars
   with _OBSTACK_SIZE_T, an "unsigned int" for now.
b) Make obstack.chunk_size a _CHUNK_SIZE_T, an "unsigned long" for now.
c) Make all obstack macros checking available room use obstack_room.
   "next_free + desired > chunk_limit" may wrap the lhs for chunks
   allocated near the top of memory.
d) Use unsigned comparisons, and macro locals to support >2G on 32-bit.

* lib/obstack.h (_OBSTACK_SIZE_T): Define.  Use throughout
in place of "int" size parameters, return values and local vars.
(_CHUNK_SIZE_T): Define.
(struct obstack): Make chunk_size a _CHUNK_SIZE_T.  Make temp
union use an _OBSTACK_SIZE_T integer type.
For __GNUC__ versions of the following macros...
(obstack_room): Rename local var.
(obstack_make_room): Use obstack_room.
(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
obstack_int_grow, obstack_blank): Likewise.
(obstack_finish): Use unsigned comparison when comparing aligned
next_free against chunk_limit.
(obstack_free): Cast OBJ to remove possible const qualifier.
For !__GNUC__ versions of the following macros...
(obstack_make_room): Use obstack_room.
(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
obstack_int_grow, obstack_blank): Likewise.
(obstack_finish): Use unsigned comparision when comparing aligned
next_free against chunk_limit.
(obstack_free): Use temp.p and same comparisons as __GNUC__ version.
* lib/obstack.c (_obstack_begin_worker): Make "size" parameter
_OBSTACK_SIZE_T.
(_obstack_begin, _obstack_begin_1): Likewise.
(_obstack_newchunk): Likewise for length parameter.  Use size_t locals.
(_obstack_memory_used): Return and use _OBSTACK_SIZE_T local.
---
 lib/obstack.c | 16 +--
 lib/obstack.h | 89 +++
 2 files changed, 55 insertions(+), 50 deletions(-)

diff --git a/lib/obstack.c b/lib/obstack.c
index d9beb9b..eafb376 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -118,7 +118,7 @@ typedef void (*freefun_type) (void *, struct _obstack_chunk 
*);
 
 static int
 _obstack_begin_worker (struct obstack *h,
-   int size, int alignment,
+   _OBSTACK_SIZE_T size, int alignment,
chunkfun_type chunkfun, freefun_type freefun)
 {
   struct _obstack_chunk *chunk; /* points to new chunk */
@@ -162,7 +162,7 @@ _obstack_begin_worker (struct obstack *h,
 
 int
 _obstack_begin (struct obstack *h,
-int size, int alignment,
+_OBSTACK_SIZE_T size, int alignment,
 void *(*chunkfun) (size_t),
 void (*freefun) (void *))
 {
@@ -174,7 +174,7 @@ _obstack_begin (struct obstack *h,
 
 int
 _obstack_begin_1 (struct obstack *h,
-  int size, int alignment,
+  _OBSTACK_SIZE_T size, int alignment,
   void *(*chunkfun) (void *, size_t),
   void (*freefun) (void *, void *),
   void *arg)
@@ -193,12 +193,12 @@ _obstack_begin_1 (struct obstack *h,
to the beginning of the new one.  */
 
 void
-_obstack_newchunk (struct obstack *h, int length)
+_obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
 {
   struct _obstack_chunk *old_chunk = h->chunk;
   struct _obstack_chunk *new_chunk;
-  long new_size;
-  long obj_size = h->next_free - h->object_base;
+  size_t new_size;
+  size_t obj_size = h->next_free - h->object_base;
   char *object_base;
 
   /* Compute size for new chunk.  */
@@ -306,11 +306,11 @@ _obstack_free (struct obstack *h, void *obj)
 strong_alias (_obstack_free, obstack_free)
 # endif
 
-int
+_OBSTACK_SIZE_T
 _obstack_memory_used (struct obstack *h)
 {
   struct _obstack_chunk *lp;
-  int nbytes = 0;
+  _OBSTACK_SIZE_T nbytes = 0;
 
   for (lp = h->chunk; lp != 0; lp = lp->prev)
 {
diff --git a/lib/obstack.h b/lib/obstack.h
index ef647aa..b30cc3b 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -106,6 +106,9 @@
 
 #include 
 
+#define _OBSTACK_SIZE_T unsigned int
+#define _CHUNK_SIZE_T unsigned long
+
 /* If B is the base of an object addressed by P, return the result of
aligning P to the next multiple of A + 1.  B and P must be of type
char *.  A + 1 must be a power of 2.  */
@@ -142,14 +145,14 @@ struct _obstack_chunk   /* Lives at front of each 
chunk. */
 
 struct obstack  /* control current object in current chunk */
 {
-  long chunk_size;  /* preferred size to allocate chunks in */
+  _CHUNK_SIZE_T chunk_size; /* preferred size to allocate chunks in */
   struct _obstack_chunk *chunk; /* address of current struct

[PATCH 1/5] obstack tidy part 1

2014-10-28 Thread Alan Modra
a) Rename temp fields.  temp.tempint and temp.tempptr just looks ugly
   to me, and result in overlong lines after later patches.
b) Move error handling code, to avoid a forward declaration and to
   simplify later patches in this series.

* lib/obstack.h (struct obstack ): Rename fields of union
and update all uses.
* lib/obstack.c: Include stdlib.h earlier.
(obstack_exit_failure, obstack_alloc_failed_handler): Move later
in file.
(print_and_abort): Remove now redundant forward declaration.
---
 lib/obstack.c | 35 +--
 lib/obstack.h | 52 ++--
 2 files changed, 43 insertions(+), 44 deletions(-)

diff --git a/lib/obstack.c b/lib/obstack.c
index 598f6aa..66573df 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -52,6 +52,7 @@
 #ifndef ELIDE_CODE
 
 
+# include 
 # include 
 
 /* Determine default alignment.  */
@@ -84,24 +85,6 @@ enum
 # endif
 
 
-/* The functions allocating more room by calling 'obstack_chunk_alloc'
-   jump to the handler pointed to by 'obstack_alloc_failed_handler'.
-   This can be set to a user defined function which should either
-   abort gracefully or use longjump - but shouldn't return.  This
-   variable by default points to the internal function
-   'print_and_abort'.  */
-static _Noreturn void print_and_abort (void);
-void (*obstack_alloc_failed_handler) (void) = print_and_abort;
-
-/* Exit value used when 'print_and_abort' is used.  */
-# include 
-# ifdef _LIBC
-int obstack_exit_failure = EXIT_FAILURE;
-# else
-#  include "exitfail.h"
-#  define obstack_exit_failure exit_failure
-# endif
-
 # ifdef _LIBC
 #  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
 /* A looong time ago (before 1994, anyway; we're not sure) this global variable
@@ -391,6 +374,15 @@ _obstack_memory_used (struct obstack *h)
 }
 
 /* Define the error handler.  */
+
+/* Exit value used when 'print_and_abort' is used.  */
+# ifdef _LIBC
+int obstack_exit_failure = EXIT_FAILURE;
+# else
+#  include "exitfail.h"
+#  define obstack_exit_failure exit_failure
+# endif
+
 # ifdef _LIBC
 #  include 
 # else
@@ -420,4 +412,11 @@ print_and_abort (void)
   exit (obstack_exit_failure);
 }
 
+/* The functions allocating more room by calling 'obstack_chunk_alloc'
+   jump to the handler pointed to by 'obstack_alloc_failed_handler'.
+   This can be set to a user defined function which should either
+   abort gracefully or use longjump - but shouldn't return.  This
+   variable by default points to the internal function
+   'print_and_abort'.  */
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
 #endif  /* !ELIDE_CODE */
diff --git a/lib/obstack.h b/lib/obstack.h
index f92492f..cd90e4e 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -159,8 +159,8 @@ struct obstack  /* control current object in 
current chunk */
   char *chunk_limit;/* address of char after current chunk */
   union
   {
-PTR_INT_TYPE tempint;
-void *tempptr;
+PTR_INT_TYPE i;
+void *p;
   } temp;   /* Temporary for some macros.  */
   int alignment_mask;   /* Mask of alignment for each object. */
   /* These prototypes vary based on 'use_extra_arg', and we use
@@ -429,23 +429,23 @@ extern int obstack_exit_failure;
but some compilers won't accept it.  */
 
 # define obstack_make_room(h, length)\
-  ((h)->temp.tempint = (length), \
-   (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)  \
-   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
+  ((h)->temp.i = (length),   \
+   (((h)->next_free + (h)->temp.i > (h)->chunk_limit)\
+   ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0))
 
 # define obstack_grow(h, where, length)
  \
-  ((h)->temp.tempint = (length), \
-   (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)  \
-   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0),   \
-   memcpy ((h)->next_free, where, (h)->temp.tempint),\
-   (h)->next_free += (h)->temp.tempint)
+  ((h)->temp.i = (length),   \
+   (((h)->next_free + (h)->temp.i > (h)->chunk_limit)\
+   ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+   memcpy ((h)->next_free, where, (h)->temp.i),
  \
+   (h)->next_free += (h)->temp.i)
 
 # define obstack_grow0(h, where, length) \
-  ((h)->temp.tempint = (length), \
-   (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit)
  \
-   ? (_obstack_newchunk ((h), (h)->temp.temp