summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-02-15 22:30:46 +0000
committerJim Meyering <jim@meyering.net>2003-02-15 22:30:46 +0000
commite52bb403b5ac466e192d47043c62b185c7ed9ceb (patch)
treef23907b29327d612f1fd9a9d9c5d7d9e44a77d16 /lib
parentfa6fd215808a2f504ac3d002a26033878e13852f (diff)
downloadcoreutils-e52bb403b5ac466e192d47043c62b185c7ed9ceb.tar.xz
*** empty log message ***
Diffstat (limited to 'lib')
-rw-r--r--lib/mmap-stack.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/mmap-stack.c b/lib/mmap-stack.c
new file mode 100644
index 000000000..615031526
--- /dev/null
+++ b/lib/mmap-stack.c
@@ -0,0 +1,86 @@
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+#if HAVE_UCONTEXT_H
+# include <ucontext.h>
+#endif
+
+#include "mmap-stack.h"
+
+#ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS 0
+#endif
+
+/* Set up context, *CTX, so that it may be used via makecontext,
+ using a block of SIZE bytes of mmap'd memory for its stack.
+ Return nonzero upon error. */
+static int
+get_context (ucontext_t *ctx, size_t size)
+{
+ void *stack;
+ int fd = 0;
+
+ if (getcontext (ctx))
+ return 1;
+
+ /* use tmpfile if MAP_ANONYMOUS is not defined. */
+#if MAP_ANONYMOUS == 0
+ {
+ FILE *fp = tmpfile ();
+ if (!fp)
+ return 1;
+ fd = fileno (fp);
+ }
+#endif
+
+ stack = mmap (NULL, size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
+ if (stack == MAP_FAILED)
+ return 1;
+ ctx->uc_stack.ss_sp = stack;
+ ctx->uc_stack.ss_size = size;
+ ctx->uc_link = NULL;
+ return 0;
+}
+
+/* Yep, this is arbitrary. tough :-) */
+#define ARGC_MAX 6
+
+/* Set up a context without conventional stack limitations,
+ then call function FUNC with the specified number (ARGC) of arguments.
+ If get_context and setcontext succeed, this function does not return,
+ so FUNC must be sure to exit appropriately. Otherwise, this function
+ does return, and the caller should diagnose the failure. */
+void
+run_on_mmaped_stack (void (*func) (void), size_t argc, ...)
+{
+ ucontext_t ctx;
+ size_t size = 1024 * 1024 * 1024;
+ long bs_argv[ARGC_MAX];
+ unsigned i;
+ va_list ap;
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; i++)
+ bs_argv[i] = va_arg (ap, long);
+ va_end (ap);
+
+ if (get_context (&ctx, size) == 0)
+ {
+ makecontext (&ctx, func, argc,
+ bs_argv[0], bs_argv[1], bs_argv[2],
+ bs_argv[3], bs_argv[4], bs_argv[5]);
+ setcontext (&ctx);
+ }
+
+ /* get_context or setcontext failed;
+ Resort to using the conventional stack. */
+}