I'm trying to simulate threads swapcontext() and whatnot but I have some issues:
- The callback function doesn't run
- I get a memory error from free(): free(): invalid size Aborted
- How do I wait until all the threads are done?
here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <stdarg.h>
#define STACK_SIZE 1024
typedef struct thread {
ucontext_t context;
void* stack;
int done;
} thread_t;
thread_t thread1, thread2;
void thread1_function(int argc, ...) {
va_list args;
va_start(args, argc);
for (int i = 0; i < 10; i++) {
printf("Thread 1 count: %d\n", i);
swapcontext(&thread1.context, &thread2.context);
}
thread1.done = 1;
printf("Thread 1 done\n");
va_end(args);
}
void thread2_function() {
for (int i = 0; i < 10; i++) {
printf("Thread 2 count: %d\n", i);
swapcontext(&thread2.context, &thread1.context);
}
printf("Thread 2 done\n");
thread2.done = 1;
}
int main() {
// Allocate stacks for each thread
thread1.stack = malloc(STACK_SIZE);
thread2.stack = malloc(STACK_SIZE);
// Initialize the execution context for each thread
getcontext(&thread1.context);
thread1.context.uc_stack.ss_sp = thread1.stack;
thread1.context.uc_stack.ss_size = STACK_SIZE;
makecontext(&thread1.context, (void (*)())thread1_function, 1, 2, 0);
getcontext(&thread2.context);
thread2.context.uc_stack.ss_sp = thread2.stack;
thread2.context.uc_stack.ss_size = STACK_SIZE;
makecontext(&thread2.context, (void (*)())thread2_function, 0);
// Switch to thread1
swapcontext(&thread1.context, &thread2.context);
// Free stacks
free(thread1.stack);
free(thread2.stack);
return 0;
}
When I run the code is supposed to run both my callback function instead of I get below error and without the function at all (as far i know):
Thread 2 count: 0 free(): invalid size Aborted
In my tests,
STACK_SIZEmust be set to at least 6 KB, otherwise I get the error messagefree(): invalid sizeor a segmentation fault. Therefore, I recommend settingSTACK_SIZEto at least 32 KB in order to be reasonably sure that the stack size is sufficient.In your posted code, you set up
thread1.contextto run the functionthread1_functionandthread2.contextto run the functionthread2_function.However, in the line
of the function
main, you overwritethread1.contextwith the current context and executethread2.context. This means thatthread1.contextis no longer set up to execute the functionthread1_function, but is instead set up to execute the remainder ofmain.Because you are now executing
thread2.context, the functionthread2_functionwill be executed. This function will first printand then it will execute this line:
As previously stated,
thread1.contextis no longer set up to execute the functionthread1_function, but is instead set up to execute the remainder ofmain. Therefore, after callingswapcontext, the program will execute these lines ofmain:These lines will terminate the program, causing nothing else to be printed.
In order to fix this, you should not store the context of
maininthread1.context. It should be stored in a separate object.Also, if you don't set the value of
thread1.context.uclinkandthread2.context.uclinkto a non-zero value, then the program will terminate as soon asthread1_functionorthread2_functionreturns.One possible solution is to set the member
uclinkto the context that is executing the functionmain. The functionmaincan then be programmed to terminate if both threads are done, otherwise it will set the context to the thread that is not yet done.Another issue is that the line
in the function
thread1_functionis not meaningful if thread 2 is already done, because in that case, setting the context to thread 2 will cause thread 2 to repeat its final time slice (with the stack that has already been used by the final time slice of thread 2, which may cause the program to crash).For this reason, that line should be changed to
The function
thread2_functionhas the same problem.Here is a solution which fixes all errors mentioned above:
This program has the following output: