user stack support for TMP_ALLOC

Bill Allombert allomber at
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

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)

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;

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,
-------------- next part --------------
diff -ur gmp-4.1.4/
--- gmp-4.1.4/	Fri Apr 16 00:24:13 2004
+++	Tue Oct  5 23:49:21 2004
@@ -300,7 +300,7 @@
 # get them in "make dist".
-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/
diff -ur gmp-4.1.4/aclocal.m4
--- gmp-4.1.4/aclocal.m4	Tue Sep 21 15:03:57 2004
+++	Tue Oct  5 18:35:34 2004
@@ -2341,6 +2341,13 @@
     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
+    ;;
     AC_DEFINE(WANT_TMP_REENTRANT, 1, [--enable-alloca=malloc-reentrant])
Only in autom4te.cache
diff -ur gmp-4.1.4/
diff -ur gmp-4.1.4/configure
diff -ur gmp-4.1.4/
--- gmp-4.1.4/	Tue Sep 21 15:02:43 2004
+++	Tue Oct  5 18:19:54 2004
@@ -77,12 +77,12 @@
 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]) ;;
diff -ur gmp-4.1.4/cxx/
diff -ur gmp-4.1.4/demos/
diff -ur gmp-4.1.4/demos/calc/
diff -ur gmp-4.1.4/demos/expr/
diff -ur gmp-4.1.4/gmp-impl.h
--- gmp-4.1.4/gmp-impl.h	Fri Apr 23 01:59:53 2004
+++	Wed Oct  6 00:17:45 2004
@@ -203,6 +203,17 @@
 #define TMP_FREE(m)
+/* 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)
 /* See tal-reent.c for some comments. */
 struct tmp_reentrant_t {
diff -ur gmp-4.1.4/mpbsd/
diff -ur gmp-4.1.4/mpf/
diff -ur gmp-4.1.4/mpfr/
diff -ur gmp-4.1.4/mpfr/tests/
diff -ur gmp-4.1.4/mpn/
Only in gmp-4.1.4/mpn: udiv.loT
diff -ur gmp-4.1.4/mpq/
diff -ur gmp-4.1.4/mpz/
diff -ur gmp-4.1.4/printf/
diff -ur gmp-4.1.4/scanf/
Only in
Only in tal-stack.c
diff -ur gmp-4.1.4/tests/
diff -ur gmp-4.1.4/tests/cxx/
diff -ur gmp-4.1.4/tests/devel/
diff -ur gmp-4.1.4/tests/misc/
diff -ur gmp-4.1.4/tests/mpbsd/
diff -ur gmp-4.1.4/tests/mpf/
diff -ur gmp-4.1.4/tests/mpn/
diff -ur gmp-4.1.4/tests/mpq/
diff -ur gmp-4.1.4/tests/mpz/
diff -ur gmp-4.1.4/tests/rand/
diff -ur gmp-4.1.4/tune/
--- /dev/null	Wed Jul  2 16:24:28 2003
+++	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;
+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