Esempio n. 1
0
static
void thread_func(co_thread_t * self) {
    args_t & args = * (args_t*) co_get_user(self);
    for (uint32_t to=999999;to;--to) {
        if (--args.val_) {
            uint32_t next = rand64() % num_threads;
            co_yield(self, args.thread_[next]);
        }
        else {
            co_yield(self, args.host_);
        }
    }
}
Esempio n. 2
0
static int
timing_yield(lua_State *L) {
#ifdef DEBUG_LOG
	lua_State *from = lua_tothread(L, -1);
#endif
	lua_rawget(L, lua_upvalueindex(2));	// check total time
	if (lua_isnil(L, -1)) {
		lua_pop(L,1);
	} else {
		double ti = lua_tonumber(L, -1);
		lua_pop(L,1);

		lua_pushthread(L);
		lua_rawget(L, lua_upvalueindex(1));
		double starttime = lua_tonumber(L, -1);
		lua_pop(L,1);

		double diff = diff_time(starttime);
		ti += diff;
#ifdef DEBUG_LOG
		fprintf(stderr, "PROFILE [%p] yield (%lf/%lf)\n", from, diff, ti);
#endif

		lua_pushthread(L);
		lua_pushnumber(L, ti);
		lua_rawset(L, lua_upvalueindex(2));
	}

	lua_CFunction co_yield = lua_tocfunction(L, lua_upvalueindex(3));

	return co_yield(L);
}
Esempio n. 3
0
static
void thread_a(co_thread_t * self) {
    assert(co_get_user(self));
    args_t & args = * (args_t*) co_get_user(self);
    co_yield(self, args.b_);
    assert(!"Should not get here");
}
Esempio n. 4
0
static int
timing_yield(lua_State *L) {
	// printf("%s(%d): %d\n", __FUNCTION__, __LINE__, lua_gettop(L));
#ifdef DEBUG_LOG
	lua_State *from = lua_tothread(L, -1);
#endif
	lua_rawget(L, lua_upvalueindex(2));	// check total time, 当前函数第二个upvalue指向的index,该index指向一个table,栈顶为key,key为一个协程,从lyield传入,取table[key]压栈
	if (lua_isnil(L, -1)) {
		lua_pop(L,1);
		// printf("%s(%d): %d\n", __FUNCTION__, __LINE__, lua_gettop(L));
	} else {
		double ti = lua_tonumber(L, -1); // total time
		lua_pop(L,1);

		lua_pushthread(L); // 协程压入
		lua_rawget(L, lua_upvalueindex(1)); // 当前函数的第一个upvalue指向的index,该index指向的table,以上面的协程为索引,取得starttime 
		double starttime = lua_tonumber(L, -1); // start time
		lua_pop(L,1);

		double diff = diff_time(starttime); // now - start time
		ti += diff; // 更新时间开销
#ifdef DEBUG_LOG
		fprintf(stderr, "PROFILE [%p] yield (%lf/%lf)\n", from, diff, ti);
		// printf("%s(%d): %d\n", __FUNCTION__, __LINE__, lua_gettop(L));
#endif

		lua_pushthread(L); // 协程入栈作为key
		lua_pushnumber(L, ti); // 更新后的ti入栈作为value
		lua_rawset(L, lua_upvalueindex(2)); // 更新当前函数第二个upvalue指向的index指向的table,t[key]=value
	}

	lua_CFunction co_yield = lua_tocfunction(L, lua_upvalueindex(3)); // lua_CFuntion是一个c函数指针类型,面向lua调用的一个接口,取出当前函数的第三个upvalue指向的index指向的函数指针

	return co_yield(L); // 执行这个函数
}
Esempio n. 5
0
static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
                                 int64_t offset, size_t size,
                                 QEMUIOVector *qiov)
{
    ssize_t r;
    size_t got;
    char *buf, *end_of_vec;
    struct iovec *i;

    DPRINTF("offset=%" PRIi64 " size=%zu", offset, size);

    ssh_seek(s, offset, SSH_SEEK_READ);

    /* This keeps track of the current iovec element ('i'), where we
     * will write to next ('buf'), and the end of the current iovec
     * ('end_of_vec').
     */
    i = &qiov->iov[0];
    buf = i->iov_base;
    end_of_vec = i->iov_base + i->iov_len;

    /* libssh2 has a hard-coded limit of 2000 bytes per request,
     * although it will also do readahead behind our backs.  Therefore
     * we may have to do repeated reads here until we have read 'size'
     * bytes.
     */
    for (got = 0; got < size; ) {
    again:
        DPRINTF("sftp_read buf=%p size=%zu", buf, end_of_vec - buf);
        r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf);
        DPRINTF("sftp_read returned %zd", r);

        if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
            co_yield(s, bs);
            goto again;
        }
        if (r < 0) {
            sftp_error_report(s, "read failed");
            s->offset = -1;
            return -EIO;
        }
        if (r == 0) {
            /* EOF: Short read so pad the buffer with zeroes and return it. */
            qemu_iovec_memset(qiov, got, 0, size - got);
            return 0;
        }

        got += r;
        buf += r;
        s->offset += r;
        if (buf >= end_of_vec && got < size) {
            i++;
            buf = i->iov_base;
            end_of_vec = i->iov_base + i->iov_len;
        }
    }

    return 0;
}
Esempio n. 6
0
int32_t test_unchained() {

    args_t args;
    args.host_ = co_init(nullptr);
    args.val_ = 100000;
    
    for (uint32_t i = 0; i < num_threads; ++i) {
        args.thread_[i] = co_create (args.host_, thread_func, 1024, nullptr);
        assert(args.thread_[i]);
        co_set_user(args.thread_[i], &args);
    }
    co_yield(args.host_, args.thread_[0]);
    assert(args.val_ == 0);
    return 0;
}
Esempio n. 7
0
int32_t test_yieldmain() {

    args_t args;
    args.host_ = co_init(nullptr);

    args.a_ = co_create (args.host_, thread_a, 1024, nullptr, &args);
    args.b_ = co_create (args.host_, thread_b, 1024, nullptr, &args);

    co_yield(args.host_, args.a_);

    co_delete(args.a_);
    co_delete(args.b_);
    co_delete(args.host_);

    return 0;
}
Esempio n. 8
0
static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs)
{
    int r;

    DPRINTF("fsync");
 again:
    r = libssh2_sftp_fsync(s->sftp_handle);
    if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
        co_yield(s, bs);
        goto again;
    }
    if (r == LIBSSH2_ERROR_SFTP_PROTOCOL &&
        libssh2_sftp_last_error(s->sftp) == LIBSSH2_FX_OP_UNSUPPORTED) {
        unsafe_flush_warning(s, "OpenSSH >= 6.3");
        return 0;
    }
    if (r < 0) {
        sftp_error_report(s, "fsync failed");
        return -EIO;
    }

    return 0;
}
Esempio n. 9
0
static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
                     int64_t offset, size_t size,
                     QEMUIOVector *qiov)
{
    ssize_t r;
    size_t written;
    char *buf, *end_of_vec;
    struct iovec *i;

    DPRINTF("offset=%" PRIi64 " size=%zu", offset, size);

    ssh_seek(s, offset, SSH_SEEK_WRITE);

    /* This keeps track of the current iovec element ('i'), where we
     * will read from next ('buf'), and the end of the current iovec
     * ('end_of_vec').
     */
    i = &qiov->iov[0];
    buf = i->iov_base;
    end_of_vec = i->iov_base + i->iov_len;

    for (written = 0; written < size; ) {
    again:
        DPRINTF("sftp_write buf=%p size=%zu", buf, end_of_vec - buf);
        r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf);
        DPRINTF("sftp_write returned %zd", r);

        if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
            co_yield(s, bs);
            goto again;
        }
        if (r < 0) {
            sftp_error_report(s, "write failed");
            s->offset = -1;
            return -EIO;
        }
        /* The libssh2 API is very unclear about this.  A comment in
         * the code says "nothing was acked, and no EAGAIN was
         * received!" which apparently means that no data got sent
         * out, and the underlying channel didn't return any EAGAIN
         * indication.  I think this is a bug in either libssh2 or
         * OpenSSH (server-side).  In any case, forcing a seek (to
         * discard libssh2 internal buffers), and then trying again
         * works for me.
         */
        if (r == 0) {
            ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE);
            co_yield(s, bs);
            goto again;
        }

        written += r;
        buf += r;
        s->offset += r;
        if (buf >= end_of_vec && written < size) {
            i++;
            buf = i->iov_base;
            end_of_vec = i->iov_base + i->iov_len;
        }

        if (offset + written > s->attrs.filesize)
            s->attrs.filesize = offset + written;
    }

    return 0;
}
Esempio n. 10
0
	void CoYield(void * pCoID)
	{
		co_yield((stCoRoutine_t *)pCoID);
	}