#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <signal.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sched.h>
#define MAX_THREADS 4
#define STACK_SIZE 8192
typedef struct {
ucontext_t context;
int active;
void (*func)(void);
} Thread;
Thread threads[MAX_THREADS];
int current_thread = 0;
void schedule() {
int next_thread = (current_thread + 1) % MAX_THREADS;
int original_thread = current_thread;
do {
if (threads[next_thread].active) {
// Save the current context to the current thread's context
getcontext(&threads[current_thread].context);
// Set the current_thread to the next thread
current_thread = next_thread;
// Swap the context to the next thread's context
swapcontext(&threads[original_thread].context, &threads[current_thread].context);
// The code below will only execute if we return to this thread
break;
}
next_thread = (next_thread + 1) % MAX_THREADS;
} while (next_thread != original_thread);
}
void thread_func1() {
printf("Thread 1 is running...\n");
threads[current_thread].active = 0;
}
void thread_func2() {
printf("Thread 2 is running...\n");
threads[current_thread].active = 0;
}
void monitor_thread(void* arg) {
while (1) {
if (!threads[current_thread].active) {
schedule();
threads[current_thread].func();
}
}
}
int create_thread(void (*func)(void)) {
int thread_id = -1;
for (int i = 0; i < MAX_THREADS; i++) {
if (!threads[i].active) {
thread_id = i;
break;
}
}
if (thread_id == -1) {
return -1;
}
getcontext(&threads[thread_id].context);
threads[thread_id].context.uc_stack.ss_sp = malloc(STACK_SIZE);
threads[thread_id].context.uc_stack.ss_size = STACK_SIZE;
makecontext(&threads[thread_id].context, (void (*)())func, 0);
threads[thread_id].func = func;
threads[thread_id].active = 1;
return thread_id;
}
int main() {
create_thread(thread_func1);
create_thread(thread_func2);
int pid = clone((int (*)(void *))monitor_thread, malloc(STACK_SIZE) + STACK_SIZE, CLONE_VM | CLONE_THREAD, NULL);
setcontext(&threads[current_thread].context);
return 0;
}
i try to debug in gdb, but i dont understand why thread_func2 is not running i want to create manager thread which run my user threads(round robin algorithm and clear resources stack for example) how to debug ucontext? can edb help me? how not set manually completed in thread routine funcs? who should clean thread manager resources?
You didn't say what the threads are supposed to be doing even when prompted, so let's say we wanted to create two threads that each write something 5 times one second apart.
First, we need a way of creating threads.
We need to handle destroyed threads.
We need a way of switching threads.
We need a way to wait for a thread to complete.
To achieve what they want to achieve, our threads are going to need to sleep.
Now our threads. There are actually three, with the code in
main
being one of them.All together:
Notes:
clone
.