Reputation: 1047
I'm writing a multithreading environment in c using setjmp() and longjmp() to switch between threads.
I'm unsure how would be best to allocate stack space to each thread. This must be done dynamically in the larger scale threading environments but I cant think of a way to track how much stack is being used by the threads in order to alter the amount allocated.
I could pre allocate a static amount of space in between the sections of the stack like this:
void call_with_cushion (void) {
char space[1000];
space[999] = 1; /* Do not optimize array out of existence */
child();
}
(code snippet from wikipedia http://en.wikipedia.org/wiki/Setjmp.h)
but this seems beyond inflexible, I was just wondering how multithreading environments generally allocate memory to each thread?
Thanks
Upvotes: 3
Views: 2759
Reputation: 126203
Generally, the maximum amount of stack space assigned to a thread is fixed when the thread is created, and if the thread exceeds this limit, the result is undefined behavior -- there's no way to increase the stack space beyond that limit. If you're lucky, overflowing the stack will result in some kind of stack overflow exception or signal (depending on OS and thread implementation), but there's no guarantee.
If you're trying to implement your own thread library, ideally what you want to do is allocate a large amount of address space for each thread's stack, and set up the VM system to allocate memory in that space on demand, and trap when the space is full. This is what most OS-level threading libraries (like pthreads or win32 threads) do, but the details of the VM management are tricky.
If you don't want to mess with the VM stuff, you can allocate a larger than you think you'll ever need block on the heap for each thread stack, and then optionally probe the stack pointer in your code to see if its close to getting full (using more space than you thought you would need) and trap/abort if so. Depending on your compiler, there may an option to get it to automatically generate stack overflow checks in every function that you can use.
The code on the wikipedia page is very much a hack -- it might work, but doesn't do any checking to ensure that there's enough stackspace, and depends on the compiler not doing something odd with the undefined behavior that will screw things up (such as optimizing away the unused stack pad space
, which it might do even with the assignment).
Upvotes: 5
Reputation: 81159
Task switching via stack manipulation is often fairly easy, but setjmp/longjmp are not adequate tools for the purpose unless you can manipulate the internal structures of the jmp_buff. The moment code exits the context where a setjmp was performed, the jmp_buff that twas created thereby becomes invalid, and any attempt to do anything with it will cause Undefined Behavior, and that will be true even if you hope nothing disturbs the area of stack where the setjmp was performed.
Study the ABI (Application Binary Interface) rules for the processor you're using, and learn enough assembly language to perform some basic register manipulations. You probably won't need more than 1-2 dozen lines of assembly code, but you'll most likely need some. That will be especially true if you're using any sort of exception-handling framework.
Upvotes: 0