示例#1
0
文件: libdill.c 项目: jimjag/libdill
int dill_msleep(int64_t deadline) {
    /* Return ECANCELED if shutting down. */
    int rc = dill_canblock();
    if(dill_slow(rc < 0)) return -1;
    /* Actual waiting. */
    struct dill_tmclause tmcl;
    dill_timer(&tmcl, 1, deadline);
    int id = dill_wait();
    if(dill_slow(id < 0)) return -1;
    return 0;
}
示例#2
0
int dill_msleep(int64_t deadline, const char *where) {
    /* Return ECANCELED if shutting down. */
    int rc = dill_canblock();
    if(dill_slow(rc < 0)) return -1;
    /* Trivial case. No waiting, but we do want a context switch. */
    if(dill_slow(deadline == 0)) return yield();
    /* Actual waiting. */
    struct dill_tmcl tmcl;
    if(deadline > 0)
        dill_timer(&tmcl, 1, deadline);
    int id = dill_wait(where);
    if(dill_slow(id < 0)) return -1;
    dill_assert(id == 1);
    return 0;
}
示例#3
0
文件: cr.c 项目: jimjag/libdill
/* Gets called when coroutine handle is closed. */
static void dill_cr_close(struct dill_hvfs *vfs) {
    struct dill_ctx_cr *ctx = &dill_getctx->cr;
    struct dill_cr *cr = dill_cont(vfs, struct dill_cr, vfs);
    /* If the coroutine has already finished, we are done. */
    if(!cr->done) {
        /* No blocking calls from this point on. */
        cr->no_blocking1 = 1;
        /* Resume the coroutine if it was blocked. */
        if(!cr->ready.next)
            dill_cancel(cr, ECANCELED);
        /* Wait for the coroutine to stop executing. With no clauses added,
           the only mechanism to resume is through dill_cancel(). This is not
           really a blocking call, although it looks like one. Given that the
           coroutine that is being shut down is not permitted to block, we
           should get control back pretty quickly. */
        cr->closer = ctx->r;
        int rc = dill_wait();
        /* This assertion triggers when coroutine tries to close a bundle that
           it is part of. There's no sane way to handle that so let's just
           crash the process. */
        dill_assert(!(rc == -1 && errno == ECANCELED));
        dill_assert(rc == -1 && errno == 0);
    }
#if defined DILL_CENSUS
    /* Find the first overwritten byte on the stack.
       Determine stack usage based on that. */
    uint8_t *bottom = ((uint8_t*)cr) - cr->stacksz;
    int i;
    for(i = 0; i != cr->stacksz; ++i) {
        if(bottom[i] != 0xa0 + (i % 13)) {
            /* dill_cr is located on the stack so we have to take that into
               account. Also, it may be necessary to align the top of the stack
               to a 16-byte boundary, so add 16 bytes to account for that. */
            size_t used = cr->stacksz - i - sizeof(struct dill_cr) + 16;
            if(used > cr->census->max_stack)
                cr->census->max_stack = used;
            break;
        }
    }
#endif
#if defined DILL_VALGRIND
    VALGRIND_STACK_DEREGISTER(cr->sid);
#endif
    /* Now that the coroutine is finished, deallocate it. */
    if(!cr->mem) dill_freestack(cr + 1);
}
示例#4
0
文件: libdill.c 项目: jimjag/libdill
int dill_fdout(int fd, int64_t deadline) {
    /* Return ECANCELED if shutting down. */
    int rc = dill_canblock();
    if(dill_slow(rc < 0)) return -1;
    /* Start waiting for the fd. */
    struct dill_fdclause fdcl;
    rc = dill_pollset_out(&fdcl, 1, fd);
    if(dill_slow(rc < 0)) return -1;
    /* Optionally, start waiting for a timer. */
    struct dill_tmclause tmcl;
    dill_timer(&tmcl, 2, deadline);
    /* Block. */
    int id = dill_wait();
    if(dill_slow(id < 0)) return -1;
    if(dill_slow(id == 2)) {errno = ETIMEDOUT; return -1;}
    return 0;
}
示例#5
0
文件: cr.c 项目: jimjag/libdill
int dill_bundle_wait(int h, int64_t deadline) {
    int rc = dill_canblock();
    if(dill_slow(rc < 0)) return -1;
    struct dill_bundle *self = dill_hquery(h, dill_bundle_type);
    if(dill_slow(!self)) return -1;
    /* If there are no coroutines in the bundle succeed immediately. */
    if(dill_list_empty(&self->crs)) return 0;
    /* Otherwise wait for all coroutines to finish. */
    struct dill_clause cl;
    self->waiter = &cl;
    dill_waitfor(&cl, 0, NULL);
    struct dill_tmclause tmcl;
    dill_timer(&tmcl, 1, deadline);
    int id = dill_wait();
    self->waiter = NULL;
    if(dill_slow(id < 0)) return -1;
    if(dill_slow(id == 1)) {errno = ETIMEDOUT; return -1;}
    dill_assert(id == 0);
    return 0;
}
示例#6
0
int dill_fdout(int fd, int64_t deadline, const char *where) {
    /* TODO: deadline == 0? */
    /* Return ECANCELED if shutting down. */
    int rc = dill_canblock();
    if(dill_slow(rc < 0)) return -1;
    /* Start waiting for the fd. */
    struct dill_clause fdcl;
    rc = dill_out(&fdcl, 1, fd);
    if(dill_slow(rc < 0)) return -1;
    /* Optionally, start waiting for a timer. */
    struct dill_tmcl tmcl;
    if(deadline > 0)
        dill_timer(&tmcl, 2, deadline);
    /* Block. */
    int id = dill_wait(where);
    if(dill_slow(id < 0)) return -1;
    if(dill_slow(id == 2)) {errno = ETIMEDOUT; return -1;}
    dill_assert(id == 1);
    return 0;
}
示例#7
0
文件: cr.c 项目: 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();
}