user stack support for TMP_ALLOC

Bill Allombert allomber at math.u-bordeaux.fr
Thu Oct 7 17:15:50 CEST 2004


Hello GMP developers,

I am a developer of the PARI/GP project which can use GMP as a
multiprecision kernel, as mentionned on your webpage (thanks btw).

The only issue we have with this multiprecision kernel is the alloca stack
overflow problem.

Beside recompiling GMP with --disable-alloca, a slightly better solution
is to patch TMP_ALLOC to use the PARI stack instead of the system stack.
The performance hit is smaller and we are able to detect stack overflow 
and reallocate a larger stack more easily than with the system stack.
The resulting libgmp can of course only be used with libpari which is
not practical.

So I would like to propose a more generic scheme:
An alternative TMP_ALLOC implementation that allow for a custom stack
handler to be plugged at run-time (like mp_set_memory_functions but with
semantic for the functions compatible with the requirement of a stack)
and default to alloca. A custom stack being defined by a variable
holding the current stack pointer and a function allocate a chunk of
memory in the stack, as alloca does. The memory is freed by resetting
the stack pointer to the value before the call to alloc.

I have written a patch to that effect.
Basically you add to gmp-impl.h something like

#if WANT_TMP_STACK
extern void **__gmp_tmp_stack_ptr;
extern void *(*__gmp_tmp_stack_alloc) (size_t);
#define TMP_DECL(m)  void *m
#define TMP_ALLOC(x) (__gmp_tmp_stack_alloc?__gmp_tmp_stack_alloc(x):alloca(x))
#define TMP_MARK(m)  (m=*__gmp_tmp_stack_ptr)
#define TMP_FREE(m)  (*__gmp_tmp_stack_ptr=m)
#endif

and an new source file like:

void *__gmp_tmp_stack_dummy;
void **__gmp_tmp_stack_ptr=&__gmp_tmp_stack_dummy;
void *(*__gmp_tmp_stack_alloc)(size_t)=(void *(*)(size_t)) 0;

void
mp_set_stack_functions (void **sp, void *(*alloc)(size_t))
{
  __gmp_tmp_stack_ptr = sp;
  __gmp_tmp_stack_alloc = alloc;
}
(where sp is a pointer to the variable holding the stack pointer,
and alloc is the alloca replacement).

When --enable-alloca=stack is specified, TMP_ALLOC behave like alloca
until a call to mp_set_stack_functions switch to a user stack.

Without --enable-alloca=stack, mp_set_stack_functions should exist to
preserve the ABI but should do nothing.

There is an overhead compare to to --enable-alloca=alloca, but it should
be less important than --enable-alloca=noreentrant, so it can be
installed as /usr/lib/libgmp on a box without major slowdown.

I have attached my patch, however in its current form it has the flaw of
defining mp_set_stack_functions only when --enable-alloca=stack.

Thanks for considering,
Bill.
-------------- next part --------------
diff -ur gmp-4.1.4/Makefile.am gmp-4.1.4.new/Makefile.am
--- gmp-4.1.4/Makefile.am	Fri Apr 16 00:24:13 2004
+++ gmp-4.1.4.new/Makefile.am	Tue Oct  5 23:49:21 2004
@@ -300,7 +300,7 @@
 # get them in "make dist".
 #
 EXTRA_LTLIBRARIES = libdummy.la
-libdummy_la_SOURCES = tal-debug.c tal-notreent.c tal-reent.c
+libdummy_la_SOURCES = tal-debug.c tal-notreent.c tal-reent.c tal-stack.c
 
 
 info_TEXINFOS = gmp.texi
diff -ur gmp-4.1.4/Makefile.in gmp-4.1.4.new/Makefile.in
diff -ur gmp-4.1.4/aclocal.m4 gmp-4.1.4.new/aclocal.m4
--- gmp-4.1.4/aclocal.m4	Tue Sep 21 15:03:57 2004
+++ gmp-4.1.4.new/aclocal.m4	Tue Oct  5 18:35:34 2004
@@ -2341,6 +2341,13 @@
     fi
     AC_DEFINE(WANT_TMP_ALLOCA, 1, [--enable-alloca=yes])
     ;;
+  stack)
+    if test $gmp_cv_func_alloca = no; then
+      AC_MSG_ERROR([--enable-alloca=stack specified, but alloca not available])
+    fi
+    AC_DEFINE(WANT_TMP_STACK, 1, [--enable-alloca=stack])
+    TAL_OBJECT=tal-stack$U.lo
+    ;;
   malloc-reentrant)
     AC_DEFINE(WANT_TMP_REENTRANT, 1, [--enable-alloca=malloc-reentrant])
     TAL_OBJECT=tal-reent$U.lo
Only in gmp-4.1.4.new: autom4te.cache
diff -ur gmp-4.1.4/config.in gmp-4.1.4.new/config.in
diff -ur gmp-4.1.4/configure gmp-4.1.4.new/configure
diff -ur gmp-4.1.4/configure.in gmp-4.1.4.new/configure.in
--- gmp-4.1.4/configure.in	Tue Sep 21 15:02:43 2004
+++ gmp-4.1.4.new/configure.in	Tue Oct  5 18:19:54 2004
@@ -77,12 +77,12 @@
 AC_ARG_ENABLE(alloca,
 AC_HELP_STRING([--enable-alloca],[how to get temp memory [[default=reentrant]]]),
 [case $enableval in
-alloca|malloc-reentrant|malloc-notreentrant) ;;
+alloca|stack|malloc-reentrant|malloc-notreentrant) ;;
 yes|no|reentrant|notreentrant) ;;
 debug) ;;
 *)
   AC_MSG_ERROR([bad value $enableval for --enable-alloca, need one of:
-yes no reentrant notreentrant alloca malloc-reentrant malloc-notreentrant debug]) ;;
+yes no reentrant notreentrant alloca stack malloc-reentrant malloc-notreentrant debug]) ;;
 esac],
 [enable_alloca=reentrant])
 
diff -ur gmp-4.1.4/cxx/Makefile.in gmp-4.1.4.new/cxx/Makefile.in
diff -ur gmp-4.1.4/demos/Makefile.in gmp-4.1.4.new/demos/Makefile.in
diff -ur gmp-4.1.4/demos/calc/Makefile.in gmp-4.1.4.new/demos/calc/Makefile.in
diff -ur gmp-4.1.4/demos/expr/Makefile.in gmp-4.1.4.new/demos/expr/Makefile.in
diff -ur gmp-4.1.4/gmp-impl.h gmp-4.1.4.new/gmp-impl.h
--- gmp-4.1.4/gmp-impl.h	Fri Apr 23 01:59:53 2004
+++ gmp-4.1.4.new/gmp-impl.h	Wed Oct  6 00:17:45 2004
@@ -203,6 +203,17 @@
 #define TMP_FREE(m)
 #endif
 
+#if WANT_TMP_STACK
+/* See tal-stack.c for some comments. */
+extern void **__gmp_tmp_stack_ptr;
+extern void *(*__gmp_tmp_stack_alloc) (size_t);
+#define TMP_DECL(m)  void *m
+#define TMP_ALLOC(x) (__gmp_tmp_stack_alloc?__gmp_tmp_stack_alloc(x):alloca(x))
+#define TMP_MARK(m)  (m=*__gmp_tmp_stack_ptr)
+#define TMP_FREE(m)  (*__gmp_tmp_stack_ptr=m)
+#endif
+
+
 #if WANT_TMP_REENTRANT
 /* See tal-reent.c for some comments. */
 struct tmp_reentrant_t {
diff -ur gmp-4.1.4/mpbsd/Makefile.in gmp-4.1.4.new/mpbsd/Makefile.in
diff -ur gmp-4.1.4/mpf/Makefile.in gmp-4.1.4.new/mpf/Makefile.in
diff -ur gmp-4.1.4/mpfr/Makefile.in gmp-4.1.4.new/mpfr/Makefile.in
diff -ur gmp-4.1.4/mpfr/tests/Makefile.in gmp-4.1.4.new/mpfr/tests/Makefile.in
diff -ur gmp-4.1.4/mpn/Makefile.in gmp-4.1.4.new/mpn/Makefile.in
Only in gmp-4.1.4/mpn: udiv.loT
diff -ur gmp-4.1.4/mpq/Makefile.in gmp-4.1.4.new/mpq/Makefile.in
diff -ur gmp-4.1.4/mpz/Makefile.in gmp-4.1.4.new/mpz/Makefile.in
diff -ur gmp-4.1.4/printf/Makefile.in gmp-4.1.4.new/printf/Makefile.in
diff -ur gmp-4.1.4/scanf/Makefile.in gmp-4.1.4.new/scanf/Makefile.in
Only in gmp-4.1.4.new: stamp-h.in
Only in gmp-4.1.4.new: tal-stack.c
diff -ur gmp-4.1.4/tests/Makefile.in gmp-4.1.4.new/tests/Makefile.in
diff -ur gmp-4.1.4/tests/cxx/Makefile.in gmp-4.1.4.new/tests/cxx/Makefile.in
diff -ur gmp-4.1.4/tests/devel/Makefile.in gmp-4.1.4.new/tests/devel/Makefile.in
diff -ur gmp-4.1.4/tests/misc/Makefile.in gmp-4.1.4.new/tests/misc/Makefile.in
diff -ur gmp-4.1.4/tests/mpbsd/Makefile.in gmp-4.1.4.new/tests/mpbsd/Makefile.in
diff -ur gmp-4.1.4/tests/mpf/Makefile.in gmp-4.1.4.new/tests/mpf/Makefile.in
diff -ur gmp-4.1.4/tests/mpn/Makefile.in gmp-4.1.4.new/tests/mpn/Makefile.in
diff -ur gmp-4.1.4/tests/mpq/Makefile.in gmp-4.1.4.new/tests/mpq/Makefile.in
diff -ur gmp-4.1.4/tests/mpz/Makefile.in gmp-4.1.4.new/tests/mpz/Makefile.in
diff -ur gmp-4.1.4/tests/rand/Makefile.in gmp-4.1.4.new/tests/rand/Makefile.in
diff -ur gmp-4.1.4/tune/Makefile.in gmp-4.1.4.new/tune/Makefile.in
--- /dev/null	Wed Jul  2 16:24:28 2003
+++ gmp-4.1.4.new/tal-stack.c	Wed Oct  6 00:18:20 2004
@@ -0,0 +1,35 @@
+/* Stack allocation routines.  This is intended for machines without support
+   for the `alloca' function.
+
+Copyright 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP 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 MP 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 MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void *__gmp_tmp_stack_dummy;
+void **__gmp_tmp_stack_ptr=&__gmp_tmp_stack_dummy;
+void *(*__gmp_tmp_stack_alloc)(size_t)=(void *(*)(size_t)) 0;
+
+void
+mp_set_stack_functions (void **sp, void *(*alloc)(size_t))
+{
+  __gmp_tmp_stack_ptr = sp;
+  __gmp_tmp_stack_alloc = alloc;
+}


More information about the gmp-devel mailing list