Example #1
0
void dill_timer_add(struct dill_timer *timer, int64_t deadline) {
    dill_assert(deadline >= 0);
    timer->expiry = deadline;
    /* Move the timer into the right place in the ordered list
       of existing timers. TODO: This is an O(n) operation! */
    struct dill_list_item *it = dill_list_begin(&dill_timers);
    while(it) {
        struct dill_timer *tm = dill_cont(it, struct dill_timer, item);
        /* If multiple timers expire at the same momemt they will be fired
           in the order they were created in (> rather than >=). */
        if(tm->expiry > timer->expiry)
            break;
        it = dill_list_next(it);
    }
    dill_list_insert(&dill_timers, &timer->item, it);
}
Example #2
0
File: cr.c Project: jimjag/libdill
/* The initial part of go(). Allocates a new stack and bundle. */
int dill_prologue(sigjmp_buf **jb, void **ptr, size_t len, int bndl,
      const char *file, int line) {
    int err;
    struct dill_ctx_cr *ctx = &dill_getctx->cr;
    /* Return ECANCELED if shutting down. */
    int rc = dill_canblock();
    if(dill_slow(rc < 0)) {err = ECANCELED; goto error1;}
    /* If bundle is not supplied by the user create one. If user supplied a
       memory to use put the bundle at the beginning of the block. */
    int new_bundle = bndl < 0;
    if(new_bundle) {
        if(*ptr) {
            bndl = dill_bundle_mem(*ptr);
            *ptr = ((uint8_t*)*ptr) + sizeof(struct dill_bundle_storage);
            len -= sizeof(struct dill_bundle_storage);
        }
        else {
            bndl = dill_bundle();
        }
        if(dill_slow(bndl < 0)) {err = errno; goto error1;}
    }
    struct dill_bundle *bundle = dill_hquery(bndl, dill_bundle_type);
    if(dill_slow(!bundle)) {err = errno; goto error2;}
    /* Allocate a stack. */
    struct dill_cr *cr;
    size_t stacksz;
    if(!*ptr) {
        cr = (struct dill_cr*)dill_allocstack(&stacksz);
        if(dill_slow(!cr)) {err = errno; goto error2;}
    }
    else {
        /* The stack is supplied by the user.
           Align the top of the stack to a 16-byte boundary. */
        uintptr_t top = (uintptr_t)*ptr;
        top += len;
        top &= ~(uintptr_t)15;
        stacksz = top - (uintptr_t)*ptr;
        cr = (struct dill_cr*)top;
        if(dill_slow(stacksz < sizeof(struct dill_cr))) {
            err = ENOMEM; goto error2;}
    }
#if defined DILL_CENSUS
    /* Mark the bytes in the stack as unused. */
    uint8_t *bottom = ((char*)cr) - stacksz;
    int i;
    for(i = 0; i != stacksz; ++i)
        bottom[i] = 0xa0 + (i % 13);
#endif
    --cr;
    cr->vfs.query = dill_cr_query;
    cr->vfs.close = dill_cr_close;
    dill_list_insert(&cr->bundle, &bundle->crs);
    cr->ready.next = NULL;
    dill_slist_init(&cr->clauses);
    cr->closer = NULL;
    cr->no_blocking1 = 0;
    cr->no_blocking2 = 0;
    cr->done = 0;
    cr->mem = *ptr ? 1 : 0;
#if defined DILL_VALGRIND
    cr->sid = VALGRIND_STACK_REGISTER((char*)(cr + 1) - stacksz, cr);
#endif
#if defined DILL_CENSUS
    /* Find the appropriate census item if it exists. It's O(n) but meh. */
    cr->census = NULL;
    struct dill_slist *it;
    for(it = dill_slist_next(&ctx->census); it != &ctx->census;
          it = dill_slist_next(it)) {
        cr->census = dill_cont(it, struct dill_census_item, crs);
        if(cr->census->line == line && strcmp(cr->census->file, file) == 0)
            break;
    }
    /* Allocate it if it does not exist. */
    if(it == &ctx->census) {
        cr->census = malloc(sizeof(struct dill_census_item));
        dill_assert(cr->census);
        dill_slist_push(&ctx->census, &cr->census->crs);
        cr->census->file = file;
        cr->census->line = line;
        cr->census->max_stack = 0;
    }
    cr->stacksz = stacksz - sizeof(struct dill_cr);
#endif
    /* Return the context of the parent coroutine to the caller so that it can
       store its current state. It can't be done here because we are at the
       wrong stack frame here. */
    *jb = &ctx->r->ctx;
    /* Add parent coroutine to the list of coroutines ready for execution. */
    dill_resume(ctx->r, 0, 0);
    /* Mark the new coroutine as running. */
    *ptr = ctx->r = cr;
    /* In case of success go() returns the handle, bundle_go() returns 0. */
    return new_bundle ? bndl : 0;
error2:
    if(new_bundle) {
        rc = dill_hclose(bndl);
        dill_assert(rc == 0);
    }
error1:
    errno = err;
    return -1;
}