Beispiel #1
0
void dill_ctx_stack_term(struct dill_ctx_stack *ctx) {
    /* Deallocate leftover coroutines. */
    struct dill_qlist *it;
    while((it = dill_qlist_pop(&ctx->cache)) != &ctx->cache) {
#if (HAVE_POSIX_MEMALIGN && HAVE_MPROTECT) & !defined DILL_NOGUARD
        void *ptr = ((uint8_t*)(it + 1)) - dill_stack_size - dill_page_size();
        int rc = mprotect(ptr, dill_page_size(), PROT_READ|PROT_WRITE);
        dill_assert(rc == 0);
        free(ptr);
#else
        void *ptr = ((uint8_t*)(it + 1)) - dill_stack_size;
        free(ptr);
#endif
    }
}
Beispiel #2
0
void *dill_allocstack(size_t *stack_size) {
    struct dill_ctx_stack *ctx = &dill_getctx->stack;
    if(stack_size)
        *stack_size = dill_stack_size;
    /* If there's a cached stack, use it. */
    if(!dill_qlist_empty(&ctx->cache)) {
        --ctx->count;
        return (void*)(dill_qlist_pop(&ctx->cache) + 1);
    }
    /* Allocate a new stack. */
    uint8_t *top;
#if (HAVE_POSIX_MEMALIGN && HAVE_MPROTECT) & !defined DILL_NOGUARD
    /* Allocate the stack so that it's memory-page-aligned.
       Add one page as stack overflow guard. */
    size_t sz = dill_align(dill_stack_size, dill_page_size()) +
        dill_page_size();
    uint8_t *ptr;
    int rc = posix_memalign((void**)&ptr, dill_page_size(), sz);
    if(dill_slow(rc != 0)) {
        errno = rc;
        return NULL;
    }
    /* The bottom page is used as a stack guard. This way stack overflow will
       cause segfault rather than randomly overwrite the heap. */
    rc = mprotect(ptr, dill_page_size(), PROT_NONE);
    if(dill_slow(rc != 0)) {
        int err = errno;
        free(ptr);
        errno = err;
        return NULL;
    }
    top = ptr + dill_page_size() + dill_stack_size;
#else
    /* Simple allocation without a guard page. */
    uint8_t *ptr = malloc(dill_stack_size);
    if(dill_slow(!ptr)) {
        errno = ENOMEM;
        return NULL;
    }
    top = ptr + dill_stack_size;
#endif
    return top;
}
Beispiel #3
0
                        break;
                    dill_trigger(&tmcl->cl, ETIMEDOUT);
                    fired = 1;
                }
            }
            /* Never retry the poll when in non-blocking mode. */
            if(!block || fired)
                break;
            /* If the timeout was hit but there were no expired timers,
               do the poll again. It can happen if the timers were canceled
               in the meantime. */
        }
        ctx->last_poll = nw;
    }
    /* There's a coroutine ready to be executed so jump to it. */
    struct dill_slist *it = dill_qlist_pop(&ctx->ready);
    it->next = NULL;
    ctx->r = dill_cont(it, struct dill_cr, ready);
    /* dill_longjmp has to be at the end of a function body, otherwise stack
       unwinding information will be trimmed if a crash occurs in this
       function. */
    dill_longjmp(ctx->r->ctx);
    return 0;
}

static void dill_docancel(struct dill_cr *cr, int id, int err) {
    /* Sanity check: Make sure that the coroutine was really suspended. */
    dill_assert(!cr->ready.next);
    /* Remove the clauses from endpoints' lists of waiting coroutines. */
    struct dill_slist *it;
    for(it = dill_slist_next(&cr->clauses); it != &cr->clauses;