📄 simschedulerbasicp.nc
字号:
/*
* "Copyright (c) 2005 Stanford University. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose, without fee, and without written
* agreement is hereby granted, provided that the above copyright
* notice, the following two paragraphs and the author appear in all
* copies of this software.
*
* IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
* PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY
* HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS."
*/
/**
*
* SimSchedulerBasic implements the default TinyOS scheduler sequence
* (documented in TEP 106) for the TOSSIM platform. Its major departure
* from the standard TinyOS scheduler is that tasks are executed
* within TOSSIM events. This introduces task latency.
*
* @author Philip Levis
* @author Cory Sharp
* @date August 19 2005
*/
#include <sim_event_queue.h>
module SimSchedulerBasicP {
provides interface Scheduler;
provides interface TaskBasic[uint8_t id];
}
implementation
{
enum
{
NUM_TASKS = uniqueCount("TinySchedulerC.TaskBasic"),
NO_TASK = 255,
};
uint8_t m_head;
uint8_t m_tail;
uint8_t m_next[NUM_TASKS];
/* This simulation state is kept on a per-node basis.
Better to take advantage of nesC's automatic state replication
than try to do it ourselves. */
bool sim_scheduler_event_pending = FALSE;
sim_event_t sim_scheduler_event;
int sim_config_task_latency() {return 100;}
/* Only enqueue the event for execution if it is
not already enqueued. If there are more tasks in the
queue, the event will re-enqueue itself (see the handle
function). */
void sim_scheduler_submit_event() {
if (sim_scheduler_event_pending == FALSE) {
sim_scheduler_event.time = sim_time() + sim_config_task_latency();
sim_queue_insert(&sim_scheduler_event);
sim_scheduler_event_pending = TRUE;
}
}
void sim_scheduler_event_handle(sim_event_t* e) {
sim_scheduler_event_pending = FALSE;
// If we successfully executed a task, re-enqueue the event. This
// will always succeed, as sim_scheduler_event_pending was just
// set to be false. Note that this means there will be an extra
// execution (on an empty task queue). We could optimize this
// away, but this code is cleaner, and more accurately reflects
// the real TinyOS main loop.
if (call Scheduler.runNextTask()) {
sim_scheduler_submit_event();
}
}
/* Initialize a scheduler event. This should only be done
* once, when the scheduler is initialized. */
void sim_scheduler_event_init(sim_event_t* e) {
e->mote = sim_node();
e->force = 0;
e->data = NULL;
e->handle = sim_scheduler_event_handle;
e->cleanup = sim_queue_cleanup_none;
}
// Helper functions (internal functions) intentionally do not have atomic
// sections. It is left as the duty of the exported interface functions to
// manage atomicity to minimize chances for binary code bloat.
// move the head forward
// if the head is at the end, mark the tail at the end, too
// mark the task as not in the queue
uint8_t popTask()
{
if( m_head != NO_TASK )
{
uint8_t id = m_head;
m_head = m_next[m_head];
if( m_head == NO_TASK )
{
m_tail = NO_TASK;
}
m_next[id] = NO_TASK;
return id;
}
else
{
return NO_TASK;
}
}
bool isWaiting( uint8_t id )
{
return (m_next[id] != NO_TASK) || (m_tail == id);
}
bool pushTask( uint8_t id )
{
if( !isWaiting(id) )
{
if( m_head == NO_TASK )
{
m_head = id;
m_tail = id;
}
else
{
m_next[m_tail] = id;
m_tail = id;
}
return TRUE;
}
else
{
return FALSE;
}
}
command void Scheduler.init()
{
dbg("Scheduler", "Initializing scheduler.\n");
atomic
{
memset( m_next, NO_TASK, sizeof(m_next) );
m_head = NO_TASK;
m_tail = NO_TASK;
sim_scheduler_event_pending = FALSE;
sim_scheduler_event_init(&sim_scheduler_event);
}
}
command bool Scheduler.runNextTask()
{
uint8_t nextTask;
atomic
{
nextTask = popTask();
if( nextTask == NO_TASK )
{
dbg("Scheduler", "Told to run next task, but no task to run.\n");
return FALSE;
}
}
dbg("Scheduler", "Running task %hhu.\n", nextTask);
signal TaskBasic.runTask[nextTask]();
return TRUE;
}
command void Scheduler.taskLoop() {
// This should never run.
}
/**
* Return SUCCESS if the post succeeded, EBUSY if it was already posted.
*/
async command error_t TaskBasic.postTask[uint8_t id]()
{
error_t result;
atomic {
result = pushTask(id) ? SUCCESS : EBUSY;
}
if (result == SUCCESS) {
dbg("Scheduler", "Posting task %hhu.\n", id);
sim_scheduler_submit_event();
}
else {
dbg("Scheduler", "Posting task %hhu, but already posted.\n", id);
}
return result;
}
default event void TaskBasic.runTask[uint8_t id]()
{
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -