From 9825532c82070122b39367f9917cd60541a8ea7e Mon Sep 17 00:00:00 2001 From: stefan Date: Tue, 3 Aug 2010 10:20:32 +0000 Subject: [PATCH] - remove obsolete files - the function join_kernel_task delivers the return value of the task, which is watinting for -spinlocks supports irq save functions git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@21 315a16e6-25f9-4109-90ae-ca3045a26c18 --- arch/x86/include/asm/processor.h | 2 + arch/x86/kernel/timer.c | 2 +- include/metalsvm/irqflags.h | 33 --------- include/metalsvm/spinlocks.h | 12 ++++ include/metalsvm/tasks.h | 2 +- include/metalsvm/tasks_types.h | 3 +- kernel/main.c | 16 ++--- kernel/tasks.c | 116 +++++++++++++++++++++---------- 8 files changed, 105 insertions(+), 81 deletions(-) delete mode 100644 include/metalsvm/irqflags.h diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 66db266f..51d21511 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -31,6 +31,8 @@ static inline uint64_t rdtsc() return x; } +#define get_return_value(ret) asm volatile ("movl %%eax, %0" : "=r"(ret)) + #define NOP1 asm volatile ("nop") #define NOP2 asm volatile ("nop;nop") #define NOP4 asm volatile ("nop;nop;nop;nop") diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index 4b3b2fd4..bfe42d21 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -21,9 +21,9 @@ #include #include #include -#include #include #include +#include /* * This will keep track of how many ticks that the system diff --git a/include/metalsvm/irqflags.h b/include/metalsvm/irqflags.h deleted file mode 100644 index 00a61d03..00000000 --- a/include/metalsvm/irqflags.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010 Stefan Lankes, Chair for Operating Systems, - * RWTH Aachen University - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of MetalSVM. - */ - -#ifndef __IRQFLAGS_H__ -#define __IRQFLAGS_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/metalsvm/spinlocks.h b/include/metalsvm/spinlocks.h index 975527dd..c6de10f3 100644 --- a/include/metalsvm/spinlocks.h +++ b/include/metalsvm/spinlocks.h @@ -22,6 +22,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -59,6 +60,17 @@ inline static int spinlock_unlock(spinlock_t* s) { return 0; } +inline static int spinlock_lock_irqsave(spinlock_t* s) { + irq_disable(); + return spinlock_lock(s); +} + +inline static int spinlock_unlock_irqsave(spinlock_t* s) { + int ret = spinlock_unlock(s); + irq_enable(); + return ret; +} + #ifdef __cplusplus } #endif diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index fb89eb77..2f08b346 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -33,7 +33,7 @@ extern task_t* current_task; int multitasking_init(void); int create_kernel_task(tid_t*, entry_point_t, void*, size_t); -int join_kernel_task(tid_t); +int join_kernel_task(tid_t, void**); void schedule(void); task_t* get_new_task(void); int wakeup_task(tid_t); diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index e448e07f..1d9c4c27 100644 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -37,7 +37,7 @@ extern "C" { typedef void* (STDCALL *entry_point_t)(void*); typedef unsigned int tid_t; -typedef struct task { +typedef struct { unsigned char* top; unsigned int ip; tid_t id; @@ -45,6 +45,7 @@ typedef struct task { unsigned char* stack; size_t stack_size; unsigned char blocked_tasks[MAX_TASKS]; + void* return_value; unsigned char status; unsigned char idle; } task_t; diff --git a/kernel/main.c b/kernel/main.c index ca2bf3ee..11932943 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -69,11 +68,11 @@ void* STDCALL producer(void* arg) } for(i=0; i<5; i++) { - kprintf("Send mail %d\n", mail[i]); + //kprintf("Send mail %d\n", mail[i]); mailbox_post(&mbox, mail+i); } - join_kernel_task(id); + join_kernel_task(id, NULL); return NULL; } @@ -90,18 +89,19 @@ void* STDCALL foo(void* arg) sleep(1); } - return NULL; + return (void*) 42; } void* STDCALL join_test(void* arg) { - int ret; - tid_t id; + int ret; + tid_t id; + void* result = NULL; 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); + ret = join_kernel_task(id, &result); + kprintf("Task %u finished: ret = %d, result = %u\n", id, ret, (int)result); return NULL; } diff --git a/kernel/tasks.c b/kernel/tasks.c index c5b9860e..5f5d02fd 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -20,13 +20,14 @@ #include #include #include -#include #include #include #include +#include task_t* current_task = NULL; static task_t task_table[MAX_TASKS]; +static spinlock_t table_lock = SPINLOCK_INIT; int multitasking_init(void) { memset(task_table, 0, sizeof(task_t)*MAX_TASKS); @@ -40,9 +41,32 @@ int multitasking_init(void) { return 0; } -void NORETURN leave_task(void) { - kprintf("Terminate task: %u\n", current_task->id); +static void wakeup_blocked_tasks(void* result) +{ + unsigned int i; + spinlock_lock_irqsave(&table_lock); + + /* wake up blocked tasks */ + for(i=0; iblocked_tasks[i] && (task_table[i].status == TASK_BLOCKED)) { + task_table[i].return_value = result; + task_table[i].status = TASK_READY; + } + current_task->blocked_tasks[i] = 0; + } + + spinlock_unlock_irqsave(&table_lock); +} + +void NORETURN leave_task(void) { + void* result = NULL; + + get_return_value(result); + + kprintf("Terminate task: %u, return value = %p\n", current_task->id, result); + + wakeup_blocked_tasks(result); current_task->status = TASK_FINISHED; schedule(); @@ -53,8 +77,11 @@ void NORETURN leave_task(void) { } void NORETURN abort(void) { - kprintf("Abbort task: %u\n", current_task->id); + void* result = (void*) -1; + kprintf("Abort task: %u\n", current_task->id); + + wakeup_blocked_tasks(result); current_task->status = TASK_FINISHED; schedule(); @@ -75,7 +102,7 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size if (!stack_size) stack_size = DEFAULT_STACK_SIZE; - irq_disable(); + spinlock_lock_irqsave(&table_lock); for(i=0; iidle, 0)) - goto out; + goto join_out; /* a task is not able to wait for itself */ if (BUILTIN_EXPECT(current_task->id == id, 0)) - goto out; + goto join_out; /* invalid id */ if (BUILTIN_EXPECT(id >= MAX_TASKS, 0)) - goto out; - - ret = 0; + goto join_out; /* task already finished */ if (BUILTIN_EXPECT(task_table[id].status == TASK_INVALID, 0)) - goto out; + goto join_out; /* task already finished */ if (BUILTIN_EXPECT(task_table[id].status == TASK_FINISHED, 0)) - goto out; + goto join_out; task_table[id].blocked_tasks[current_task->id] = 1; current_task->status = TASK_BLOCKED; -out: - irq_enable(); + + spinlock_unlock_irqsave(&table_lock); schedule(); - return ret; + if (result) { + *result = current_task->return_value; + current_task->return_value = NULL; + } + + return 0; + +join_out: + spinlock_unlock_irqsave(&table_lock); + return -1; } int wakeup_task(tid_t id) { + int ret = -1; + + spinlock_lock_irqsave(&table_lock); + if (task_table[id].status != TASK_BLOCKED) { kprintf("Task %u is already unblocked\n", id); - return -1; + goto wakeup_out; } task_table[id].status = TASK_READY; - - return 0; + ret = 0; + +wakeup_out: + spinlock_unlock_irqsave(&table_lock); + return ret; } task_t* get_new_task(void) { + task_t* ret; unsigned int i, new_id; - /* signalize that this task could be reuse */ - if (current_task->status == TASK_FINISHED) { - current_task->status = TASK_INVALID; + spinlock_lock(&table_lock); - /* wake up blocked tasks */ - for(i=0; iblocked_tasks[i]) && (task_table[i].status == TASK_BLOCKED)) - task_table[i].status = TASK_READY; - current_task->blocked_tasks[i] = 0; - } - } + /* signalize that this task could be reuse */ + if (current_task->status == TASK_FINISHED) + current_task->status = TASK_INVALID; for(i=1; i <= MAX_TASKS; i++) { new_id = (current_task->id + i) % MAX_TASKS; @@ -185,12 +220,15 @@ task_t* get_new_task(void) current_task->status = TASK_READY; task_table[new_id].status = TASK_RUNNING; - return task_table+new_id; + ret = task_table+new_id; + goto get_task_out; } } - if (!(current_task->idle) && (current_task->status == TASK_RUNNING)) - return current_task; + if (!(current_task->idle) && (current_task->status == TASK_RUNNING)) { + ret = current_task; + goto get_task_out; + } /* * we switch to the idle task (id=0), if the current task terminates @@ -198,5 +236,9 @@ task_t* get_new_task(void) */ task_table[0].status = TASK_RUNNING; - return task_table+0; + ret = task_table+0; + +get_task_out: + spinlock_unlock(&table_lock); + return ret; }