From 452aa3b1d193baa3c07f830041e55587f8b4b3d5 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 3 Aug 2011 19:37:05 +0200 Subject: [PATCH 01/11] cosmetic changes and add some scheduling statistics --- arch/x86/include/asm/processor.h | 4 ++-- arch/x86/include/asm/tasks.h | 5 +++++ arch/x86/kernel/apic.c | 6 +++--- include/metalsvm/tasks_types.h | 10 ++++++---- kernel/main.c | 1 + kernel/tasks.c | 27 +++++++++++++++++++++++++-- kernel/tests.c | 2 ++ 7 files changed, 44 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 91f30387..da3b3556 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -42,9 +42,9 @@ extern "C" { // feature list 1 #define CPU_FEATURE_FPU (1 << 0) #define CPU_FEATURE_MMX (1 << 23) -#define CPU_FEATURE_FXSR (1 << 24) +#define CPU_FEATURE_FXSR (1 << 24) #define CPU_FEATURE_SSE (1 << 25) -#define CPU_FEATURE_SSE2 (1 << 26) +#define CPU_FEATURE_SSE2 (1 << 26) // feature list 2 #define CPU_FEATURE_AVX (1 << 28) diff --git a/arch/x86/include/asm/tasks.h b/arch/x86/include/asm/tasks.h index c12f946a..d2cf6731 100644 --- a/arch/x86/include/asm/tasks.h +++ b/arch/x86/include/asm/tasks.h @@ -36,6 +36,11 @@ extern "C" { #endif +/** + * @brief Dump some scheduling statistics + */ +int dump_scheduling_statistics(void); + /** @brief Fork a task from current task * * @param task Pointer to the task structure to fork to diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 29033d0e..0651750e 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -301,9 +301,6 @@ void smp_start(uint32_t id) // install IDT idt_install(); - // enable additional cpu features - cpu_detection(); - /* enable paging */ write_cr3((uint32_t)get_boot_pgd()); i = read_cr0(); @@ -320,6 +317,9 @@ void smp_start(uint32_t id) */ register_task(per_core(current_task)); + // enable additional cpu features + cpu_detection(); + smp_main(); // idle loop diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index 9725454b..f63ae533 100644 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -41,11 +41,11 @@ extern "C" { #endif #define TASK_INVALID 0 -#define TASK_READY 1 +#define TASK_READY 1 #define TASK_RUNNING 2 #define TASK_BLOCKED 3 #define TASK_FINISHED 4 -#define TASK_IDLE 5 +#define TASK_IDLE 5 #define TASK_DEFAULT_FLAGS 0 #define TASK_FPU_INIT (1 << 0) @@ -61,8 +61,10 @@ typedef struct task { tid_t id; /// Task status (INVALID, READY, RUNNING, ...) uint32_t status; + /// Number of used time slices + uint32_t time_slices; /// Usage in number of pages - atomic_int32_t user_usage; + atomic_int32_t user_usage; /// Avoids concurrent access to the page directory spinlock_t pgd_lock; /// pointer to the page directory @@ -85,7 +87,7 @@ typedef struct task { mailbox_wait_msg_t* outbox[MAX_TASKS]; /// FPU state union fpu_state fpu; -} __attribute__((packed)) task_t; +} task_t; #ifdef __cplusplus } diff --git a/kernel/main.c b/kernel/main.c index 86646610..8b54795f 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -128,6 +128,7 @@ int main(void) list_root(); test_init(); per_core(current_task)->status = TASK_IDLE; + per_core(current_task)->time_slices = 0; // reset the number of time slices reschedule(); while(1) { diff --git a/kernel/tasks.c b/kernel/tasks.c index 00e23098..95c4c1ed 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -47,8 +47,8 @@ * A task's id will be its position in this array. */ static task_t task_table[MAX_TASKS] = { \ - [0] = {0, TASK_RUNNING, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}, \ - [1 ... MAX_TASKS-1] = {0, TASK_INVALID, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}}; + [0] = {0, TASK_RUNNING, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}, \ + [1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}}; static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT; DEFINE_PER_CORE(task_t*, current_task, task_table+0); @@ -63,6 +63,24 @@ task_t* get_current_task(void) { return per_core(current_task); } +int dump_scheduling_statistics(void) +{ + uint32_t i; + uint32_t id = 0; + + kprintf("Scheduling statistics:\n"); + kprintf("======================\n"); + kprintf("total ticks:\t%llu\n", get_clock_tick()); + for(i=0; itime_slices++; + /* signalizes that this task could be reused */ if (curr_task->status == TASK_FINISHED) curr_task->status = TASK_INVALID; diff --git a/kernel/tests.c b/kernel/tests.c index ecef70c2..bced389b 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -121,6 +121,8 @@ static int join_test(void* arg) kprintf("Child %u finished: result = %d\n", id, result); + dump_scheduling_statistics(); + return 0; } From 40230ade507748b936be007b33eed441f9d84ae6 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 3 Aug 2011 21:38:40 +0200 Subject: [PATCH 02/11] avoid unneeded using of per_core macro --- include/metalsvm/semaphore.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/metalsvm/semaphore.h b/include/metalsvm/semaphore.h index 735c0e78..42348383 100644 --- a/include/metalsvm/semaphore.h +++ b/include/metalsvm/semaphore.h @@ -83,6 +83,8 @@ inline static int sem_destroy(sem_t* s) { * - -1 on failure */ inline static int sem_wait(sem_t* s) { + task_t* curr_task = per_core(current_task); + if (BUILTIN_EXPECT(!s, 0)) return -1; @@ -92,9 +94,9 @@ next_try: s->value--; spinlock_unlock(&s->lock); } else { - s->queue[s->pos] = per_core(current_task)->id; + s->queue[s->pos] = curr_task->id; s->pos = (s->pos + 1) % MAX_TASKS; - block_task(per_core(current_task)->id); + block_task(curr_task->id); spinlock_unlock(&s->lock); reschedule(); goto next_try; From 2e1cfd7965eeb061c08c8d99a1f50a5423b040d8 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 3 Aug 2011 21:40:07 +0200 Subject: [PATCH 03/11] fix wrong data type and wrong using of create_kernel_task --- lwip/src/arch/sys_arch.c | 2 +- lwip/src/include/arch/sys_arch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lwip/src/arch/sys_arch.c b/lwip/src/arch/sys_arch.c index 47c6e6ec..b9b2d7db 100644 --- a/lwip/src/arch/sys_arch.c +++ b/lwip/src/arch/sys_arch.c @@ -82,7 +82,7 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, tid_t tmp; kprintf("Create LWIP task %s\n", name); - create_kernel_task(&tmp,thread,arg); + create_kernel_task(&tmp, thread, arg); return tmp; } diff --git a/lwip/src/include/arch/sys_arch.h b/lwip/src/include/arch/sys_arch.h index eab88cb5..6857d983 100644 --- a/lwip/src/include/arch/sys_arch.h +++ b/lwip/src/include/arch/sys_arch.h @@ -21,7 +21,7 @@ typedef struct int valid; } sys_mbox_t; -typedef tid_t* sys_thread_t; +typedef tid_t sys_thread_t; #if SYS_LIGHTWEIGHT_PROT #if MAX_CORES > 1 From 22441375bb2253b0f1f82f6ef5e4d6fb4cade0dd Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 3 Aug 2011 21:41:06 +0200 Subject: [PATCH 04/11] add blocking timers only the idle tasks use the polling mode --- arch/x86/kernel/timer.c | 56 ++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index 251f71f8..66c4ac82 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -23,17 +23,26 @@ #include #include #include +#include #include #include #include #include #include +typedef struct { + uint8_t active; + uint64_t timeout; +} timer_t; + +static timer_t timers[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, 0}}; +static spinlock_irqsave_t timers_lock = SPINLOCK_IRQSAVE_INIT; + /* * This will keep track of how many ticks the system * has been running for */ -static volatile uint64_t timer_ticks __attribute__ ((aligned (CACHE_LINE))) = 0; +static volatile uint64_t timer_ticks = 0; uint64_t get_clock_tick(void) { @@ -60,13 +69,24 @@ int sys_times(struct tms* buffer, clock_t* clock) */ static void timer_handler(struct state *s) { + uint32_t i; + /* Increment our 'tick counter' */ #if MAX_CORES > 1 if (smp_id() == 0) - timer_ticks++; -#else - timer_ticks++; #endif + { + timer_ticks++; + + spinlock_irqsave_lock(&timers_lock); + for(i=1; i= timers[i].timeout)) { + timers[i].active = 0; + wakeup_task(i); + } + } + spinlock_irqsave_unlock(&timers_lock); + } /* * Every TIMER_FREQ clocks (approximately 1 second), we will @@ -84,15 +104,33 @@ static void timer_handler(struct state *s) void timer_wait(unsigned int ticks) { uint64_t eticks = timer_ticks + ticks; + task_t* curr_task = per_core(current_task); - while (timer_ticks < eticks) { + // Task 0 is always an idle task + // Perhaps, the status is not set correctly... + if ((curr_task->status == TASK_IDLE) || (curr_task->id == 0)) + { + while (timer_ticks < eticks) { + check_workqueues(); + + // recheck break condition + if (timer_ticks >= eticks) + break; + + HALT; + } + } else if (timer_ticks < eticks) { check_workqueues(); - // recheck break condition - if (timer_ticks >= eticks) - break; + spinlock_irqsave_lock(&timers_lock); + if (timer_ticks < eticks) { + timers[curr_task->id].active = 1; + timers[curr_task->id].timeout = eticks; + block_task(curr_task->id); + spinlock_irqsave_unlock(&timers_lock); - reschedule(); + reschedule(); + } else spinlock_irqsave_unlock(&timers_lock); } } From 387ef0ea9b92303073fd18f5a4a2ca9bc45ff1b6 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 4 Aug 2011 16:48:04 +0200 Subject: [PATCH 05/11] cosmetic changes --- arch/x86/kernel/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 0651750e..379a181b 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -338,7 +338,7 @@ static apic_mp_t* search_apic(size_t base, size_t limit) { if (tmp->signature == MP_FLT_SIGNATURE) { if (!((tmp->version > 4) || tmp->features[0])) return tmp; - } + } } return NULL; From 87cd484bb92e8f0ac49e08b5d8e71b62fdbe9a11 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 6 Aug 2011 15:46:10 +0200 Subject: [PATCH 06/11] add additional debug information --- drivers/net/rtl8139.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 1afc6a10..c7978fdf 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -113,7 +113,8 @@ static err_t rtl8139if_output(struct netif* netif, struct pbuf* p) static void rtl8139if_input(struct netif* netif, struct pbuf* p) { struct eth_hdr *ethhdr; - + err_t err; + /* points to packet payload, which starts with an Ethernet header */ ethhdr = p->payload; @@ -127,8 +128,9 @@ static void rtl8139if_input(struct netif* netif, struct pbuf* p) case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ /* full packet send to tcpip_thread to process */ - if (mynetif->input(p, mynetif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_input: IP input error\n")); + err = mynetif->input(p, mynetif); + if (err != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_input: IP input error %d\n", (int32_t) err)); pbuf_free(p); } break; From e4a170938e3789b571c8701e86f0f840584f05c7 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 6 Aug 2011 15:52:47 +0200 Subject: [PATCH 07/11] create a special init task (initd), which spawns all other tasks --- kernel/init.c | 43 +++++++++++++++++++++++++++++++++++++++++++ kernel/main.c | 42 ++---------------------------------------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/kernel/init.c b/kernel/init.c index b63c5c43..39274ebb 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef CONFIG_LWIP #include #include @@ -47,6 +48,7 @@ void echo_init(void); void ping_init(void); +int test_init(void); /* * Note that linker symbols are not variables, they have no memory allocated for @@ -178,4 +180,45 @@ int network_shutdown(void) return 0; } +static void list_fs(vfs_node_t* node, uint32_t depth) +{ + int j, i = 0; + dirent_t* dirent = NULL; + + while ((dirent = readdir_fs(node, i)) != 0) { + for(j=0; jname); + + if (strcmp(dirent->name, ".") && strcmp(dirent->name, "..")) { + vfs_node_t *new_node = finddir_fs(node, dirent->name); + if (new_node) { + if (new_node->type == FS_FILE) { + char buff[16] = {[0 ... 15] = 0x00}; + + read_fs(new_node, (uint8_t*)buff, 8, 0); + for(j=0; j #include #include -#include #include #include +#include #include #include #include @@ -34,8 +34,6 @@ #include #endif -extern int test_init(void); - /* * Note that linker symbols are not variables, they have no memory allocated for * maintaining a value, rather their address is their value. @@ -45,39 +43,6 @@ extern const void kernel_end; extern char __BUILD_DATE; extern char __BUILD_TIME; -static void list_fs(vfs_node_t* node, uint32_t depth) -{ - int j, i = 0; - dirent_t* dirent = NULL; - - while ((dirent = readdir_fs(node, i)) != 0) { - for(j=0; jname); - - if (strcmp(dirent->name, ".") && strcmp(dirent->name, "..")) { - vfs_node_t *new_node = finddir_fs(node, dirent->name); - if (new_node) { - if (new_node->type == FS_FILE) { - char buff[16] = {[0 ... 15] = 0x00}; - - read_fs(new_node, (uint8_t*)buff, 8, 0); - for(j=0; j 1 // idle loop of the application processors int smp_main(void) @@ -117,7 +82,6 @@ int main(void) kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end); system_calibration(); - network_init(); kprintf("Processor frequency: %u MHz\n", get_cpu_frequency()); kprintf("Total memory: %u MBytes\n", atomic_int32_read(&total_pages)/((1024*1024)/PAGE_SIZE)); @@ -125,9 +89,7 @@ int main(void) kprintf("Current available memory: %u MBytes\n", atomic_int32_read(&total_available_pages)/((1024*1024)/PAGE_SIZE)); sleep(5); - list_root(); - test_init(); - per_core(current_task)->status = TASK_IDLE; + create_kernel_task(NULL, initd, NULL); per_core(current_task)->time_slices = 0; // reset the number of time slices reschedule(); From 54dfd7ba49304c05c9a154af1e1fed47b029c194 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 6 Aug 2011 15:54:00 +0200 Subject: [PATCH 08/11] add example macro to check if the tcpip thread is alive --- lwip/src/include/lwipopts.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index 4be7eb4c..1d3e7b9d 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -118,4 +118,5 @@ #define TIMERS_DEBUG LWIP_DBG_OFF #define SOCKETS_DEBUG LWIP_DBG_OFF +//#define LWIP_TCPIP_THREAD_ALIVE() kputs("TCPIP thread is alive!\n") #endif From a179ded21bf7c1a0c313b27fa334c7ccc1083199 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 6 Aug 2011 15:55:34 +0200 Subject: [PATCH 09/11] redesign of the timers, support of timeouts in mailboxes and semaphores --- arch/x86/kernel/gdt.c | 7 +- arch/x86/kernel/timer.c | 59 +++++------- include/metalsvm/init.h | 3 + include/metalsvm/mailbox.h | 39 +++++--- include/metalsvm/semaphore.h | 139 +++++++++++++++++++---------- include/metalsvm/semaphore_types.h | 4 +- include/metalsvm/tasks.h | 7 -- include/metalsvm/tasks_types.h | 8 +- include/metalsvm/time.h | 8 +- kernel/tasks.c | 137 +++++++++++++++------------- kernel/tests.c | 6 +- lwip/src/arch/sys_arch.c | 105 +++++++++++----------- 12 files changed, 287 insertions(+), 235 deletions(-) diff --git a/arch/x86/kernel/gdt.c b/arch/x86/kernel/gdt.c index 9441410a..f6667c60 100644 --- a/arch/x86/kernel/gdt.c +++ b/arch/x86/kernel/gdt.c @@ -116,9 +116,8 @@ int arch_fork(task_t* task) asm volatile ("pop %0" : "=r"(task_state_segments[id].ecx)); asm volatile ("pop %0" : "=r"(task_state_segments[id].eax)); - // store current EFLAGS and set IF flag - // => the parent task will enable the interrupt handling - asm volatile ("pushf; pop %%eax; or $2,%%ah" : "=a"(task_state_segments[id].eflags)); + // store the current EFLAGS + asm volatile ("pushf; pop %%eax" : "=a"(task_state_segments[id].eflags)); // This will be the entry point for the new task. asm volatile ("call read_eip" : "=a"(task_state_segments[id].eip)); @@ -146,7 +145,7 @@ int create_default_frame(task_t* task, internal_entry_point_t ep, void* arg) task_state_segments[id].fs = ds; task_state_segments[id].gs = ds; task_state_segments[id].es = ds; - task_state_segments[id].eflags = 0x1202; + task_state_segments[id].eflags = 0x1002; // 0x1202; task_state_segments[id].cr3 = (uint32_t) (virt_to_phys((size_t)task->pgd)); task_state_segments[id].eip = (uint32_t) ep; task_state_segments[id].esp = (uint32_t) kstacks[id] + KERNEL_STACK_SIZE - sizeof(size_t); diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index 66c4ac82..8a806eb6 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -30,14 +30,6 @@ #include #include -typedef struct { - uint8_t active; - uint64_t timeout; -} timer_t; - -static timer_t timers[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, 0}}; -static spinlock_irqsave_t timers_lock = SPINLOCK_IRQSAVE_INIT; - /* * This will keep track of how many ticks the system * has been running for @@ -78,38 +70,27 @@ static void timer_handler(struct state *s) { timer_ticks++; - spinlock_irqsave_lock(&timers_lock); - for(i=1; i= timers[i].timeout)) { - timers[i].active = 0; - wakeup_task(i); - } - } - spinlock_irqsave_unlock(&timers_lock); + /* + * Every TIMER_FREQ clocks (approximately 1 second), we will + * display a message on the screen + */ + /*if (timer_ticks % TIMER_FREQ == 0) { + vga_puts("One second has passed\n"); + }*/ } - - /* - * Every TIMER_FREQ clocks (approximately 1 second), we will - * display a message on the screen - */ - /*if (timer_ticks % TIMER_FREQ == 0) { - vga_puts("One second has passed\n"); - }*/ } -/* - * This will continuously loop until the given time has - * been reached - */ -void timer_wait(unsigned int ticks) +int timer_wait(unsigned int ticks) { uint64_t eticks = timer_ticks + ticks; task_t* curr_task = per_core(current_task); - // Task 0 is always an idle task - // Perhaps, the status is not set correctly... - if ((curr_task->status == TASK_IDLE) || (curr_task->id == 0)) + if (curr_task->status == TASK_IDLE) { + /* + * This will continuously loop until the given time has + * been reached + */ while (timer_ticks < eticks) { check_workqueues(); @@ -122,16 +103,18 @@ void timer_wait(unsigned int ticks) } else if (timer_ticks < eticks) { check_workqueues(); - spinlock_irqsave_lock(&timers_lock); if (timer_ticks < eticks) { - timers[curr_task->id].active = 1; - timers[curr_task->id].timeout = eticks; - block_task(curr_task->id); - spinlock_irqsave_unlock(&timers_lock); + uint32_t flags = irq_nested_disable(); + curr_task->timeout = eticks; + curr_task->flags |= TASK_TIMER_USED; + curr_task->status = TASK_BLOCKED; + irq_nested_enable(flags); reschedule(); - } else spinlock_irqsave_unlock(&timers_lock); + } } + + return 0; } #define LATCH(f) ((CLOCK_TICK_RATE + f/2) / f) diff --git a/include/metalsvm/init.h b/include/metalsvm/init.h index fddf3409..02f97091 100644 --- a/include/metalsvm/init.h +++ b/include/metalsvm/init.h @@ -42,6 +42,9 @@ int network_init(void); /** @brief Shutdown the networking subsystem. */ int network_shutdown(void); +/** @brief Entry point of the init task */ +int initd(void* arg); + #ifdef __cplusplus } #endif diff --git a/include/metalsvm/mailbox.h b/include/metalsvm/mailbox.h index 3ffb1d87..8d86492c 100644 --- a/include/metalsvm/mailbox.h +++ b/include/metalsvm/mailbox.h @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -32,7 +33,7 @@ extern "C" { #define MAILBOX(name, type) \ inline static int mailbox_##name##_init(mailbox_##name##_t* m) { \ if (BUILTIN_EXPECT(!m, 0)) \ - return -1; \ + return -EINVAL; \ \ memset(m->buffer, 0x00, sizeof(type)*MAILBOX_SIZE); \ m->wpos = m->rpos = 0; \ @@ -46,7 +47,7 @@ extern "C" { \ inline static int mailbox_##name##_destroy(mailbox_##name##_t* m) { \ if (BUILTIN_EXPECT(!m, 0)) \ - return -1; \ + return -EINVAL; \ \ sem_destroy(&m->mails); \ sem_destroy(&m->boxes); \ @@ -58,9 +59,9 @@ extern "C" { \ inline static int mailbox_##name##_post(mailbox_##name##_t* m, type mail) { \ if (BUILTIN_EXPECT(!m, 0)) \ - return -1; \ + return -EINVAL; \ \ - sem_wait(&m->boxes); \ + sem_wait(&m->boxes, 0); \ spinlock_lock(&m->wlock); \ m->buffer[m->wpos] = mail; \ m->wpos = (m->wpos+1) % MAILBOX_SIZE; \ @@ -70,11 +71,29 @@ extern "C" { return 0; \ } \ \ - inline static int mailbox_##name##_fetch(mailbox_##name##_t* m, type* mail) { \ - if (BUILTIN_EXPECT(!m || !mail, 0)) \ - return -1; \ + inline static int mailbox_##name##_trypost(mailbox_##name##_t* m, type mail) { \ + if (BUILTIN_EXPECT(!m, 0)) \ + return -EINVAL; \ \ - sem_wait(&m->mails); \ + if (sem_trywait(&m->boxes)) \ + return -EBUSY; \ + spinlock_lock(&m->wlock); \ + m->buffer[m->wpos] = mail; \ + m->wpos = (m->wpos+1) % MAILBOX_SIZE; \ + spinlock_unlock(&m->wlock); \ + sem_post(&m->mails); \ + \ + return 0; \ + } \ + \ + inline static int mailbox_##name##_fetch(mailbox_##name##_t* m, type* mail, uint32_t ms) { \ + int err; \ + \ + if (BUILTIN_EXPECT(!m || !mail, 0)) \ + return -EINVAL; \ + \ + err = sem_wait(&m->mails, ms); \ + if (err) return err; \ spinlock_lock(&m->rlock); \ *mail = m->buffer[m->rpos]; \ m->rpos = (m->rpos+1) % MAILBOX_SIZE; \ @@ -86,10 +105,10 @@ extern "C" { \ inline static int mailbox_##name##_tryfetch(mailbox_##name##_t* m, type* mail) { \ if (BUILTIN_EXPECT(!m || !mail, 0)) \ - return -1; \ + return -EINVAL; \ \ if (sem_trywait(&m->mails) != 0) \ - return -1; \ + return -EINVAL; \ spinlock_lock(&m->rlock); \ *mail = m->buffer[m->rpos]; \ m->rpos = (m->rpos+1) % MAILBOX_SIZE; \ diff --git a/include/metalsvm/semaphore.h b/include/metalsvm/semaphore.h index 42348383..19ad8e38 100644 --- a/include/metalsvm/semaphore.h +++ b/include/metalsvm/semaphore.h @@ -29,6 +29,8 @@ #include #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -43,19 +45,19 @@ extern "C" { * * @return * - 0 on success - * - -1 on failure + * - -EINVAL on invalid argument */ inline static int sem_init(sem_t* s, unsigned int v) { unsigned int i; if (BUILTIN_EXPECT(!s, 0)) - return -1; + return -EINVAL; s->value = v; s->pos = 0; for(i=0; iqueue[i] = MAX_TASKS; - spinlock_init(&s->lock); + spinlock_irqsave_init(&s->lock); return 0; } @@ -63,44 +65,13 @@ inline static int sem_init(sem_t* s, unsigned int v) { /** @brief Destroy semaphore * @return * - 0 on success - * - -1 on failure + * - -EINVAL on invalid argument */ inline static int sem_destroy(sem_t* s) { if (BUILTIN_EXPECT(!s, 0)) - return -1; + return -EINVAL; - spinlock_destroy(&s->lock); - - return 0; -} - -/** @brief Blocking wait for semaphore - * - * This will put your task to sleep - * - * @return - * - 0 on success - * - -1 on failure - */ -inline static int sem_wait(sem_t* s) { - task_t* curr_task = per_core(current_task); - - if (BUILTIN_EXPECT(!s, 0)) - return -1; - -next_try: - spinlock_lock(&s->lock); - if (s->value > 0) { - s->value--; - spinlock_unlock(&s->lock); - } else { - s->queue[s->pos] = curr_task->id; - s->pos = (s->pos + 1) % MAX_TASKS; - block_task(curr_task->id); - spinlock_unlock(&s->lock); - reschedule(); - goto next_try; - } + spinlock_irqsave_destroy(&s->lock); return 0; } @@ -111,37 +82,111 @@ next_try: * * @return * - 0 on success (You got the semaphore) - * - -1 on failure (You still have to wait) + * - -EINVAL on invalid argument + * - -ECANCELED on failure (You still have to wait) */ inline static int sem_trywait(sem_t* s) { - int ret = -1; + int ret = -ECANCELED; if (BUILTIN_EXPECT(!s, 0)) - return -1; + return -EINVAL; - spinlock_lock(&s->lock); + spinlock_irqsave_lock(&s->lock); if (s->value > 0) { s->value--; ret = 0; } - spinlock_unlock(&s->lock); + spinlock_irqsave_unlock(&s->lock); return ret; } +/** @brief Blocking wait for semaphore + * + * @param ms Timeout in milliseconds + * @return + * - 0 on success + * - -EINVAL on invalid argument + * - -ETIME on timer expired + */ +inline static int sem_wait(sem_t* s, uint32_t ms) { + task_t* curr_task = per_core(current_task); + + if (BUILTIN_EXPECT(!s, 0)) + return -EINVAL; + + if (!ms) { +next_try1: + spinlock_irqsave_lock(&s->lock); + if (s->value > 0) { + s->value--; + spinlock_irqsave_unlock(&s->lock); + } else { + s->queue[s->pos] = curr_task->id; + s->pos = (s->pos + 1) % MAX_TASKS; + curr_task->status = TASK_BLOCKED; + spinlock_irqsave_unlock(&s->lock); + reschedule(); + NOP2; + goto next_try1; + } + + return 0; + } else { + uint32_t ticks = (ms * TIMER_FREQ) / 1000; + uint32_t remain = (ms * TIMER_FREQ) % 1000; + + if (ticks) { + uint64_t deadline = get_clock_tick() + ticks; + +next_try2: + spinlock_irqsave_lock(&s->lock); + if (s->value > 0) { + s->value--; + spinlock_irqsave_unlock(&s->lock); + return 0; + } else { + if (get_clock_tick() >= deadline) { + spinlock_irqsave_unlock(&s->lock); + goto timeout; + } + s->queue[s->pos] = curr_task->id; + s->pos = (s->pos + 1) % MAX_TASKS; + curr_task->timeout = deadline; + curr_task->flags |= TASK_TIMER_USED; + curr_task->status = TASK_BLOCKED; + spinlock_irqsave_unlock(&s->lock); + reschedule(); + goto next_try2; + } + } + +timeout: + while (remain) { + udelay(1000); + remain--; + + if (!sem_trywait(s)) + return 0; + } + + return -ETIME; + } +} + /** @brief Give back resource * @return * - 0 on success - * - -1 on failure + * - -EINVAL on invalid argument */ inline static int sem_post(sem_t* s) { if (BUILTIN_EXPECT(!s, 0)) - return -1; + return -EINVAL; - spinlock_lock(&s->lock); + spinlock_irqsave_lock(&s->lock); if (s->value > 0) { s->value++; - spinlock_unlock(&s->lock); + spinlock_irqsave_unlock(&s->lock); } else { unsigned int k, i; @@ -155,7 +200,7 @@ inline static int sem_post(sem_t* s) { } i = (i + 1) % MAX_TASKS; } - spinlock_unlock(&s->lock); + spinlock_irqsave_unlock(&s->lock); } return 0; diff --git a/include/metalsvm/semaphore_types.h b/include/metalsvm/semaphore_types.h index a80dbc5e..5812d51a 100644 --- a/include/metalsvm/semaphore_types.h +++ b/include/metalsvm/semaphore_types.h @@ -41,11 +41,11 @@ typedef struct { /// Position in queue unsigned int pos; /// Access lock - spinlock_t lock; + spinlock_irqsave_t lock; } sem_t; /// Macro for initialization of semaphore -#define SEM_INIT(v) {v, {[0 ... MAX_TASKS-1] = MAX_TASKS}, 0, SPINLOCK_INIT} +#define SEM_INIT(v) {v, {[0 ... MAX_TASKS-1] = MAX_TASKS}, 0, SPINLOCK_IRQSAVE_INIT} #ifdef __cplusplus } diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index c4e68991..0b0bcdac 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -100,13 +100,6 @@ void scheduler(void); */ int wakeup_task(tid_t); -/** @brief Change a task's status to TASK_BLOCKED - * @return - * - 0 on success - * - -EINVAL (-22) on failure - */ -int block_task(tid_t); - /** @brief Abort current task */ void NORETURN abort(void); diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index f63ae533..f972feba 100644 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -50,6 +50,8 @@ extern "C" { #define TASK_DEFAULT_FLAGS 0 #define TASK_FPU_INIT (1 << 0) #define TASK_FPU_USED (1 << 1) +#define TASK_TIMER_USED (1 << 2) +#define TASK_SWITCH_IN_PROGRESS (1 << 3) typedef int (*entry_point_t)(void*); typedef int (STDCALL *internal_entry_point_t)(void*); @@ -61,8 +63,12 @@ typedef struct task { tid_t id; /// Task status (INVALID, READY, RUNNING, ...) uint32_t status; + /// Additional status flags. For instance, to signalize the using of the FPU + uint32_t flags; /// Number of used time slices uint32_t time_slices; + /// timeout for a blocked task + uint64_t timeout; /// Usage in number of pages atomic_int32_t user_usage; /// Avoids concurrent access to the page directory @@ -73,8 +79,6 @@ typedef struct task { spinlock_t vma_lock; /// List of VMAs vma_t* vma_list; - /// Additional status flags. For instance, to signalize the using of the FPU - uint32_t flags; /// starting time/tick of the task uint64_t start_tick; /// Start address of the heap diff --git a/include/metalsvm/time.h b/include/metalsvm/time.h index aa47e47a..c20d059c 100644 --- a/include/metalsvm/time.h +++ b/include/metalsvm/time.h @@ -56,13 +56,13 @@ int sys_times(struct tms*, clock_t* clock); */ int timer_init(void); -/** @brief Blocking wait function - * - * This function does no busy-wait. +/** @brief Initialized a timer * * @param ticks Amount of ticks to wait + * @return + * - 0 on success */ -void timer_wait(unsigned int ticks); +int timer_wait(unsigned int ticks); /** @brief Returns the current number of ticks. * @return Current number of ticks diff --git a/kernel/tasks.c b/kernel/tasks.c index 95c4c1ed..5813e50a 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -47,8 +47,8 @@ * A task's id will be its position in this array. */ static task_t task_table[MAX_TASKS] = { \ - [0] = {0, TASK_RUNNING, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}, \ - [1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}}; + [0] = {0, TASK_IDLE, 0, 0, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0}, \ + [1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, 0, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0}}; static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT; DEFINE_PER_CORE(task_t*, current_task, task_table+0); @@ -82,15 +82,17 @@ int dump_scheduling_statistics(void) } int multitasking_init(void) { - if (BUILTIN_EXPECT(task_table[0].status == TASK_RUNNING, 1)) { - mailbox_wait_msg_init(&task_table[0].inbox); - memset(task_table[0].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS); - task_table[0].pgd = get_boot_pgd(); - task_table[0].flags = TASK_DEFAULT_FLAGS; - return 0; + if (BUILTIN_EXPECT(task_table[0].status != TASK_IDLE, 0)) { + kputs("Task 0 is not an idle task\n"); + return -ENOMEM; } - return -ENOMEM; + mailbox_wait_msg_init(&task_table[0].inbox); + memset(task_table[0].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS); + task_table[0].pgd = get_boot_pgd(); + task_table[0].flags = TASK_DEFAULT_FLAGS; + + return 0; } size_t get_idle_task(uint32_t id) @@ -100,13 +102,13 @@ size_t get_idle_task(uint32_t id) return -EINVAL; task_table[id].id = id; - task_table[id].time_slices = 0; task_table[id].status = TASK_IDLE; + task_table[id].flags = TASK_DEFAULT_FLAGS; + task_table[id].time_slices = 0; atomic_int32_set(&task_table[id].user_usage, 0); mailbox_wait_msg_init(&task_table[id].inbox); memset(task_table[id].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS); task_table[id].pgd = get_boot_pgd(); - task_table[id].flags = TASK_DEFAULT_FLAGS; current_task[id].var = task_table+id; return get_stack(id); @@ -192,17 +194,6 @@ void NORETURN abort(void) { do_exit(-1); } -/* - * @brief: if the task gets the first time slice, - * the table_lock is hold and have to be released. - */ -inline static void start_first_time_slice(void) -{ -#if MAX_CORES > 1 - spinlock_irqsave_unlock(&table_lock); -#endif -} - /** @brief Create a task with a specific entry point * * @param id Pointer to a tid_t struct were the id shall be set @@ -236,6 +227,8 @@ static int create_task(tid_t* id, internal_entry_point_t ep, void* arg) } task_table[i].id = i; + task_table[i].status = TASK_READY; + task_table[i].flags = TASK_DEFAULT_FLAGS; task_table[i].time_slices = 0; spinlock_init(&task_table[i].vma_lock); task_table[i].vma_list = NULL; @@ -248,11 +241,9 @@ static int create_task(tid_t* id, internal_entry_point_t ep, void* arg) ret = create_default_frame(task_table+i, ep, arg); - task_table[i].flags = TASK_DEFAULT_FLAGS; task_table[i].start_heap = 0; task_table[i].end_heap = 0; task_table[i].start_tick = get_clock_tick(); - task_table[i].status = TASK_READY; break; } } @@ -312,7 +303,7 @@ int sys_fork(void) mailbox_wait_msg_init(&task_table[i].inbox); memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS); task_table[i].outbox[parent_task->id] = &parent_task->inbox; - task_table[i].flags = parent_task->flags; + task_table[i].flags = parent_task->flags & ~TASK_SWITCH_IN_PROGRESS; memcpy(&(task_table[i].fpu), &(parent_task->fpu), sizeof(union fpu_state)); task_table[i].start_tick = get_clock_tick(); task_table[i].start_heap = 0; @@ -325,7 +316,13 @@ int sys_fork(void) // Leave the function without releasing the locks // because the locks are already released // by the parent task! - start_first_time_slice(); +#if MAX_CORES > 1 + task_t* old = per_core(old_task); + + if (old) + old->flags &= ~TASK_SWITCH_IN_PROGRESS; +#endif + irq_enable(); return 0; } @@ -359,8 +356,13 @@ static int STDCALL kernel_entry(void* args) { int ret; kernel_args_t* kernel_args = (kernel_args_t*) args; +#if MAX_CORES > 1 + task_t* old = per_core(old_task); - start_first_time_slice(); + if (old) + old->flags &= ~TASK_SWITCH_IN_PROGRESS; +#endif + irq_enable(); if (BUILTIN_EXPECT(!kernel_args, 0)) return -EINVAL; @@ -600,8 +602,13 @@ invalid: static int STDCALL user_entry(void* arg) { int ret; +#if MAX_CORES > 1 + task_t* old = per_core(old_task); - start_first_time_slice(); + if (old) + old->flags &= ~TASK_SWITCH_IN_PROGRESS; +#endif + irq_enable(); if (BUILTIN_EXPECT(!arg, 0)) return -EINVAL; @@ -754,7 +761,7 @@ tid_t wait(int32_t* result) if (BUILTIN_EXPECT(curr_task->status == TASK_IDLE, 0)) return -EINVAL; - mailbox_wait_msg_fetch(&curr_task->inbox, &tmp); + mailbox_wait_msg_fetch(&curr_task->inbox, &tmp, 0); if (result) *result = tmp.result; @@ -772,12 +779,9 @@ int wakeup_task(tid_t id) { int ret = -EINVAL; - /* avoid nested locking */ spinlock_irqsave_lock(&table_lock); - if (task_table[id].status != TASK_BLOCKED) { - kprintf("Task %d is not blocked!\n", id); - } else { + if (task_table[id].status == TASK_BLOCKED) { task_table[id].status = TASK_READY; ret = 0; } @@ -787,28 +791,6 @@ int wakeup_task(tid_t id) return ret; } -/** @brief Block a running or ready task. - * @param id The task's tid_t structure - * @return - * - 0 on success - * - -EINVAL (-22) on failure - */ -int block_task(tid_t id) -{ - int ret = -EINVAL; - - spinlock_irqsave_lock(&table_lock); - - if ((task_table[id].status == TASK_RUNNING) || (task_table[id].status == TASK_READY)) { - task_table[id].status = TASK_BLOCKED; - ret = 0; - } else kprintf("Unable to block task %d!\n", id); - - spinlock_irqsave_unlock(&table_lock); - - return ret; -} - /* * we use this struct to guarantee that the id * has its own cache line @@ -828,12 +810,13 @@ void scheduler(void) task_t* curr_task; uint32_t i; uint32_t new_id; + uint64_t current_tick; static last_id_t last_id = { 0 }; #if MAX_CORES > 1 spinlock_irqsave_lock(&table_lock); #endif - + current_tick = get_clock_tick(); orig_task = curr_task = per_core(current_task); /* increase the number of used time slices */ @@ -849,12 +832,29 @@ void scheduler(void) curr_task->flags &= ~TASK_FPU_USED; } - for(i=1, new_id=(last_id.id + 1) % MAX_TASKS; + for(i=0, new_id=(last_id.id + 1) % MAX_TASKS; istatus == TASK_RUNNING) + if (task_table[new_id].flags & TASK_TIMER_USED) { + if (task_table[new_id].status != TASK_BLOCKED) + task_table[new_id].flags &= ~TASK_TIMER_USED; + if ((task_table[new_id].status == TASK_BLOCKED) && (current_tick >= task_table[new_id].timeout)) { + task_table[new_id].flags &= ~TASK_TIMER_USED; + task_table[new_id].status = TASK_READY; + } + } + + if ((task_table[new_id].status == TASK_READY) && !(task_table[new_id].flags & TASK_SWITCH_IN_PROGRESS)) { + if (curr_task->status == TASK_RUNNING) { curr_task->status = TASK_READY; +#if MAX_CORES > 1 + curr_task->flags |= TASK_SWITCH_IN_PROGRESS; + per_core(old_task) = curr_task; +#endif + } +#if MAX_CORES > 1 + else per_core(old_task) = NULL; +#endif task_table[new_id].status = TASK_RUNNING; curr_task = per_core(current_task) = task_table+new_id; last_id.id = new_id; @@ -863,6 +863,10 @@ void scheduler(void) } } +#if MAX_CORES > 1 + per_core(old_task) = NULL; +#endif + if ((curr_task->status == TASK_RUNNING) || (curr_task->status == TASK_IDLE)) goto get_task_out; @@ -874,14 +878,19 @@ void scheduler(void) curr_task = per_core(current_task) = task_table+CORE_ID; get_task_out: - //kprintf("schedule %d on core %d\n", per_core(current_task)->id, smp_id()); - - if (curr_task != orig_task) - switch_task(new_id); - #if MAX_CORES > 1 spinlock_irqsave_unlock(&table_lock); #endif + + if (curr_task != orig_task) { + //kprintf("schedule from %d to %d on core %d\n", orig_task->id, curr_task->id, smp_id()); + switch_task(new_id); +#if MAX_CORES > 1 + orig_task= per_core(old_task); + if (orig_task) + orig_task->flags &= ~TASK_SWITCH_IN_PROGRESS; +#endif + } } void reschedule(void) diff --git a/kernel/tests.c b/kernel/tests.c index bced389b..989dfe51 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -44,14 +44,14 @@ static int consumer(void* arg) int i, m = 0; for(i=0; i<5; i++) { - sem_wait(&consuming); + sem_wait(&consuming, 0); kprintf("Consumer got %d\n", val); val = 0; sem_post(&producing); } for(i=0; i<5; i++) { - mailbox_int32_fetch(&mbox, &m); + mailbox_int32_fetch(&mbox, &m, 0); kprintf("Got mail %d\n", m); } @@ -64,7 +64,7 @@ static int producer(void* arg) int mail[5] = {1, 2, 3, 4, 5}; for(i=0; i<5; i++) { - sem_wait(&producing); + sem_wait(&producing, 0); kprintf("Produce value: current val %d\n", val); val = 42; sem_post(&consuming); diff --git a/lwip/src/arch/sys_arch.c b/lwip/src/arch/sys_arch.c index b9b2d7db..b46f0fd7 100644 --- a/lwip/src/arch/sys_arch.c +++ b/lwip/src/arch/sys_arch.c @@ -32,18 +32,22 @@ #define FALSE 0 #endif +#if SYS_LIGHTWEIGHT_PROT +#if MAX_CORES > 1 +static spinlock_irqsave_t lwprot_lock; +#endif +#endif + /** Returns the current time in milliseconds, * may be the same as sys_jiffies or at least based on it. */ -u32_t -sys_now(void) +u32_t sys_now(void) { - return (get_clock_tick() / TIMER_FREQ) * 1000; + return (get_clock_tick() / TIMER_FREQ) * 1000; } -u32_t -sys_jiffies(void) +u32_t sys_jiffies(void) { - return (get_clock_tick() / TIMER_FREQ) * 1000; + return (get_clock_tick() / TIMER_FREQ) * 1000; } #if !NO_SYS @@ -51,9 +55,13 @@ sys_jiffies(void) /* sys_init(): init needed system resources * Note: At the moment there are none */ -void -sys_init(void) +void sys_init(void) { +#if SYS_LIGHTWEIGHT_PROT +#if MAX_CORES > 1 + spinlock_irqsave_init(&lwprot_lock); +#endif +#endif } /** @@ -61,28 +69,24 @@ sys_init(void) * * @param ms number of milliseconds to sleep */ -void -sys_msleep(u32_t ms) +void sys_msleep(u32_t ms) { - if (ms > 0) { - sys_sem_t delaysem; - err_t err = sys_sem_new(&delaysem, 0); - if (err == ERR_OK) { - sys_arch_sem_wait(&delaysem, ms); - sys_sem_free(&delaysem); - } - } + if (ms * TIMER_FREQ / 1000 > 0) + timer_wait(ms * TIMER_FREQ / 1000); + else if (ms > 0) + udelay(ms * 1000); } /* sys_thread_new(): Spawns a new thread with given attributes as supported * Note: In MetalSVM this is realized as kernel tasks */ -sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, + int stacksize, int prio) { - tid_t tmp; + sys_thread_t tmp; - kprintf("Create LWIP task %s\n", name); create_kernel_task(&tmp, thread, arg); + kprintf("Created LWIP task %s with id %u\n", name, tmp); return tmp; } @@ -108,10 +112,10 @@ int sys_sem_valid(sys_sem_t* sem) /* sys_sem_new(): creates a new semaphre with given count. * This semaphore becomes valid */ -err_t sys_sem_new(sys_sem_t* sem,u8_t count) +err_t sys_sem_new(sys_sem_t* sem, u8_t count) { sem->valid = TRUE; - return sem_init(&sem->sem,count); + return sem_init(&sem->sem, count); } /* sys_sem_set_invalid(): this semapohore becomes invalid @@ -137,16 +141,11 @@ void sys_sem_signal(sys_sem_t* sem) u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) { int err; - if (!timeout) - return sem_wait(&sem->sem); - while (timeout) - { - err = sem_trywait(&sem->sem); - if (err != -1) - return err; - udelay(1000); - timeout--; - } + + err = sem_wait(&sem->sem, timeout); + if (!err) + return 0; + return SYS_ARCH_TIMEOUT; } @@ -164,16 +163,11 @@ int sys_mbox_valid(sys_mbox_t * mbox) */ u32_t sys_arch_mbox_fetch(sys_mbox_t * mbox, void **msg, u32_t timeout) { - if (!timeout) - return mailbox_ptr_fetch(&mbox->mailbox,msg); + int err; - while(timeout) - { - if (!mailbox_ptr_tryfetch(&mbox->mailbox,msg)) - return 0; - udelay(1000); - timeout--; - } + err = mailbox_ptr_fetch(&mbox->mailbox, msg, timeout); + if (!err) + return 0; return SYS_ARCH_TIMEOUT; } @@ -192,13 +186,13 @@ void sys_mbox_free(sys_mbox_t* mbox) */ u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void** msg) { - return mailbox_ptr_tryfetch(&mbox->mailbox,msg); + mailbox_ptr_tryfetch(&mbox->mailbox, msg); } /* sys_mbox_new(): create a new mailbox with a minimum size of "size" * */ -err_t sys_mbox_new(sys_mbox_t* mbox,int size) +err_t sys_mbox_new(sys_mbox_t* mbox, int size) { mbox->valid = TRUE; return mailbox_ptr_init(&mbox->mailbox); @@ -218,15 +212,19 @@ void sys_mbox_set_invalid(sys_mbox_t* mbox) */ err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) { - return mailbox_ptr_post(&mbox->mailbox,msg); + int err; + + err = mailbox_ptr_trypost(&mbox->mailbox, msg); + + return err; } /* sys_mbox_post(): post new data to the mailbox * */ -void sys_mbox_post(sys_mbox_t* mbox,void* msg) +void sys_mbox_post(sys_mbox_t* mbox, void* msg) { - mailbox_ptr_post(&mbox->mailbox,msg); + mailbox_ptr_post(&mbox->mailbox, msg); } /* sys_mutex_lock(): lock the given mutex @@ -235,7 +233,7 @@ void sys_mbox_post(sys_mbox_t* mbox,void* msg) */ void sys_mutex_lock(sys_mutex_t* mutex) { - sem_wait(mutex); + sem_wait(mutex, 0); } /* sys_mutex_unlock(): unlock the given mutex @@ -251,23 +249,22 @@ void sys_mutex_unlock(sys_mutex_t* mutex) */ err_t sys_mutex_new(sys_mutex_t * mutex) { - sem_init(mutex,1); + sem_init(mutex, 1); return 0; } #if SYS_LIGHTWEIGHT_PROT #if MAX_CORES > 1 -static spinlock_irqsave_t lwprot_lock = SPINLOCK_IRQSAVE_INIT; - sys_prot_t sys_arch_protect(void) { - spinlock_irqsave_lock(&lwprot_lock); - return 0; + spinlock_irqsave_lock(&lwprot_lock); + return 0; } void sys_arch_unprotect(sys_prot_t pval) { - spinlock_irqsave_unlock(&lwprot_lock); + LWIP_UNUSED_ARG(pval); + spinlock_irqsave_unlock(&lwprot_lock); } #endif #endif From 6d08dbcf72e2ae3493df41963bd7c684fda10208 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 6 Aug 2011 07:24:21 -0700 Subject: [PATCH 10/11] minor changes to support the new semaphore interface --- drivers/net/mmnif.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/mmnif.c b/drivers/net/mmnif.c index d2dbdece..18c126d2 100644 --- a/drivers/net/mmnif.c +++ b/drivers/net/mmnif.c @@ -540,7 +540,7 @@ __inline void mmnif_lock_rx_hdr(int dest_ip) #else if(disable_locking) return; mm_rx_buffer_t* hdr = (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size; - sem_wait(&hdr->lock); + sem_wait(&hdr->lock, 0); #endif } /* mmnif_unlock_rx_hdr(): unlock the header @@ -879,7 +879,7 @@ err_t mmnif_init(struct netif* netif) */ sem_init(&mmnif->com_poll,1); - sem_wait(&mmnif->com_poll); + sem_wait(&mmnif->com_poll,0); /* inform via interrupt should be the dafault */ @@ -1113,7 +1113,7 @@ static int mmnif_wait(struct netif* netif, uint32_t poll, int budget) } else { - mailbox_ptr_fetch(&(mmnif->mbox), (void**) &p); + mailbox_ptr_fetch(&(mmnif->mbox), (void**) &p,0); } /* if there is data, pass it up to the lwip @@ -1174,7 +1174,7 @@ int mmnif_poll(void* e) if (!no_irq) { - sem_wait(&mmnif->com_poll); + sem_wait(&mmnif->com_poll,0); } /*run while driver is up*/ @@ -1196,7 +1196,7 @@ int mmnif_poll(void* e) #ifdef DEBUG_MMNIF DEBUGPRINTF("mmnif_poll(): heuristical interrupts enabled\n"); #endif - sem_wait(&mmnif->com_poll); + sem_wait(&mmnif->com_poll,0); mmnif->stats.pll_empty = 1; } } From 40d3763d4cec1ba8addc0cae586ebe37ecd37cdc Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 6 Aug 2011 07:27:14 -0700 Subject: [PATCH 11/11] remove typo --- drivers/net/rckemac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index cd3409e9..1c8ae09d 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -276,7 +276,7 @@ static void rckemacif_input(struct netif* netif, struct pbuf* p) #endif /* PPPOE_SUPPORT */ /* full packet send to tcpip_thread to process */ if (mynetif->input(p, mynetif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_input: IP input error\n")); + LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_input: IP input error\n")); pbuf_free(p); } break;