view src/pthread/TaskManager.cbc @ 15:2e764a0ae8ff

bit modify.
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Sat, 09 Jan 2010 18:48:57 +0900
parents 5f65da34f4f3
children e89acebd97b1
line wrap: on
line source

#include "List.h"
#include "Queue.h"
#include "TaskManager.h"
#include "Task.h"
#include "Debug.h"

typedef __code (*Scheduler)(struct _UserManager*,Taskrun,void*,void*);

typedef struct _UserManager {
	Scheduler scheduler;
	TaskManager *manager;
} UserManager;
// used only in this file.


/* defined in TaskManagerAbst.  */
extern Task *createTask(int, char *);
extern void taskSetData(Task*, void*, int, void*, int);
extern void taskSpawn(UserManager*, Task*);

/* declarations of code segment.  */
int main (int argc, char **argv);
__code startTaskManager ();
__code searchStartTask (TaskManager *manager);
__code searchStartTask_1 (TaskManager *manager, int i);
__code startTask (TaskManager *manager, int i);
__code executeTask (TaskManager *manager, ListIter *iter, Task *task);
__code checkEvent (TaskManager *manager);
__code checkEvent_real (TaskManager *manager);
static __code selectCode (TaskManager *manager);
static __code schedEntry(UserManager *user, Taskrun nextcode, void *rbuff, void *wbuff);

/* external code segments.  */
extern __code executed (TaskManager *manager, ListIter *iter, Task *task);
extern __code finishTask (TaskManager *manager, Task *task);
extern __code noEvent (TaskManager *manager);
extern __code searchStartTask(TaskManager *manager);


/* for Debug.  */
void printTasks(TaskManager *manager);




int
main(int argc, char **argv)
{
	goto startTaskManager();
}

// TODO: some codes are moved to TaskManagerAbst.
/*
 *   Initialization
 */
__code
startTaskManager()
{
	TaskManager *manager;
	UserManager *umanager;
	manager = malloc(sizeof(TaskManager));
	umanager= malloc(sizeof(UserManager));
	manager->waitingList = NULL;
	manager->activeList = NULL;
	manager->schedTasks = NULL;
	manager->finishtaskQ = createQueue(1);
	manager->user = umanager;

	umanager->manager = manager;
	umanager->scheduler = schedEntry;
	goto startThreadManager(manager);
}

/*
 *  Initialize all ThreadManager.
 */
__code
startThreadManager(TaskManager *manager)
{
	manager->thread_num = 3;//TODO
	manager->thread = malloc(sizeof(ThreadManager)*manager->thread_num);
	manager->thread_round = 0;
	goto startThreadManager_iter(manager, 0);
}
__code
startThreadManager_iter(TaskManager *manager, int i)
{
	if (i < manager->thread_num) {
		manager->thread[i].finishtaskQ = manager->finishtaskQ;
		manager->thread[i].newtaskQ = createQueue(1);
		manager->thread[i].thread_id = i;
		manager->thread[i].finishFlag = 0;
		manager->thread[i].schedTasks = NULL;
		manager->thread[i].running = NULL;
		pthread_create(&manager->thread[i].thread, NULL, threadbase, &manager->thread[i]);
		goto startThreadManager_iter(manager, i+1);
	} else {
		goto searchStartTask(manager);
	}
}



__code
executeTask(TaskManager *manager, ListIter *iter, Task *task)
{
	if (task->cpu==MAIN) {
		SchedTask *stask;
		stask = malloc(sizeof(SchedTask));
		stask->task = task;
		stask->nextcode = tasktypes[task->typeid].code;
		stask->rbuff = task->rbuff;
		stask->wbuff = task->wbuff;

		manager->schedTasks = _listAddFirst(manager->schedTasks, stask);
	} else {
		// どのthreadに渡すかが問題
		// とりあえずラウンドロビン
		queueOffer(manager->thread[manager->thread_round].newtaskQ, task);
		manager->thread_round++;
		manager->thread_round %= manager->thread_num;
	}
	goto executed(manager, iter, task);
}

__code
checkEvent(TaskManager *manager)
{
	goto selectCode(manager);
	// to selectCode, run tasks, and return to checkEvent_real.
}
__code
checkEvent_real(TaskManager *manager)
{
	Task *task;
	//printTasks(manager);
	task = queuePoll(manager->finishtaskQ);
	if (task) {
		__DEBUG("task[%d] finished.\n", task->id);
		goto finishTask(manager, task);
	/*} else if (manager->newtasks) { */
	} else {
		goto noEvent(manager);
	}
}

__code
exitTaskManager(TaskManager *manager)
{
	__DEBUG("all tasks finished!\n");
	exit(0);
}


/*
 *  Scheduler
 */
static __code
selectCode(TaskManager *manager)
{
	SchedTask *task;
	if (manager->schedTasks) {
		task = (SchedTask*)_listGetLastData(manager->schedTasks);
		manager->running = task;

		/* goto user-defined task.  */
		goto task->nextcode(manager->user, task->task->rbuff, task->task->wbuff);
	} else {
		/* no task we have.  */
		//goto checkNewCode();
		goto checkEvent_real(manager);
	}
}

static __code
schedEntry(UserManager *user, Taskrun nextcode, void *rbuff, void *wbuff)
{
	TaskManager *manager = user->manager;
	/* schedulerd  */
	if ( nextcode==NULL ) {
		/* the task finished.  */
		Task *task;
		task = manager->running->task;
		manager->schedTasks =
			_listRemove(manager->schedTasks, manager->running);
		free(manager->running);
		queueOffer(manager->finishtaskQ, task);
		goto selectCode(manager);
	} else {
		/* save the next code segment for the task.  */
		manager->running->nextcode = nextcode;
		manager->running->rbuff = rbuff;
		manager->running->wbuff = wbuff;
		/* move last task to first to be fair.  */
		manager->schedTasks = _listMoveLasttoFirst(manager->schedTasks);
		goto selectCode(manager);
	}
}



/*
 *  for Debug.
 */
void
printTasks(TaskManager *manager)
{
	Task *task;
	SchedTask *stask;
	ListIter *iter;
	__DEBUG("waiting:\n\t");
	iter = _listIterator(manager->waitingList);
	while ( (task=_listIterNext(iter))!=NULL ) {
		__DEBUGnoF("%d, ", task->id);
	}
	__DEBUGnoF("\n");
	_listIterEnd(iter);

	__DEBUG("scheduled:\n\t");
	iter = _listIterator(manager->schedTasks);
	while ( (stask=_listIterNext(iter))!=NULL ) {
		__DEBUGnoF("%d, ", stask->task->id);
	}
	__DEBUGnoF("\n");
	_listIterEnd(iter);

	/*
	__DEBUG("exit:\n\t");
	iter = _listIterator(manager->exitTasks);
	while ( (stask=_listIterNext(iter))!=NULL ) {
		__DEBUGnoF("%d, ", stask->task->id);
	}
	*/
	__DEBUGnoF("\n");
	_listIterEnd(iter);
}

void
taskSpawn(UserManager *user, Task *task)
{
	TaskManager *manager = user->manager;
	manager->waitingList = _listAddFirst(manager->waitingList, task);
	//ablayer->spawnedTasks = _listAddFirst(ablayer->spawnedTasks, task);
	return ;
}