예제 #1
0
파일: worker.c 프로젝트: jsyk/lpel
static void FetchAllMessages( workerctx_t *wc)
{
  workermsg_t msg;
  while( LpelMailboxHasIncoming(wc->mailbox) ) {
    LpelMailboxRecv(wc->mailbox, &msg);
    ProcessMessage( wc, &msg);
  }
}
예제 #2
0
static void WrapperLoop(workerctx_t *wp)
{
	lpel_task_t *t = NULL;
	workermsg_t msg;

	do {
		t = wp->current_task;
		if (t != NULL) {
			/* execute task */
			mctx_switch(&wp->mctx, &t->mctx);
		} else {
			/* no ready tasks */
			LpelMailboxRecv(wp->mailbox, &msg);
			switch(msg.type) {
			case WORKER_MSG_ASSIGN:
				t = msg.body.task;
				WORKER_DBG("wrapper: get task %d\n", t->uid);
				assert(t->state == TASK_CREATED);
				t->state = TASK_READY;
				wp->current_task = t;
#ifdef USE_LOGGING
				if (t->mon) {
					if (MON_CB(worker_create_wrapper)) {
						wp->mon = MON_CB(worker_create_wrapper)(t->mon);
					} else {
						wp->mon = NULL;
					}
				}
				if (t->mon && MON_CB(task_assign)) {
					MON_CB(task_assign)(t->mon, wp->mon);
				}
#endif
				break;

			case WORKER_MSG_WAKEUP:
				t = msg.body.task;
				WORKER_DBG("wrapper: unblock task %d\n", t->uid);
				assert (t->state == TASK_BLOCKED);
				t->state = TASK_READY;
				wp->current_task = t;
#ifdef USE_LOGGING
				if (t->mon && MON_CB(task_assign)) {
					MON_CB(task_assign)(t->mon, wp->mon);
				}
#endif
				break;
			default:
				assert(0);
				break;
			}
		}
	} while (!wp->terminate);
	LpelTaskDestroy(wp->current_task);
	/* cleanup task context marked for deletion */
}
예제 #3
0
static void WorkerLoop(workerctx_t *wc)
{
	WORKER_DBG("start worker %d\n", wc->wid);

  lpel_task_t *t = NULL;
  requestTask(wc);		// ask for the first time

  workermsg_t msg;
  do {
  	  LpelMailboxRecv(wc->mailbox, &msg);

  	  switch(msg.type) {
  	  case WORKER_MSG_ASSIGN:
  	  	t = msg.body.task;
  	  	WORKER_DBG("worker %d: get task %d\n", wc->wid, t->uid);
  	  	assert(t->state == TASK_READY);
  	  	t->worker_context = wc;
  	  	wc->current_task = t;

#ifdef USE_LOGGING
  	  	if (wc->mon && MON_CB(worker_waitstop)) {
  	  		MON_CB(worker_waitstop)(wc->mon);
  	  	}
  	  	if (t->mon && MON_CB(task_assign)) {
  	  		MON_CB(task_assign)(t->mon, wc->mon);
  	  	}
#endif
  	  	mctx_switch(&wc->mctx, &t->mctx);
  	  	//task return here
  	  	assert(t->state != TASK_RUNNING);
//  	  	if (t->state != TASK_ZOMBIE) {
  	  	wc->current_task = NULL;
  	  		t->worker_context = NULL;
  	  		returnTask(t);
//  	  	} else
//  	  		LpelTaskDestroy(t);		// if task finish, destroy it and not return to master
  	  	break;
  	  case WORKER_MSG_TERMINATE:
  	  	wc->terminate = 1;
  	  	break;
  	  default:
  	  	assert(0);
  	  	break;
  	  }
  	  // reach here --> message request for task has been sent
  } while (!(wc->terminate) );
}
예제 #4
0
/*
 * clean up master's mailbox before terminating master
 * last messages including: task request from worker, and return zombie task
 */
static void cleanupMasterMb() {
	workermsg_t msg;
	lpel_task_t *t;
	while (LpelMailboxHasIncoming(master->mailbox)) {
		LpelMailboxRecv(master->mailbox, &msg);
		switch(msg.type) {
		case WORKER_MSG_REQUEST:
			break;
		case WORKER_MSG_RETURN:
			t = msg.body.task;
			WORKER_DBG("master: get returned task %d\n", t->uid);
	    assert(t->state == TASK_ZOMBIE);
			LpelTaskDestroy(t);
			break;
		default:
			assert(0);
			break;
		}
	}
}
예제 #5
0
파일: worker.c 프로젝트: jsyk/lpel
static void WaitForNewMessage( workerctx_t *wc)
{
  workermsg_t msg;

#ifdef USE_LOGGING
  if (wc->mon && MON_CB(worker_waitstart)) {
    MON_CB(worker_waitstart)(wc->mon);
  }
#endif

  LpelMailboxRecv(wc->mailbox, &msg);

#ifdef USE_LOGGING
  if (wc->mon && MON_CB(worker_waitstop)) {
    MON_CB(worker_waitstop)(wc->mon);
  }
#endif

  ProcessMessage( wc, &msg);
}
예제 #6
0
static void MasterLoop(masterctx_t *master)
{
	WORKER_DBG("start master\n");
	do {
		workermsg_t msg;

		LpelMailboxRecv(mastermb, &msg);
		lpel_task_t *t;
		int wid;
		switch(msg.type) {
		case WORKER_MSG_ASSIGN:
			/* master receive a new task */
			t = msg.body.task;
			assert (t->state == TASK_CREATED);
			t->state = TASK_READY;
			WORKER_DBG("master: get task %d\n", t->uid);
			if (servePendingReq(master, t) < 0) {		 // no pending request
				t->sched_info.prior = DBL_MAX; //created task does not set up input/output stream yet, set as highest priority
				t->state = TASK_INQUEUE;
				LpelTaskqueuePush(master->ready_tasks, t);
			}
			break;

		case WORKER_MSG_RETURN:
			t = msg.body.task;
			WORKER_DBG("master: get returned task %d\n", t->uid);
			switch(t->state) {
			case TASK_BLOCKED:
				if (t->wakenup == 1) {	/* task has been waked up */
					t->wakenup = 0;
					t->state = TASK_READY;
					// no break, task will be treated as if it is returned as ready
				} else {
					t->state = TASK_RETURNED;
					updatePriorityNeigh(master->ready_tasks, t);
					break;
				}

			case TASK_READY:	// task yields
#ifdef _USE_NEG_DEMAND_LIMIT_
				t->sched_info.prior = LpelTaskCalPriority(t);
				if (t->sched_info.prior == LPEL_DBL_MIN) {		// if not schedule task if it has too low priority
					t->state = TASK_INQUEUE;
					LpelTaskqueuePush(master->ready_tasks, t);
					break;
				}
#endif
				if (servePendingReq(master, t) < 0) {		// no pending request
					updatePriorityNeigh(master->ready_tasks, t);
					t->sched_info.prior = LpelTaskCalPriority(t);	//update new prior before add to the queue
					t->state = TASK_INQUEUE;
					LpelTaskqueuePush(master->ready_tasks, t);
				}
				break;

			case TASK_ZOMBIE:
				updatePriorityNeigh(master->ready_tasks, t);
				LpelTaskDestroy(t);
				break;
			default:
				assert(0);
				break;
			}
			break;

		case WORKER_MSG_WAKEUP:
			t = msg.body.task;
			if (t->state != TASK_RETURNED) {		// task has not been returned yet
				t->wakenup = 1;		// set task as wakenup so that when returned it will be treated as ready
				break;
			}
			WORKER_DBG("master: unblock task %d\n", t->uid);
			t->state = TASK_READY;

#ifdef _USE_NEG_DEMAND_LIMIT_
				t->sched_info.prior = LpelTaskCalPriority(t);
				if (t->sched_info.prior == LPEL_DBL_MIN) {		// if not schedule task if it has too low priority
					t->state = TASK_INQUEUE;
					LpelTaskqueuePush(master->ready_tasks, t);
					break;
				}
#endif

			if (servePendingReq(master, t) < 0) {		// no pending request
#ifndef _USE_NEG_DEMAND_LIMIT_
					t->sched_info.prior = LpelTaskCalPriority(t);	//update new prior before add to the queue
#endif
					t->state = TASK_INQUEUE;
					LpelTaskqueuePush(master->ready_tasks, t);
			}
			break;


		case WORKER_MSG_REQUEST:
			wid = msg.body.from_worker;
			WORKER_DBG("master: request task from worker %d\n", wid);
			t = LpelTaskqueuePeek(master->ready_tasks);
			if (t == NULL) {
				master->waitworkers[wid] = 1;
			} else {

#ifdef _USE_NEG_DEMAND_LIMIT_
				if (t->sched_info.prior == LPEL_DBL_MIN) {		// if not schedule task if it has too low priority
					master->waitworkers[wid] = 1;
					break;
				}
#endif
				t->state = TASK_READY;
				sendTask(wid, t);
				t = LpelTaskqueuePop(master->ready_tasks);
			}
			break;

		case WORKER_MSG_TERMINATE:
			master->terminate = 1;
			break;
		default:
			assert(0);
		}
	} while (!(master->terminate && LpelTaskqueueSize(master->ready_tasks) == 0));
}