Skip to content
Snippets Groups Projects
Select Git revision
  • 14d1d97543e3f6b56f5e0b645efe0e8de1d87c92
  • master default protected
  • tp5
  • tp4
  • tp3
  • tp2
  • tp1
7 results

try.c

Blame
  • try.c 2.04 KiB
    #include <stdlib.h>
    #include <assert.h>
    #include "try.h"
    
    static ctx_t *current_ctx = NULL;
    static ctx_t *ring_ctx = NULL;
    
    int try(ctx_t *pctx, func_t *f, int arg)
    {
        asm("movl %%esp, %0"
            "\n\t"
            "movl %%ebp, %1"
            : "=r"(pctx->esp), "=r"(pctx->ebp));
    
        return f(arg);
    }
    
    int throw(ctx_t * pctx, int r)
    {
        assert(pctx != NULL);
    
        static int r_tmp;
        r_tmp = r;
    
        asm("movl %0 ,%%esp"
            "\n\t"
            "movl %1 ,%%ebp "
            :
            : "r"(pctx->esp), "r"(pctx->ebp));
    
        return r_tmp;
    }
    
    int init_ctx(ctx_t *pctx, int stack_size, 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;
    }
    
    void switch_to_ctx(ctx_t *pctx)
    {
        assert(pctx->status != CTX_END);
        if (current_ctx != NULL)
        {
            // Sauvegarder où on en est avec le ctx courant
            asm("movl %%esp, %0"
                "\n\t"
                "movl %%ebp, %1"
                : "=r"(current_ctx->esp), "=r"(current_ctx->ebp));
        }
    
        current_ctx = pctx;
        asm("movl %0, %%esp"
            "\n\t"
            "movl %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;
        current_ctx->f(current_ctx->args);
        current_ctx->status = CTX_END;
        yield();
    }
    
    ctx_t *create_ctx(int stack_size, funct_t f, void *args)
    {
        ctx_t *new_ctx = malloc(sizeof(ctx_t));
    
        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, stack_size, f, args);
        return new_ctx;
    }
    
    void yield()
    {
        assert(ring_ctx != NULL || current_ctx != NULL);
        if (current_ctx == NULL)
            switch_to_ctx(ring_ctx->next_ctx);
        else
            switch_to_ctx(current_ctx->next_ctx);
    }