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() {}