#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) {
current_thread = next_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;
}
почему не работает USER тред?
makecontext
не задав uc_link
. thread_func1
отрабатывает, а дальше гонка между вызовом thread_func2
из monitor_thread
и завершением программы из-за возврата из функции контекста в контексте созданном с uc_link == NULL
.clone
. Непонятно зачем дублировать указатель на функцию в Thread::func
и в Thread::context
. Непонятно зачем контексты, если schedule
их не использует. Непонятно, зачем monitor_thread
занимается активным ожиданием Thread::active
. Непонятно, зачем функции потоков лезут в потроха Thread
. Короче, этому коду не хватает идеи.