コード例 #1
0
ファイル: coopth.c プロジェクト: ccarcel/dosemu2
/* for some time coopth_leave() was implemented on top of coopth_detach().
 * This appeared not the best implementation. In particular, the commit
 * 551371689 was needed to make leaving operation atomic, but this is
 * not needed for detached threads at all. While the detached threads
 * has a separate entry point (via coopth_run()), the left thread must
 * not have a separate entry point. So it appeared better to return the
 * special type "left" threads.
 * Additionally the leave operation now calls the post handler immediately. */
void coopth_leave(void)
{
    struct coopth_thrdata_t *thdata;
    if (!_coopth_is_in_thread_nowarn())
       return;
    thdata = co_get_data(co_current());
    ensure_single(thdata);
    if (thdata->left)
	return;
    switch_state(COOPTH_LEAVE);
}
コード例 #2
0
ファイル: coopth.c プロジェクト: ccarcel/dosemu2
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);
}
コード例 #3
0
ファイル: coopth.c プロジェクト: ccarcel/dosemu2
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);
}
コード例 #4
0
ファイル: coopth.c プロジェクト: andrewbird/dosemu2
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);
}
コード例 #5
0
ファイル: coopth.c プロジェクト: jschwartzenberg/dosemu2
/* for some time coopth_leave() was implemented on top of coopth_detach().
 * This appeared not the best implementation. In particular, the commit
 * 551371689 was needed to make leaving operation atomic, but this is
 * not needed for detached threads at all. While the detached threads
 * has a separate entry point (via coopth_run()), the left thread must
 * not have a separate entry point. So it appeared better to return the
 * special type "left" threads.
 * Additionally the leave operation now calls the post handler immediately,
 * and it should be called from the context of the main thread. This is
 * the reason why coopth_leave() for detached thread cannot be a no-op. */
void coopth_leave(void)
{
    struct coopth_thrdata_t *thdata;
    if (!_coopth_is_in_thread_nowarn())
       return;
    thdata = co_get_data(co_current());
    ensure_single(thdata);
    if (thdata->left)
	return;
    /* leaving detached thread should be atomic even wrt other detached
     * threads. This is needed so that DPMI cannot run concurrently with
     * leavedos().
     * for joinable threads leaving should be atomic only wrt DOS code,
     * but, because of an optimization loop in run_vm86(), it is actually
     * also atomic wrt detached threads. */
    if (!thdata->attached)
	thdata->atomic_switch = 1;
    switch_state(COOPTH_LEAVE);
}
コード例 #6
0
ファイル: coopth.c プロジェクト: ccarcel/dosemu2
/* 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;
}
コード例 #7
0
ファイル: coopth.c プロジェクト: ccarcel/dosemu2
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);
}