Пример #1
0
static int run_traverser(int (*pred)(struct coopth_per_thread_t *),
	void (*post)(struct coopth_per_thread_t *))
{
    int i;
    int cnt = 0;
    for (i = 0; i < threads_active; i++) {
	int tid = active_tids[i];
	struct coopth_t *thr = &coopthreads[tid];
	struct coopth_per_thread_t *pth = current_thr(thr);
	/* only run detached threads here */
	if (pth->data.attached)
	    continue;
	if (pth->data.left) {
	    if (!left_running)
		error("coopth: switching to left thread?\n");
	    continue;
	}
	if (pred && !pred(pth))
	    continue;
	thread_run(thr, pth);
	if (post)
	    post(pth);
	cnt++;
    }
    return cnt;
}
Пример #2
0
void coopth_wake_up(int tid)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    do_awake(pth);
}
Пример #3
0
void coopth_ensure_sleeping(int tid)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    assert(pth->st.state == COOPTHS_SLEEPING);
}
Пример #4
0
int coopth_wants_sleep(void)
{
    struct coopth_t *thr = on_thread();
    struct coopth_per_thread_t *pth;
    if (!thr)
	return 0;
    pth = current_thr(thr);
    return (pth->st.state == COOPTHS_SLEEPING || pth->st.state == COOPTHS_SWITCH);
}
Пример #5
0
/* attach some thread to current context */
void coopth_attach_to_cur(int tid)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    assert(!pth->data.attached);
    coopth_callf(thr, pth);
}
Пример #6
0
void *coopth_pop_user_data(int tid)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    assert(pth->data.udata_num > 0);
    return pth->data.udata[--pth->data.udata_num];
}
Пример #7
0
void coopth_push_user_data(int tid, void *udata)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    assert(pth->data.udata_num < MAX_UDATA);
    pth->data.udata[pth->data.udata_num++] = udata;
}
Пример #8
0
void coopth_run_tid(int tid)
{
    struct coopth_t *thr = &coopthreads[tid];
    struct coopth_per_thread_t *pth = current_thr(thr);
    assert(DETACHED_RUNNING >= 0);
    if (DETACHED_RUNNING)
	return;
    assert(!pth->data.attached && !pth->data.left);
    thread_run(thr, pth);
}
Пример #9
0
void coopth_cancel(int tid)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    if (_coopth_is_in_thread_nowarn())
	assert(tid != coopth_get_tid());
    do_cancel(thr, pth);
}
Пример #10
0
static void coopth_hlt(Bit16u offs, void *arg)
{
    struct coopth_t *thr = (struct coopth_t *)arg + offs;
    struct coopth_per_thread_t *pth = current_thr(thr);
    if (!pth->data.attached) {
	/* someone used coopth_unsafe_detach()? */
	error("HLT on detached thread\n");
	leavedos(2);
	return;
    }
    thread_run(thr, pth);
}
Пример #11
0
int coopth_unsafe_detach(int tid)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    dosemu_error("coopth_unsafe_detach() called\n");
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    assert(pth->data.attached);
    /* this is really unsafe and should be used only if
     * the DOS side of the thread have disappeared. */
    pth->data.attached = 0;
    return 0;
}
Пример #12
0
void coopth_join(int tid, void (*helper)(void))
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    /* since main thread can call this, we have to use helper
     * function instead of just coopth_sched(). As a result,
     * recursion into run_vm86() can happen. Hope its safe. */
    assert(!_coopth_is_in_thread_nowarn() || is_detached());
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    assert(pth->data.attached);
    do_join(pth, helper);
}
Пример #13
0
void coopth_cancel(int tid)
{
    struct coopth_t *thr;
    struct coopth_per_thread_t *pth;
    check_tid(tid);
    thr = &coopthreads[tid];
    pth = current_thr(thr);
    if (_coopth_is_in_thread_nowarn()) {
	if (tid == coopth_get_tid()) {
	    assert(pth->data.left);
	    return;
	}
    }
    do_cancel(thr, pth);
}
Пример #14
0
/* desperate cleanup attempt, not extremely reliable */
int coopth_flush(void (*helper)(void))
{
    struct coopth_t *thr;
    assert(!_coopth_is_in_thread_nowarn() || is_detached());
    while (threads_joinable) {
	struct coopth_per_thread_t *pth;
	/* the sleeping threads are unlikely to be found here.
	 * This is mainly to flush zombies. */
	thr = on_thread();
	if (!thr)
	    break;
	pth = current_thr(thr);
	assert(pth->data.attached);
	do_cancel(thr, pth);
	do_join(pth, helper);
    }
    if (threads_joinable)
	g_printf("Coopth: %i threads stalled\n", threads_joinable);
    return threads_joinable;
}
Пример #15
0
void coopth_run(void)
{
    int i;
    assert(DETACHED_RUNNING >= 0);
    if (DETACHED_RUNNING)
	return;
    for (i = 0; i < threads_active; i++) {
	int tid = active_tids[i];
	struct coopth_t *thr = &coopthreads[tid];
	struct coopth_per_thread_t *pth = current_thr(thr);
	/* only run detached threads here */
	if (pth->data.attached)
	    continue;
	if (pth->data.left) {
	    if (!left_running)
		error("coopth: switching to left thread?\n");
	    continue;
	}
	thread_run(thr, pth);
    }
}
Пример #16
0
void coopth_done(void)
{
    int i, tt, itd, it;
    struct coopth_thrdata_t *thdata = NULL;
    it = _coopth_is_in_thread_nowarn();
    itd = it;
//    assert(!it || is_detached());
    if (it) {
	thdata = co_get_data(co_current());
	assert(thdata);
	/* unfortunately the shutdown can run from signal handler -
	 * in this case we can be in a joinable thread interrupted
	 * by signal, and there is no way to leave that thread. */
	if (!is_detached())
	    itd = 0;
    }
    /* there is no safe way to delete joinable threads without joining,
     * so print error only if there are also detached threads left */
    if (threads_total > threads_joinable + itd)
	error("Coopth: not all detached threads properly shut down\n");
again:
    tt = threads_total;
    for (i = 0; i < threads_active; i++) {
	int tid = active_tids[i];
	struct coopth_t *thr = &coopthreads[tid];
	struct coopth_per_thread_t *pth = current_thr(thr);
	/* dont cancel own thread */
	if (thdata && *thdata->tid == tid)
	    continue;
	if (!pth->data.attached) {
	    error("\ttid=%i state=%i name=\"%s\" off=%#x\n", tid, pth->st.state,
		    thr->name, thr->off);
	    do_cancel(thr, pth);
	    assert(threads_total == tt - 1);
	    /* retry the loop as the array changed */
	    goto again;
	} else {
	    g_printf("\ttid=%i state=%i name=%s off=%#x\n", tid, pth->st.state,
		    thr->name, thr->off);
	}
    }
    /* at this point all detached threads should be killed,
     * except perhaps current one */
    assert(threads_total == threads_joinable + itd);

    for (i = 0; i < coopth_num; i++) {
	struct coopth_t *thr = &coopthreads[i];
	int j;
	/* dont free own thread */
	if (thdata && *thdata->tid == i)
	    continue;
	for (j = thr->cur_thr; j < thr->max_thr; j++) {
	    struct coopth_per_thread_t *pth = &thr->pth[j];
	    munmap(pth->stack, pth->stk_size);
	}
    }
    if (!threads_total)
	co_thread_cleanup();
    else
	g_printf("coopth: leaked %i threads\n", threads_total);
}