diff --git a/include/context.h b/include/context.h new file mode 100644 index 0000000000000000000000000000000000000000..6c38c33a09448b7045f1e2cfcc3fb234101d1e6f --- /dev/null +++ b/include/context.h @@ -0,0 +1,47 @@ +#if !defined(CONTEXT_H) +#define CONTEXT_H + +#define STACK_SIZE 16384 +#define CTX_MAX 16 + +typedef int(func_t)(int); +typedef void(funct_t)(void *); + +typedef enum +{ + CTX_INIT, + CTX_EXEC, + CTX_END +} ctx_status_t; + +typedef struct ctx_s +{ + void *esp; + void *ebp; + char stack[STACK_SIZE]; + funct_t *f; + void *args; + ctx_status_t status; + struct ctx_s *next_ctx; + char used; +} ctx_t; + +static ctx_t ctx_heap[CTX_MAX]; + +ctx_t *malloc_ctx(); + +void free_ctx(ctx_t *ctx); + +int init_ctx(ctx_t *, funct_t, void *); + +void switch_to_ctx(ctx_t *); + +void start_ctx(); + +ctx_t *create_ctx(funct_t, void *); + +void yield(); + +void start_sched(); + +#endif // CONTEXT_H diff --git a/src/context.c b/src/context.c new file mode 100644 index 0000000000000000000000000000000000000000..d404885c7cc359cb7d0293a89e45a464966f0215 --- /dev/null +++ b/src/context.c @@ -0,0 +1,126 @@ +#include "context.h" +#include "utils.h" + +static ctx_t *current_ctx = NULL; +static ctx_t *ring_ctx = NULL; + +ctx_t *malloc_ctx() +{ + int i; + for (i = 0; i < CTX_MAX && ctx_heap[i].used; i++) + ; + + if (i == CTX_MAX || ctx_heap[i].used) + return NULL; + + ctx_heap[i].used = 1; + return &ctx_heap[i]; +} + +void free_ctx(ctx_t *ctx) +{ + int i; + for (i = 0; i < CTX_MAX && (ctx_heap + i) == ctx; i++) + ; + + if (i == CTX_MAX || !ctx_heap[i].used) + return; + + ctx_heap[i].used = 0; +} + +int init_ctx(ctx_t *pctx, funct_t f, void *args) +{ + //pctx->stack = malloc(stack_size); + pctx->esp = pctx->stack + STACK_SIZE - sizeof(void *); + pctx->ebp = pctx->stack + STACK_SIZE - sizeof(void *); + pctx->f = f; + pctx->args = args; + pctx->status = CTX_INIT; + return 0; +} + +void switch_to_ctx(ctx_t *pctx) +{ + if (pctx->status == CTX_END) + { + // Si c'est l'unique ctx + if (pctx == pctx->next_ctx) + ring_ctx = NULL; + else + current_ctx->next_ctx = pctx->next_ctx; + + free_ctx(pctx); + yield(); + return; + } + + assert(pctx->status != CTX_END); + if (current_ctx != NULL) + { + // Sauvegarder où on en est avec le ctx courant + asm("mov %%esp, %0" + "\n\t" + "mov %%ebp, %1" + : "=r"(current_ctx->esp), "=r"(current_ctx->ebp)); + } + + current_ctx = pctx; + asm("mov %0, %%esp" + "\n\t" + "mov %1, %%ebp" + : + : "r"(current_ctx->esp), "r"(current_ctx->ebp)); + + if (current_ctx->status == CTX_INIT) + start_ctx(); +} + +void start_ctx() +{ + current_ctx->status = CTX_EXEC; + irq_enable(); + current_ctx->f(current_ctx->args); + current_ctx->status = CTX_END; + puts("\nfunction termine\n"); + yield(); +} + +ctx_t *create_ctx(funct_t f, void *args) +{ + ctx_t *new_ctx = malloc_ctx(); + + if (ring_ctx == NULL) + { + new_ctx->next_ctx = new_ctx; + ring_ctx = new_ctx; + } + else + { + new_ctx->next_ctx = ring_ctx->next_ctx; + ring_ctx->next_ctx = new_ctx; + } + + init_ctx(new_ctx, f, args); + return new_ctx; +} + +void yield() +{ + irq_disable(); + if (ring_ctx == NULL) + { + puts("\nSystem stopped\n"); + for (;;) + ; + } + + if (current_ctx == NULL) + switch_to_ctx(ring_ctx->next_ctx); + else + switch_to_ctx(current_ctx->next_ctx); + + irq_enable(); +} + +void start_sched() {}