Ejemplo n.º 1
0
void *WrapperThread(void *arg)
{

	workerctx_t *wp = (workerctx_t *)arg;

#ifdef HAVE___THREAD
	workerctx_cur = wp;
#else /* HAVE___THREAD */
	/* set pointer to worker context as TSD */
	pthread_setspecific(workerctx_key, wp);
#endif /* HAVE___THREAD */

#ifdef USE_MCTX_PCL
	assert(0 == co_thread_init());
	wp->mctx = co_current();
#endif

	LpelThreadAssign(wp->wid);
	WrapperLoop(wp);

	addFreeWrapper(wp);

#ifdef USE_MCTX_PCL
	co_thread_cleanup();
#endif
	return NULL;
}
Ejemplo n.º 2
0
static void check_cancel(void)
{
    /* cancellation point */
    struct coopth_thrdata_t *thdata = co_get_data(co_current());
    if (thdata->cancelled)
	longjmp(thdata->exit_jmp, COOPTH_JMP_CANCEL);
}
Ejemplo n.º 3
0
static void coopth_thread(void *arg)
{
    struct coopth_starter_args_t *args = arg;
    enum CoopthJmp jret;
    if (args->thrdata->cancelled) {
	/* can be cancelled before start - no cleanups set yet */
	args->thrdata->ret = COOPTH_DONE;
	return;
    }
    co_set_data(co_current(), args->thrdata);

    jret = setjmp(args->thrdata->exit_jmp);
    switch (jret) {
    case COOPTH_JMP_NONE:
	args->thr.func(args->thr.arg);
	break;
    case COOPTH_JMP_CANCEL:
	if (args->thrdata->clnup.func)
	    args->thrdata->clnup.func(args->thrdata->clnup.arg);
	break;
    case COOPTH_JMP_EXIT:
	break;
    }

    args->thrdata->ret = COOPTH_DONE;
}
Ejemplo n.º 4
0
void coopth_exit(void)
{
    struct coopth_thrdata_t *thdata;
    assert(_coopth_is_in_thread());
    thdata = co_get_data(co_current());
    longjmp(thdata->exit_jmp, COOPTH_JMP_EXIT);
}
Ejemplo n.º 5
0
void *WorkerThread(void *arg)
{
  workerctx_t *wc = (workerctx_t *)arg;

#ifdef HAVE___THREAD
  workerctx_cur = wc;
#else /* HAVE___THREAD */
  /* set pointer to worker context as TSD */
  pthread_setspecific(workerctx_key, wc);
#endif /* HAVE___THREAD */


//FIXME
#ifdef USE_MCTX_PCL
  assert(0 == co_thread_init());
  wc->mctx = co_current();
#endif

  wc->terminate = 0;
  wc->current_task = NULL;
	LpelThreadAssign(wc->wid + 1);		// 0 is for the master
	WorkerLoop(wc);

#ifdef USE_LOGGING
  /* cleanup monitoring */
  if (wc->mon && MON_CB(worker_destroy)) {
    MON_CB(worker_destroy)(wc->mon);
  }
#endif

#ifdef USE_MCTX_PCL
  co_thread_cleanup();
#endif
  return NULL;
}
Ejemplo n.º 6
0
int coopth_get_tid(void)
{
    struct coopth_thrdata_t *thdata;
    assert(_coopth_is_in_thread());
    thdata = co_get_data(co_current());
    return *thdata->tid;
}
Ejemplo n.º 7
0
void coopth_push_user_data_cur(void *udata)
{
    struct coopth_thrdata_t *thdata;
    assert(_coopth_is_in_thread());
    thdata = co_get_data(co_current());
    assert(thdata->udata_num < MAX_UDATA);
    thdata->udata[thdata->udata_num++] = udata;
}
Ejemplo n.º 8
0
void *coopth_pop_user_data_cur(void)
{
    struct coopth_thrdata_t *thdata;
    assert(_coopth_is_in_thread());
    thdata = co_get_data(co_current());
    assert(thdata->udata_num > 0);
    return thdata->udata[--thdata->udata_num];
}
Ejemplo n.º 9
0
static void ensure_attached(void)
{
    struct coopth_thrdata_t *thdata = co_get_data(co_current());
    if (!thdata->attached) {
	dosemu_error("Not allowed for detached thread\n");
	leavedos(2);
    }
}
Ejemplo n.º 10
0
static void ensure_attached(void)
{
    struct coopth_thrdata_t *thdata = co_get_data(co_current(co_handle));
    if (!thdata->attached) {
	dosemu_error("Not allowed for detached thread %i, %s\n",
		*thdata->tid, coopthreads[*thdata->tid].name);
	leavedos(2);
    }
}
Ejemplo n.º 11
0
int coopth_set_cleanup_handler(coopth_func_t func, void *arg)
{
    struct coopth_thrdata_t *thdata;
    assert(_coopth_is_in_thread());
    thdata = co_get_data(co_current());
    thdata->clnup.func = func;
    thdata->clnup.arg = arg;
    return 0;
}
Ejemplo n.º 12
0
void coopth_detach(void)
{
    struct coopth_thrdata_t *thdata;
    assert(_coopth_is_in_thread());
    thdata = co_get_data(co_current());
    ensure_single(thdata);
    if (!thdata->attached)
	return;
    switch_state(COOPTH_DETACH);
}
Ejemplo n.º 13
0
int coopth_set_post_handler(coopth_func_t func, void *arg)
{
    struct coopth_thrdata_t *thdata;
    assert(_coopth_is_in_thread());
    thdata = co_get_data(co_current());
    assert(thdata->posth_num < MAX_POST_H);
    thdata->post[thdata->posth_num].func = func;
    thdata->post[thdata->posth_num].arg = arg;
    thdata->posth_num++;
    return 0;
}
Ejemplo n.º 14
0
/* 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);
}
Ejemplo n.º 15
0
void tpl_switch_context_from_it(
    tpl_context *old_context,
    tpl_context *new_context)
{
    assert( *new_context != co_current() );
    if( *new_context == &idle_task_context )
    {
        /* idle_task activation */
        co_call( idle_task_context );
    }
    else co_call( *new_context );
}
Ejemplo n.º 16
0
void tpl_switch_context(
    tpl_context *old_context,
    tpl_context *new_context)
{
	assert( *new_context != co_current() );
    tpl_release_task_lock();  
    if( *new_context == &idle_task_context )
    {
        /* idle_task activation */
        co_call( idle_task_context );
    }
    else co_call( *new_context );
    tpl_get_task_lock(); 
}
Ejemplo n.º 17
0
/* 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);
}
Ejemplo n.º 18
0
void *MasterThread(void *arg)
{
  masterctx_t *master = (masterctx_t *)arg;
  num_workers = master->num_workers;
//#ifdef HAVE___THREAD
//  workerctx_cur = ms;
//#else /* HAVE___THREAD */
//  /* set pointer to worker context as TSD */
//  pthread_setspecific(workerctx_key, ms);
//#endif /* HAVE___THREAD */


//FIXME
#ifdef USE_MCTX_PCL
  assert(0 == co_thread_init());
  master->mctx = co_current();
#endif


  /* assign to cores */
  master->terminate = 0;
  LpelThreadAssign(LPEL_MAP_MASTER);

  // master loop, no monitor for master
  MasterLoop(master);

  // master terminated, now terminate worker
  workermsg_t msg;
  msg.type = WORKER_MSG_TERMINATE;
  LpelWorkerBroadcast(&msg);

#ifdef USE_MCTX_PCL
  co_thread_cleanup();
#endif

  return NULL;
}
Ejemplo n.º 19
0
Archivo: worker.c Proyecto: jsyk/lpel
/**
 * Thread function for workers (and wrappers)
 */
static void *WorkerThread( void *arg)
{
  workerctx_t *wc = (workerctx_t *)arg;
  lpel_task_t *t;

#ifdef HAVE___THREAD
  workerctx_cur = wc;
#else /* HAVE___THREAD */
  /* set pointer to worker context as TSD */
  pthread_setspecific(workerctx_key, wc);
#endif /* HAVE___THREAD */


#ifdef USE_MCTX_PCL
  int res = co_thread_init();
  assert( 0 == res);
  wc->mctx = co_current();
#endif


  wc->current_task = NULL;

  /* no task marked for deletion */
  wc->marked_del = NULL;

  /* assign to cores */
  LpelThreadAssign( wc->wid);

  /*******************************************************/
  if ( wc->wid >= 0) {
    WorkerLoop( wc);
  } else {
    WrapperLoop( wc);
  }
  /*******************************************************/

#ifdef USE_LOGGING
  /* cleanup monitoring */
  if (wc->mon && MON_CB(worker_destroy)) {
    MON_CB(worker_destroy)(wc->mon);
  }
#endif

  /* destroy all the free tasks */
  while ((t = LpelPopTask(free, &wc->free_tasks))) {
      LpelTaskDestroy(t);
  }

  /* on a wrapper, we also can cleanup more*/
  if (wc->wid < 0) {
    /* clean up the mailbox for the worker */
    LpelMailboxDestroy(wc->mailbox);

    /* free the worker context */
    free( wc);
  }

#ifdef USE_MCTX_PCL
  co_thread_cleanup();
#endif

  return NULL;
}
Ejemplo n.º 20
0
static int is_detached(void)
{
    struct coopth_thrdata_t *thdata = co_get_data(co_current());
    assert(thdata);
    return (!thdata->attached);
}
Ejemplo n.º 21
0
static void switch_state(enum CoopthRet ret)
{
    struct coopth_thrdata_t *thdata = co_get_data(co_current());
    thdata->ret = ret;
    co_resume();
}
Ejemplo n.º 22
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);
}