diff options
author | Jim Meyering <jim@meyering.net> | 2003-02-15 22:30:46 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2003-02-15 22:30:46 +0000 |
commit | e52bb403b5ac466e192d47043c62b185c7ed9ceb (patch) | |
tree | f23907b29327d612f1fd9a9d9c5d7d9e44a77d16 /lib | |
parent | fa6fd215808a2f504ac3d002a26033878e13852f (diff) | |
download | coreutils-e52bb403b5ac466e192d47043c62b185c7ed9ceb.tar.xz |
*** empty log message ***
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mmap-stack.c | 86 |
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. */ +} |