Esempio n. 1
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_slist_empty(&ctx->cache)) {
        --ctx->count;
        return (void*)(dill_slist_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 a 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 a stack overflow will
       cause a segfault instead of randomly overwriting 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;
}
Esempio n. 2
0
File: cr.c Progetto: jimjag/libdill
/* The final part of go(). Gets called when the coroutine is finished. */
void dill_epilogue(void) {
    struct dill_ctx_cr *ctx = &dill_getctx->cr;
    /* Mark the coroutine as finished. */
    ctx->r->done = 1;
    /* If there's a coroutine waiting for us to finish, unblock it now. */
    if(ctx->r->closer)
        dill_cancel(ctx->r->closer, 0);
    /* Deallocate the coroutine, unless, of course, it is already
       in the process of being closed. */
    if(!ctx->r->no_blocking1) {
        /* If this is the last coroutine in the bundle and there's someone
           waiting for hdone() on the bundle unblock them. */
        if(dill_list_oneitem(&ctx->r->bundle)) {
            struct dill_bundle *b = dill_cont(ctx->r->bundle.next,
                struct dill_bundle, crs);
            if(b->waiter) dill_trigger(b->waiter, 0);
        }
        dill_list_erase(&ctx->r->bundle);
        dill_cr_close(&ctx->r->vfs);
    }
    /* With no clauses added, this call will never return. */
    dill_assert(dill_slist_empty(&ctx->r->clauses));
    dill_wait();
}