开发者

Creating and using a new stack in memory

开发者 https://www.devze.com 2023-04-01 06:58 出处:网络
For some special reasons (please don\'t ask me why), for some functions, I want to use a separate stack. So for example, say I want the function malloc to use a different stack for its processing, I n

For some special reasons (please don't ask me why), for some functions, I want to use a separate stack. So for example, say I want the function malloc to use a different stack for its processing, I need to switch to my newly created stack before it is called and get back to the original stack used by the program after it finishes. So the algorithm would be something like this.

switch_to_new_stack
call malloc
swith back to the original stack

What is the easiest and most efficient way o开发者_如何学JAVAf doing this? Any idea?


It probably doesn't fit your definition of easy or efficient, but the following could be one way to do it:

#include <stdio.h>
#include <stdlib.h>

#include <ucontext.h>

/* utility functions */
static void getctx(ucontext_t* ucp)
{
    if (getcontext(ucp) == -1) {
        perror("getcontext");
        exit(EXIT_FAILURE);
    }
}

static void print_sp()
{
#if defined(__x86_64)
    unsigned long long x; asm ("mov %%rsp, %0" : "=m" (x));
    printf("sp: %p\n",(void*)x);
#elif defined(__i386)
    unsigned long x; asm ("mov %%esp, %0" : "=m" (x));
    printf("sp: %p\n",(void*)x);
#elif defined(__powerpc__) && defined(__PPC64__)
    unsigned long long x; asm ("addi %0, 1, 0" : "=r" (x));
    printf("sp: %p\n",(void*)x);
#elif defined(__powerpc__)
    unsigned long x; asm ("addi %0, 1, 0" : "=r" (x));
    printf("sp: %p\n",(void*)x);
#else
    printf("unknown architecture\n");
#endif
}


/* stack for 'my_alloc', size arbitrarily chosen */
static int malloc_stack[1024];
static ucontext_t malloc_context; /* context malloc will run in */
static ucontext_t current_context; /* context to return to */

static void my_malloc(size_t sz)
{
    printf("in my_malloc(%zu) ", sz);
    print_sp();
}

void call_my_malloc(size_t sz)
{
    /* prepare context for malloc */
    getctx(&malloc_context);
    malloc_context.uc_stack.ss_sp = malloc_stack;
    malloc_context.uc_stack.ss_size = sizeof(malloc_stack);
    malloc_context.uc_link = &current_context;
    makecontext(&malloc_context, (void(*)())my_malloc, 1, sz);

    if (swapcontext(&current_context, &malloc_context) == -1) {
        perror("swapcontext");
        exit(EXIT_FAILURE);
    }
}

int main()
{
    printf("malloc_stack = %p\n", (void*)malloc_stack);
    printf("in main ");
    print_sp();
    call_my_malloc(42);
    printf("in main ");
    print_sp();
    return 0;
}

This should work on all platforms where makecontext(3) is supported. Quoting from the manpage (where I also got the inspiration for the example code):

The interpretation of ucp->uc_stack is just as in sigaltstack(2), namely, this struct contains the start and length of a memory area to be used as the stack, regardless of the direction of growth of the stack. Thus, it is not necessary for the user program to worry about this direction.

Sample output from PPC64:

$ gcc -o stack stack.c -Wall -Wextra -W -ggdb -std=gnu99 -pedantic -Werror -m64 && ./stack
malloc_stack = 0x10010fe0
in main sp: 0xfffffe44420
in my_malloc(42) sp: 0x10011e20
in main sp: 0xfffffe44420


GCC has support of splitted stacks, which works a bit like you described.

http://gcc.gnu.org/wiki/SplitStacks

The goal of the project is different, but implementation will do what you ask.

The goal of split stacks is to permit a discontiguous stack which is grown automatically as needed. This means that you can run multiple threads, each starting with a small stack, and have the stack grow and shrink as required by the program. It is then no longer necessary to think about stack requirements when writing a multi-threaded program. The memory usage of a typical multi-threaded program can decrease significantly, as each thread does not require a worst-case stack size. It becomes possible to run millions of threads (either full NPTL threads or co-routines) in a 32-bit address space.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号