⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msched.c

📁 MANTIS是由科罗拉多大学开发的传感器网络嵌入式操作系统。 这是mantis的0.9.5版本的源码。
💻 C
📖 第 1 页 / 共 2 页
字号:
//  This file is part of MANTIS OS, Operating System//  See http://mantis.cs.colorado.edu/////  Copyright (C) 2003,2004,2005 University of Colorado, Boulder////  This program is free software; you can redistribute it and/or//  modify it under the terms of the mos license (see file LICENSE)#include "plat_dep.h"#include "mos.h"#include "msched.h"#include "tlist.h"#include "mem.h"#include "led.h" //TODO: remove when done debugging#include "clock.h"#include "context_switch.h" //provides asm for saving/switching/restoring stack#include "plat_clock.h"#include "mutex.h"#ifdef DEBUG_MEMORY		// from msched.h#include <avr/pgmspace.h>#include "printf.h"const char sThreadRow[] ARCH_PROGMEM = "thread %d: sp %x, stack %x, size %d, unused %d, state %C, priority %C\n";const char sThreadTot[] ARCH_PROGMEM = "%C threads, %d stack allocated, %d stack used\n";const char sStackOver[] ARCH_PROGMEM = "stack %C has overflowed\n";const char sStackFull[] ARCH_PROGMEM = "stack %C looks full\n";#endifstatic uint8_t running;    // flag for the state of the scheduleruint16_t last_sleep_time; // time the processor was sleeping (msecs)static thread_t *wakeup_front;static thread_t threads[MAX_THREADS]; // Our array of system thread data structsthread_t *_current_thread;      // The currently running threadstatic thread_t *sleep_thread;      // The currently sleeping threadstatic tlist_t readyQ[NUM_PRIORITIES]; // Ready Queue with prioritiesstatic tlist_t sleepQ;                 // Sleep Queueextern uint8_t _end; //linker-provided symbol for end of memory/* WARNING: You can not use local variables in the dispatcher because they mess   with the calling functions stack.  So we use these */ static uint8_t d_index;/** @brief Heart of the scheduler. * * Saves the current thread's context and then restores a new * thread. This function implements both context switching and * the actual scheduling algorithm. * NOTE: the naked attribute tells the compiler not to add any * prologue or epilogue code. */void __attribute__((naked)) dispatcher(void);void idle_loop(void);void start_wrapper(void);//static void mos_thread_wakeup_sleep (void);static inline void mos_thread_wakeup(uint16_t sleep_time);static inline void mos_thread_wakeup_noints(uint16_t sleep_time,					    handle_t int_handle);void mos_single_threaded(void){   //TIMSK &= ~(1 << TSLICE_INT); //turn off time slice   DISABLE_TSLICE_TIMER();   //TSLICE_OCR = 0xffff;   //SET_TSLICE_OCR_VALUE(0xffff);}void mos_multi_threaded(void){   //uint16_t sleep_time = 0;   //handle_t int_handle = mos_disable_ints ();   //sleep_time += (10 * TSLICE_CNT) / (CLOCK_SPEED_1024 / 100);   //sleep_time += (10 * TSLICE_TIMER_VALUE) / (CLOCK_SPEED_1024 / 100);   //TSLICE_OCR = TIMESLICE_20_MS;   //SET_TSLICE_OCR_VALUE(TIMESLICE_20_MS);      //TSLICE_CNT = 0;   //SET_TSLICE_TIMER_VALUE(0);      //TIMSK |= (1 << TSLICE_INT); //turn on time slice   ENABLE_TSLICE_TIMER();   //mos_enable_ints(int_handle);   //mos_thread_wakeup(sleep_time);}void sched_init(void){   uint8_t i;   DISABLE_INTS();      // Init the memory system for our stacks.    mem_init(&_end, HEAP_TOP - ((int)&_end));      // init the thread table   for(i = 0; i < MAX_THREADS; i++) {      threads[i].sp = 0;      threads[i].state = EMPTY;      threads[i].suspend_state = SUSPEND_STATE_SLEEP;      threads[i].priority = 0;      threads[i].next = NULL;   }   // Allocate space for the kernel thread, which is currently running.    _current_thread = &threads[0];   _current_thread->state = RUNNING;     _current_thread->priority = PRIORITY_IDLE;   #ifdef DEBUG_MEMORY   // For debugging, fill these fields in for the kernel thread, too.   _current_thread->stack = (uint8_t *)HEAP_TOP;   _current_thread->stackSize = IDLE_STACK_SIZE;      // Flag the block for debugging, normally memory manager does this.   // Be careful not to write over our current stack.   stackval_t *j = (stackval_t *)HEAP_TOP;   stackval_t *sp;     GET_SP(sp);      for(; j < sp; j++)      *j = 0xEF;#endif   //Init the ready queue   for(i = 0; i < NUM_PRIORITIES; i++)      mos_tlist_init(&readyQ[i]);}void mos_sched_start(void){   running = TRUE;   //initialize the hardware timers which control   //sleeping and timeslicing   kernel_timer_init();   sleep_timer_init();   // Once interrupts are enabled here, the sheduler will start to schedule   // threads and do time slicing.   ENABLE_INTS();   //Start executing the first thread   dispatcher();   // On to the idle loop   idle_loop();}void mos_thread_suspend_state(uint8_t state){   if(state >= SUSPEND_STATE_MAX)      state = SUSPEND_STATE_IDLE;   handle_t int_handle = mos_disable_ints();    _current_thread->next = NULL;   _current_thread->state = BLOCKED; // Update the thread state   // store the old suspend state in the sleep time,   // which we aren't using   _current_thread->st = (uint32_t)_current_thread->suspend_state;   _current_thread->suspend_state = state;   mos_thread_wakeup_noints((10 * TSLICE_TIMER_VALUE) / (CLOCK_SPEED_1024 / 100),			    int_handle);}void mos_thread_suspend_noints(handle_t int_handle){   _current_thread->next = NULL;   _current_thread->state = BLOCKED; // Update the thread state   // store the old suspend state in the sleep time,   // which we aren't using   _current_thread->st = (uint32_t)_current_thread->suspend_state;   _current_thread->suspend_state = SUSPEND_STATE_IDLE;   mos_thread_wakeup_noints((10 * TSLICE_TIMER_VALUE) / (CLOCK_SPEED_1024 / 100),			    int_handle);}void mos_thread_resume(thread_t *thread){   handle_t int_handle;   int_handle = mos_disable_ints();      // put given thread onto the ready Queue if it was blocked.   if(thread->state == BLOCKED) {      mos_tlist_add(&readyQ[thread->priority], thread);      thread->state = READY;      thread->suspend_state = (uint8_t)thread->st;   }   mos_thread_wakeup_noints((10 * TSLICE_TIMER_VALUE) / (CLOCK_SPEED_1024 / 100),   		    int_handle);}void mos_thread_resume_noints(thread_t *thread, handle_t int_handle){   // put given thread onto the ready Queue if it was blocked.   if(thread->state == BLOCKED) {      mos_tlist_add(&readyQ[thread->priority], thread);      thread->state = READY;      thread->suspend_state = (uint8_t)thread->st;   }   mos_thread_wakeup_noints((10 * TSLICE_TIMER_VALUE) / (CLOCK_SPEED_1024 / 100),   		    int_handle);}void mos_thread_resume_noints_nodispatch(thread_t *thread, handle_t int_handle){   // put given thread onto the ready Queue if it was blocked.   if(thread->state == BLOCKED) {      mos_tlist_add(&readyQ[thread->priority], thread);      thread->state = READY;      thread->suspend_state = (uint8_t)thread->st;   }   }void mos_thread_sleep(uint32_t sleeptime){   handle_t int_handle;   if(sleeptime < 40)      sleeptime = 40;      int_handle = mos_disable_ints();     _current_thread->state = SLEEPING; // Update the thread state   _current_thread->st = sleeptime; // Update the sleeptime   mos_tlist_ordadd(&sleepQ, _current_thread);   mos_thread_wakeup_noints((10 * TSLICE_TIMER_VALUE) / (CLOCK_SPEED_1024 / 100),			    int_handle);}/** @brief wake up a thread along with decrementing the sleep time * this function wakes sleeping threads if necessary, otherwise just * decrements the sleep time of the head of the list. * @param down_time ammount of time passed since last sleeping */static inline void mos_thread_wakeup(uint16_t sleep_time){   //Adjust the sleepQ with the times that has already expired.   mos_tlist_adjustst(&sleepQ, sleep_time);      //get the first thread in the sleep queue   wakeup_front = mos_tlist_head(&sleepQ);   //loop through the sleep queue   while((wakeup_front != NULL) && (wakeup_front->st == 0)) {      //remove the thread if sleep time is 0      sleep_thread = mos_tlist_remove(&sleepQ);      sleep_thread->state = READY; // Update the thread state      //add thread to ready queue      mos_tlist_add(&readyQ[sleep_thread->priority], sleep_thread);      wakeup_front = mos_tlist_head(&sleepQ);   }   dispatcher();   // do the context switch.}static inline void mos_thread_wakeup_noints(uint16_t sleep_time,					    handle_t int_handle){   //Adjust the sleepQ with the times that has already expired.   mos_tlist_adjustst(&sleepQ, sleep_time);      //get the first thread in the sleep queue   wakeup_front = mos_tlist_head(&sleepQ);   //loop through the sleep queue   while((wakeup_front != NULL) && (wakeup_front->st == 0)) {      //remove the thread if sleep time is 0      sleep_thread = mos_tlist_remove(&sleepQ);      sleep_thread->state = READY; // Update the thread state      //add thread to ready queue      mos_tlist_add(&readyQ[sleep_thread->priority], sleep_thread);      wakeup_front = mos_tlist_head(&sleepQ);   }   mos_enable_ints(int_handle);      dispatcher();   // do the context switch.}/** @brief Real dispatcher function * * Doxygen doesn't seem to like gcc attributes */void __attribute__((naked)) dispatcher(void){   // Prologue: Saves the current state.   // All registers go onto current stack and then the stack is saved   running = FALSE;   PUSH_THREAD_STACK();   //stop timeslicing during the context switch, but enable interrupts to   //service any pending io interrupts   //ENABLE_INTS();   //asm volatile("nop\n");   //DISABLE_INTS();      // Only change the thread's state if it was running, not blocked   if(_current_thread->state == RUNNING) {      _current_thread->state = READY;      mos_tlist_add(&readyQ[_current_thread->priority], _current_thread);   }      // Now bring up the new thread   // idle thread's existence guarantees we'll get something   for(d_index = 0; d_index < NUM_PRIORITIES; d_index++){      _current_thread = mos_tlist_remove(&readyQ[d_index]);      if(_current_thread != NULL)	 break;   }   _current_thread->state = RUNNING;   //ENABLE_INTS();   //asm volatile("nop\n");   //DISABLE_INTS();      POP_THREAD_STACK();   running = TRUE;      // return must be explicit because naked functions don't have one   asm volatile("ret\n");}/** @brief set timer0 and go to sleep for x ammount of ms * @param time ammount of time to sleep the kernel for in ms */static inline void kernel_sleep(uint8_t time){   SET_SLEEP_TIMER_VALUE(0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -