- add the support of "join_kernel_task"

git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@16 315a16e6-25f9-4109-90ae-ca3045a26c18
This commit is contained in:
stefan 2010-08-02 13:24:05 +00:00
parent 49177e8c9e
commit b11c38d4af
3 changed files with 61 additions and 4 deletions

View file

@ -37,13 +37,14 @@ extern "C" {
typedef void* (STDCALL *entry_point_t)(void*);
typedef unsigned int tid_t;
typedef struct {
typedef struct task {
unsigned char* top;
unsigned int ip;
tid_t id;
mm_t mm;
unsigned char* stack;
size_t stack_size;
unsigned char blocked_tasks[MAX_TASKS];
unsigned char status;
unsigned char idle;
} task_t;

View file

@ -42,6 +42,18 @@ void* STDCALL foo(void* arg)
return NULL;
}
void* STDCALL join_test(void* arg)
{
int ret;
tid_t id;
ret = create_kernel_task(&id, foo, "Hello from foo2\n", 0);
kprintf("Wait for task %u: ret = %d\n", id, ret);
ret = join_kernel_task(id);
kprintf("Task %u finished: ret = %d\n", id, ret);
return NULL;
}
int main(void)
{
@ -70,7 +82,7 @@ int main(void)
timer_set_frequency(TIMER_FREQ);
create_kernel_task(&id1, foo, "Hello from foo1\n", 8192);
create_kernel_task(&id2, foo, "Hello from foo2\n", 0);
create_kernel_task(&id2, join_test, NULL, 0);
current_task->idle = 1;
schedule();

View file

@ -92,6 +92,7 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size
task_table[i].top = task_table[i].stack + stack_size - sizeof(size_t);
task_table[i].ip = 0;
task_table[i].id = i;
memset(task_table[i].blocked_tasks, 0x00, sizeof(unsigned char)*MAX_TASKS);
task_table[i].status = TASK_READY;
task_table[i].idle = 0;
@ -110,7 +111,42 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size
int join_kernel_task(tid_t id)
{
return -1;
int ret = -1;
irq_disable();
/*
* idle tasks are not allowed to wait for another task
* they should always run...
*/
if (BUILTIN_EXPECT(current_task->idle, 0))
goto out;
/* a task is not able to wait for itself */
if (BUILTIN_EXPECT(current_task->id == id, 0))
goto out;
/* invalid id */
if (BUILTIN_EXPECT(id >= MAX_TASKS, 0))
goto out;
ret = 0;
/* task already finished */
if (BUILTIN_EXPECT(task_table[id].status == TASK_INVALID, 0))
goto out;
/* task already finished */
if (BUILTIN_EXPECT(task_table[id].status == TASK_FINISHED, 0))
goto out;
task_table[id].blocked_tasks[current_task->id] = 1;
current_task->status = TASK_BLOCKED;
out:
irq_enable();
schedule();
return ret;
}
task_t* get_new_task(void)
@ -118,9 +154,17 @@ task_t* get_new_task(void)
unsigned int i, new_id;
/* signalize that this task could be reuse */
if (current_task->status == TASK_FINISHED)
if (current_task->status == TASK_FINISHED) {
current_task = TASK_INVALID;
/* wake up blocked tasks */
for(i=0; i<MAX_TASKS; i++) {
if ((current_task->blocked_tasks[i]) && (task_table[i].status == TASK_BLOCKED))
task_table[i].status = TASK_READY;
current_task->blocked_tasks[i] = 0;
}
}
for(i=1; i <= MAX_TASKS; i++) {
new_id = (current_task->id + i) % MAX_TASKS;