diff --git a/bios.c b/bios.c index 4ce7913..432253c 100644 --- a/bios.c +++ b/bios.c @@ -16,7 +16,7 @@ #include "util.h" #include "bios.h" -/* +/* Implementation of bios.h API diff --git a/bios_example1 b/bios_example1 new file mode 100644 index 0000000..affe003 Binary files /dev/null and b/bios_example1 differ diff --git a/bios_example2 b/bios_example2 new file mode 100644 index 0000000..5af981f Binary files /dev/null and b/bios_example2 differ diff --git a/bios_example3 b/bios_example3 new file mode 100644 index 0000000..fbb6fd0 Binary files /dev/null and b/bios_example3 differ diff --git a/bios_example4 b/bios_example4 new file mode 100644 index 0000000..32bdd1e Binary files /dev/null and b/bios_example4 differ diff --git a/bios_example5 b/bios_example5 new file mode 100644 index 0000000..9b125ed Binary files /dev/null and b/bios_example5 differ diff --git a/kernel_dev.c b/kernel_dev.c index 2002d89..f9af425 100644 --- a/kernel_dev.c +++ b/kernel_dev.c @@ -83,7 +83,6 @@ serial_dcb_t serial_dcb[MAX_TERMINALS]; void serial_rx_handler() { int pre = preempt_off; - /* We do not know which terminal is ready, so we must signal them all ! @@ -100,13 +99,14 @@ void serial_rx_handler() /* Read from the device, sleeping if needed. */ + int serial_read(void* dev, char *buf, unsigned int size) { serial_dcb_t* dcb = (serial_dcb_t*)dev; preempt_off; /* Stop preemption */ Mutex_Lock(& dcb->spinlock); - + uint count = 0; while(countspinlock, &dcb->rx_ready); @@ -146,16 +147,16 @@ void serial_tx_handler() int serial_write(void* dev, const char* buf, unsigned int size) { serial_dcb_t* dcb = (serial_dcb_t*)dev; - unsigned int count = 0; while(count < size) { int success = bios_write_serial(dcb->devno, buf[count] ); if(success) { count++; + flag_write = 1; } else if(count==0) - { + { yield(); } else diff --git a/kernel_dev.h b/kernel_dev.h index e7befe1..315d904 100644 --- a/kernel_dev.h +++ b/kernel_dev.h @@ -33,7 +33,6 @@ @{ */ - /** @brief The device-specific file operations table. diff --git a/kernel_init.c b/kernel_init.c index 53357cd..dad5f7c 100644 --- a/kernel_init.c +++ b/kernel_init.c @@ -39,7 +39,7 @@ void boot_tinyos_kernel() initialize_devices(); initialize_files(); initialize_scheduler(); - + /* The boot task is executed normally! */ if(Exec(boot_rec.init_task, boot_rec.argl, boot_rec.args)!=1) FATAL("The init process does not have PID==1"); diff --git a/kernel_sched.c b/kernel_sched.c index 858aa32..853e3f6 100644 --- a/kernel_sched.c +++ b/kernel_sched.c @@ -144,9 +144,10 @@ TCB* spawn_thread(PCB* pcb, void (*func)()) TCB* tcb = (TCB*) allocate_thread(THREAD_SIZE); /* Set the owner */ - tcb->owner_pcb = pcb; - + tcb->owner_pcb = pcb; /* Initialize the other attributes */ + tcb->priority = PRIORITY_INIT; //jv + tcb->alarmed = NOT_ALARMED; tcb->type = NORMAL_THREAD; tcb->state = INIT; tcb->phase = CTX_CLEAN; @@ -218,13 +219,14 @@ CCB cctx[MAX_CORES]; */ -rlnode SCHED; /* The scheduler queue */ +//rlnode SCHED; /* The scheduler queue */ Mutex sched_spinlock = MUTEX_INIT; /* spinlock for scheduler queue */ - /* Interrupt handler for ALARM */ void yield_handler() -{ +{ + TCB* current = CURTHREAD; + current->alarmed = ALARMED; yield(); } @@ -242,8 +244,9 @@ void ici_handler() void sched_queue_add(TCB* tcb) { /* Insert at the end of the scheduling list */ - Mutex_Lock(& sched_spinlock); - rlist_push_back(& SCHED, & tcb->sched_node); + Mutex_Lock(& sched_spinlock); //jv + int prty = tcb->priority; + rlist_push_back( multilevel_sched + prty, & tcb->sched_node ); Mutex_Unlock(& sched_spinlock); /* Restart possibly halted cores */ @@ -256,9 +259,15 @@ void sched_queue_add(TCB* tcb) return it. Return NULL if the list is empty. */ TCB* sched_queue_select() -{ - Mutex_Lock(& sched_spinlock); - rlnode * sel = rlist_pop_front(& SCHED); +{ + Mutex_Lock(& sched_spinlock); + int level_cnt=1; //jv + rlnode* list_level = multilevel_sched; + while( level_cnt < SCHED_LEVELS && is_rlist_empty(list_level) ){ + level_cnt++; + list_level++; + } + rlnode * sel = rlist_pop_front(list_level); Mutex_Unlock(& sched_spinlock); return sel->tcb; /* When the list is empty, this is NULL */ @@ -355,6 +364,32 @@ void yield() assert(0); /* It should not be READY or EXITED ! */ } Mutex_Unlock(& current->state_spinlock); + + /** PRIORITY COMPUTING */ + //jv + /** Only for non-base priorities + -- When quantum completes, priority decreases by 1 */ + if( current->type != IDLE_THREAD && current->alarmed == ALARMED + && current->priority < PRIORITY_MIN ) + { + current->priority++; /** Decrease priority of current thread*/ + current->alarmed = NOT_ALARMED; + } + + /** When current thread is I/O bound , priority increases by 1 + -- Check if flag is "raised" from 'serial_read' in kernel_dev.c */ + + if( (current->type != IDLE_THREAD && current->priority > PRIORITY_MAX + && current->alarmed == NOT_ALARMED) + && (flag_read || flag_write) ) + { + current->priority--; + } + flag_read = 0; + flag_write = 0; + + fprintf(stderr,"list 1: %d - list 2: %d - list 3: %d\n", + rlist_len(multilevel_sched),rlist_len(multilevel_sched+1),rlist_len(multilevel_sched+2)); /* Get next */ TCB* next = sched_queue_select(); @@ -460,8 +495,13 @@ static void idle_thread() Initialize the scheduler queue */ void initialize_scheduler() -{ - rlnode_init(&SCHED, NULL); +{ + int i; + rlnode* level; //jv + for (i=0;iidle_thread.type = IDLE_THREAD; curcore->idle_thread.state = RUNNING; curcore->idle_thread.phase = CTX_DIRTY; + curcore->idle_thread.priority = PRIORITY_INIT; //jv + curcore->idle_thread.alarmed = NOT_ALARMED; curcore->idle_thread.state_spinlock = MUTEX_INIT; rlnode_init(& curcore->idle_thread.sched_node, & curcore->idle_thread); diff --git a/kernel_sched.h b/kernel_sched.h index f901741..8a860d8 100644 --- a/kernel_sched.h +++ b/kernel_sched.h @@ -68,12 +68,28 @@ typedef enum { An object of this type is associated to every thread. In this object are stored all the metadata that relate to the thread. */ + +int flag_read; +int flag_write; +#define SCHED_LEVELS 3 +#define PRIORITY_MIN (SCHED_LEVELS-1) +#define PRIORITY_MAX 0 +#define PRIORITY_INIT 1 +#define NOT_ALARMED 0 +#define ALARMED 1 + typedef struct thread_control_block { PCB* owner_pcb; /**< This is null for a free TCB */ ucontext_t context; /**< The thread context */ + int priority; /**< Priority of thread in the scheduler + 0 for highest priority + SCHED_LEVELS-1 for lowest >> */ //jv + int alarmed; /** Used in 'yield' when called from 'yield_handler' + after ALARM interrupt */ + #ifndef NVALGRIND unsigned valgrind_stack_id; /**< This is useful in order to register the thread stack to valgrind */ #endif @@ -107,6 +123,9 @@ typedef struct thread_control_block * ************************/ +/** Multilevel Feedback Queues with each queue implemented with rlnode list */ + //jv +rlnode multilevel_sched[SCHED_LEVELS]; /** @brief Core control block. diff --git a/mtask b/mtask new file mode 100644 index 0000000..ab3e539 Binary files /dev/null and b/mtask differ diff --git a/terminal b/terminal new file mode 100644 index 0000000..71439a7 Binary files /dev/null and b/terminal differ diff --git a/test_example b/test_example new file mode 100644 index 0000000..d87cca4 Binary files /dev/null and b/test_example differ diff --git a/test_util b/test_util new file mode 100644 index 0000000..7b1a2bb Binary files /dev/null and b/test_util differ diff --git a/tinyos_shell b/tinyos_shell new file mode 100644 index 0000000..a730430 Binary files /dev/null and b/tinyos_shell differ diff --git a/validate_api b/validate_api new file mode 100644 index 0000000..bb2d2b3 Binary files /dev/null and b/validate_api differ