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