8

I'm looking for a way to call a C function in a different stack, i.e. save the current stack pointer, set the stack pointer to a different location, call the function and restore the old stack pointer when it returns.

The purpose of this is a lightweight threading system for a programming language. Threads will operate on very small stacks, check when more stack is needed and dynamically resize it. This is so that thousands of threads can be allocated without wasting a lot of memory. When calling in to C code it is not safe to use a tiny stack, since the C code does not know about checking and resizing, so I want to use a big pthread stack which is used only for calling C (shared between lightweight threads on the same pthread).

Now I could write assembly code stubs which will work fine, but I wondered if there is a better way to do this, such as a gcc extension or a library which already implements it. If not, then I guess I'll have my head buried in ABI and assembly language manuals ;-) I only ask this out of laziness and not wanting to reinvent the wheel.

2
  • You can implement your own "threads" with individualized stacks using the clone syscall. If you use the direct system call instead of the libc wrapper, it works pretty much like fork except that you can specify which resources and namespaces are shared. Commented Dec 22, 2015 at 0:16
  • I want to use this technique to allocate my stack using huge pages! Commented Dec 23, 2023 at 11:40

2 Answers 2

3

Assuming you're using POSIX threads and on a POSIX system, you can achieve this with signals. Setup an alternate signal handling stack (sigaltstack) and designate one special real-time signal to have its handler run on the alternate signal stack. Then raise the signal to switch to the stack, and have the signal handler read the data for what function to call, and what argument to pass it, from thread-local data.

Note that this approach is fairly expensive (multiple system calls to change stacks), but should be 100% portable to POSIX systems. Since it's slow, you might want to make arch-specific call-on-alt-stack functions written in assembly, and only use my general solution as a fallback for archs where you haven't written an assembly version.

Sign up to request clarification or add additional context in comments.

3 Comments

That's an interesting idea, but too expensive since it uses system calls. Thanks for the reply anyway.
Well if you're willing to write asm for the cpus you care about, it might provide a decent fallback. You could also consider the old makecontext API (obsolescent in POSIX 2001, removed in 2008) as a first fallback since it can be done entirely in userspace.
Generally, setting up your own stack and having a couple of assembly stubs to swap contexts will work. However, you may run into "stack checks" which enforce that the stack pointer is within a specific range of memory. You need to swap the stack limits (wherever it is stored on your platform) along with the stack pointer. For example, in windows it is in the _TIB::StackLimit and _TIB::StackBase in the GS segment.
0

Although deprecated in POSIX.1-2008, you could use makecontext() and swapcontext():

#define _XOPEN_SOURCE 500
#include <stdio.h>                                                          
#include <ucontext.h>                                                       

void f();

int main()
{
    static char f_stack[4096];
    static ucontext_t uc_main;
    static ucontext_t uc_f;

    getcontext(&uc_f);
    uc_f.uc_stack.ss_sp = f_stack;
    uc_f.uc_stack.ss_size = sizeof f_stack;
    uc_f.uc_link = &uc_main;
    makecontext(&uc_f, f, 1, 2);  /* f1(2) */

    f(1);
    swapcontext(&uc_main, &uc_f);
    f(3);
}

void f(int arg1)
{
    int i;
    printf("f(%d) stack %p\n", arg1, &i);
}

outputs

f(1) stack 0x7ffc5dff9274
f(2) stack 0x564b1538a3f4
f(3) stack 0x7ffc5dff9274

See makecontext, swapcontext (SUSv2, POSIX.1-2001)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.