[Tinyos-2-commits] CVS: tinyos-2.x/doc/txt tep106.txt, 1.1.2.5,
1.1.2.6 tep107.txt, 1.1.2.7, 1.1.2.8
Phil Levis
scipio at users.sourceforge.net
Fri Jun 9 09:51:47 PDT 2006
Update of /cvsroot/tinyos/tinyos-2.x/doc/txt
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv2904
Modified Files:
Tag: tinyos-2_0_devel-BRANCH
tep106.txt tep107.txt
Log Message:
Changed code formatting. Removed a redundant paragraph on task
semantics.
Index: tep106.txt
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/doc/txt/Attic/tep106.txt,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -C2 -d -r1.1.2.5 -r1.1.2.6
*** tep106.txt 18 May 2006 23:08:14 -0000 1.1.2.5
--- tep106.txt 9 Jun 2006 16:51:45 -0000 1.1.2.6
***************
*** 33,37 ****
TinyOS has two basic computational abstractions: asynchronous events
! and tasks. Prior versions of TinyOS provided a single type of task --
parameter free -- and only a FIFO scheduling policy. While changing
the latter was possible, the incorporation of tasks into the nesC
--- 33,37 ----
TinyOS has two basic computational abstractions: asynchronous events
! and tasks. Early versions of TinyOS provided a single type of task --
parameter free -- and only a FIFO scheduling policy. While changing
the latter was possible, the incorporation of tasks into the nesC
***************
*** 40,44 ****
to be presented as an interface enables extending the classes of tasks
available. TinyOS 2.0 takes both approaches, and this memo documents
! the structure of how it does so.
2. Tasks and the Scheduler in TinyOS 1.x
--- 40,45 ----
to be presented as an interface enables extending the classes of tasks
available. TinyOS 2.0 takes both approaches, and this memo documents
! the structure of how it does so as well as a simple mechanism that
! greatly increases system dependability.
2. Tasks and the Scheduler in TinyOS 1.x
***************
*** 53,65 ****
In TinyOS 1.x, the nesC language supports tasks through two
! mechanisms, ``task`` declarations and ``post`` expressions:
! | ``task void computeTask() {``
! | ``// Code here``
! | ``}``
! and
! | ``result_t rval = post computeTask();``
--- 54,66 ----
In TinyOS 1.x, the nesC language supports tasks through two
! mechanisms, ``task`` declarations and ``post`` expressions::
! task void computeTask() {
! // Code here
! }
! and::
! result_t rval = post computeTask();
***************
*** 84,92 ****
elements, the ``post`` returns fail. This model has several issues:
! 1) Some components do not have a reasonable response to a failed ``post``
2) As a given task can be posted multiple times, it can consume more than one element in the buffer
3) All tasks from all components share a single resource: one misbehaving component can cause other's posts to fail
-
Fundamentally, in order for a component A to repost a task after post
failure, another component B must call a function on it (either a
--- 85,92 ----
elements, the ``post`` returns fail. This model has several issues:
! 1) Some components do not have a reasonable response to a failed post
2) As a given task can be posted multiple times, it can consume more than one element in the buffer
3) All tasks from all components share a single resource: one misbehaving component can cause other's posts to fail
Fundamentally, in order for a component A to repost a task after post
failure, another component B must call a function on it (either a
***************
*** 113,117 ****
application component does not try to send another packet until it
knows the one it is sending completes (so it can re-use the
! buffer). As the ``sendDone()`` event was lost, this will never occur,
and the application stops sending network traffic.
--- 113,117 ----
application component does not try to send another packet until it
knows the one it is sending completes (so it can re-use the
! buffer). As the ``sendDone()`` event was lost, this does not occur,
and the application stops sending network traffic.
***************
*** 120,123 ****
--- 120,126 ----
this violates the sync/async boundary, but the justification is that
a *possible* rare race condition is better than *certain* failure.
+ Another solution would be to use an interrupt source to periodically
+ retry posting the task; while this does not break the sync/async
+ boundary, until the post succeeds the system cannot send packets.
The TinyOS 1.x model prevents it from doing any better.
***************
*** 125,141 ****
====================================================================
- TinyOS 2.x takes the position that the basic use case of tasks should
- remain simple and easy to use, but that it should be possible to
- introduce new kinds of tasks beyond the basic use case. TinyOS
- actualizes this by keeping ``post`` and ``task`` for the basic case,
- and introducing task interfaces for additional ones.
-
The semantics of tasks in TinyOS 2.x are different than those in 1.x.
This change is based on experiences with the limitations and run time
errors that the 1.x model introduces. **In TinyOS 2.x, a basic post will
! only fail if the task has already been posted and has not started
! execution.** A task can always run, but can only have one outstanding
! post at any time. If a component needs to post task several times,
! then the end of the task logic can repost itself as need be.
These semantics prevent several problems, such as the inability to
--- 128,156 ----
====================================================================
The semantics of tasks in TinyOS 2.x are different than those in 1.x.
This change is based on experiences with the limitations and run time
errors that the 1.x model introduces. **In TinyOS 2.x, a basic post will
! only fail if and only if the task has already been posted and has not
! started execution.** A task can always run, but can only have one
! outstanding post at any time.
!
! 2.x achieves these semantics by allocating one
! byte of state per task (the assumption is that there will be fewer than 255
! tasks in the system). While a very large number of tasks could make
! this overhead noticable, it is not significant in practice.
! If a component needs to post a task several times, then the end of
! the task logic can repost itself as need be.
!
! For example, one can do this::
!
! post processTask();
! ...
! task void processTask() {
! // do work
! if (moreToProcess) {
! post processTask();
! }
! }
!
These semantics prevent several problems, such as the inability to
***************
*** 144,157 ****
allocation by components that post a task many times.
Task interfaces allow users to extend the syntax and semantics of
! tasks. Generally, a task interface has an ``async`` command, ``post``,
and an event, ``run``. The exact signature of these functions are
up to the interface. For example, a task interface that allows a task
! to take an integer parameter could look like this:
! | ``interface TaskParameter {``
! | ``async error_t command postTask(uint16_t param);``
! | ``event void runTask(uint16_t param);``
! | ``}``
Using this task interface, a component could post a task with a
--- 159,178 ----
allocation by components that post a task many times.
+ TinyOS 2.x takes the position that the basic use case of tasks should
+ remain simple and easy to use, but that it should be possible to
+ introduce new kinds of tasks beyond the basic use case. TinyOS
+ achieves this by keeping ``post`` and ``task`` for the basic case,
+ and introducing task interfaces for additional ones.
+
Task interfaces allow users to extend the syntax and semantics of
! tasks. Generally, a task interface has an ``async`` command, post ,
and an event, ``run``. The exact signature of these functions are
up to the interface. For example, a task interface that allows a task
! to take an integer parameter could look like this::
! interface TaskParameter {
! async error_t command postTask(uint16_t param);
! event void runTask(uint16_t param);
! }
Using this task interface, a component could post a task with a
***************
*** 167,192 ****
call TaskParameter.postTask(34);
...
! event void TaskParameter.runTask(uint15_t param) {
...
}
! The semantics of tasks in TinyOS 2.x are different than those in 1.x.
! This change is based on experiences with the limitations and run time
! errors that the 1.x model introduces. **In TinyOS 2.x, a basic post will
! only fail if the task has already been posted and has not started
! execution.** A task can always run, but can only have one outstanding
! post at any time. 2.x achieves these semantics by allocating a single
! byte of state per task. While a very large number of tasks could make
! this overhead noticable, it is not significant in practice.
! If a component needs to post a task several times, then the end of
! the task logic can repost itself as need be.
!
! For example, one can do this::
! param = 34;
! post parameterTask();
...
task void parameterTask() {
! // use param here
}
--- 188,215 ----
call TaskParameter.postTask(34);
...
! event void TaskParameter.runTask(uint16_t param) {
...
}
! one can::
! uint16_t param;
! ...
! param = 34;
! post parameterTask();
...
task void parameterTask() {
! // use param
! }
!
! The principal difference between the simplest code for these
! two models is that if the component posts the task twice, it
! will use the older parameter in the TaskParameter example,
! while it will use the newer parameter in the basic task example.
! If a component wants to use the oldest parameter, then it can do
! this::
!
! if (post myTask() == SUCCESS) {
! param = 34;
}
***************
*** 195,199 ****
In TinyOS 2.x, the scheduler is a TinyOS component. Every scheduler
! MUST support basic nesC tasks. It MAY also support any number of
additional task interfaces. The scheduler component is resonsible for
the policy of reconciling different task types (e.g., earliest
--- 218,222 ----
In TinyOS 2.x, the scheduler is a TinyOS component. Every scheduler
! MUST support nesC tasks. It MAY also support any number of
additional task interfaces. The scheduler component is resonsible for
the policy of reconciling different task types (e.g., earliest
***************
*** 209,219 ****
dispatch tasks.
! For example, the standard TinyOS scheduler has this signature:
! | ``module SchedulerBasicP {``
! | ``provides interface Scheduler;``
! | ``provides interface TaskBasic[uint8_t taskID];``
! | ``uses interface McuSleep;``
! | ``}``
A scheduler MUST provide a parameterized TaskBasic interface.
--- 232,242 ----
dispatch tasks.
! For example, the standard TinyOS scheduler has this signature::
! module SchedulerBasicP {
! provides interface Scheduler;
! provides interface TaskBasic[uint8_t taskID];
! uses interface McuSleep;
! }
A scheduler MUST provide a parameterized TaskBasic interface.
***************
*** 227,237 ****
A scheduler MUST provide the Scheduler interface.
The Scheduler interface has commands for initialization and running
! tasks, and is used by TinyOS to execute tasks.
! | ``interface Scheduler {``
! | ``command void init();``
! | ``command bool runNextTask(bool sleep);``
! | ``command void taskLoop();``
! | ``}``
The init() command initializes the task queue and scheduler data
--- 250,260 ----
A scheduler MUST provide the Scheduler interface.
The Scheduler interface has commands for initialization and running
! tasks, and is used by TinyOS to execute tasks::
! interface Scheduler {
! command void init();
! command bool runNextTask(bool sleep);
! command void taskLoop();
! }
The init() command initializes the task queue and scheduler data
***************
*** 248,259 ****
into a low power state when the processor is idle: it never returns.
! This is the TaskBasic interface:
! | ``interface TaskBasic {``
! | ``async command error_t postTask();``
! | ``void event runTask();``
! | ``}``
! When a component declares a task with the ``task`` keyword in nesC, it
is implicitly declaring that it uses an instance of the TaskBasic
interface: the task body is the runTask event. When a component uses the
--- 271,282 ----
into a low power state when the processor is idle: it never returns.
! This is the TaskBasic interface::
! interface TaskBasic {
! async command error_t postTask();
! void event runTask();
! }
! When a component declares a task with the task keyword in nesC, it
is implicitly declaring that it uses an instance of the TaskBasic
interface: the task body is the runTask event. When a component uses the
***************
*** 292,326 ****
For example, imagine a hypothetical scheduler that provides earliest
deadline first tasks, which are provided through the TaskEdf
! interface:
! | ``interface TaskEdf {``
! | ``async command error_t postTask(uint16_t deadlineMs);``
! | ``event void runTask();``
! | ``}``
The scheduler implementation is named SchedulerEdfP, and provides both
! TaskBasic and TaskEdf interfaces:
! | ``module SchedulerEdfP {``
! | ``provides interface Scheduler;``
! | ``provides interface TaskBasic[uint8_t taskID];``
! | ``provides interface TaskEdf[uint8_t taskID];``
! | ``}``
An application that wants to use SchedulerEdfP instead of
SchedulerBasicP includes a configuration named TinySchedulerC, which
! exports all of SchedulerEdfP's interfaces:
! | ``configuration TinySchedulerC {``
! | ``provides interface Scheduler;``
! | ``provides interface TaskBasic[uint8_t taskID];``
! | ``provides interface TaskEdf[uint8_t taskID];``
! | ``}``
! | ``implementation {``
! | ``components SchedulerEdfP;``
! | ``Scheduler = SchedulerEdf;``
! | ``TaskBasic = SchedulerEdfP;``
! | ``TaskEDF = SchedulerEdfP;``
! | ``}``
For a module to have an earliest deadline first task, it uses the
--- 315,349 ----
For example, imagine a hypothetical scheduler that provides earliest
deadline first tasks, which are provided through the TaskEdf
! interface::
! interface TaskEdf {
! async command error_t postTask(uint16_t deadlineMs);
! event void runTask();
! }
The scheduler implementation is named SchedulerEdfP, and provides both
! TaskBasic and TaskEdf interfaces::
! module SchedulerEdfP {
! provides interface Scheduler;
! provides interface TaskBasic[uint8_t taskID];
! provides interface TaskEdf[uint8_t taskID];
! }
An application that wants to use SchedulerEdfP instead of
SchedulerBasicP includes a configuration named TinySchedulerC, which
! exports all of SchedulerEdfP's interfaces::
! configuration TinySchedulerC {
! provides interface Scheduler;
! provides interface TaskBasic[uint8_t taskID];
! provides interface TaskEdf[uint8_t taskID];
! }
! implementation {
! components SchedulerEdfP;
! Scheduler = SchedulerEdf;
! TaskBasic = SchedulerEdfP;
! TaskEDF = SchedulerEdfP;
! }
For a module to have an earliest deadline first task, it uses the
***************
*** 329,342 ****
where *TaskInterface* is the name of the new task interface as presented
by the scheduler. For example, the module SomethingP requires two EDF
! tasks:
! | ``configuration SomethingC {``
! | ``...``
! | ``}``
! | ``implementation {``
! | ``components SomethingP, TinySchedulerC;``
! | ``SomethingP.SendTask -> TinySchedulerC.TaskEdf["TinySchedulerC.TaskEdf"];``
! | ``SomethingP.SenseTask -> TinySchedulerC.TaskEdf["TinySchedulerC.TaskEdf"];``
! | ``}``
The module SomethingP also has a basic task. The nesC compiler
--- 352,365 ----
where *TaskInterface* is the name of the new task interface as presented
by the scheduler. For example, the module SomethingP requires two EDF
! tasks::
! configuration SomethingC {
! ...
! }
! implementation {
! components SomethingP, TinySchedulerC;
! SomethingP.SendTask -> TinySchedulerC.TaskEdf["TinySchedulerC.TaskEdf"];
! SomethingP.SenseTask -> TinySchedulerC.TaskEdf["TinySchedulerC.TaskEdf"];
! }
The module SomethingP also has a basic task. The nesC compiler
***************
*** 346,367 ****
interface. A component SHOULD use the keywords whenever possible, and it
MUST NOT mix the two syntaxes for a given task. This is an example
! implementation of SomethingP that uses keywords for basic tasks:
! | ``module SomethingP {``
! | ``uses interface TaskEdf as SendTask``
! | ``uses interface TaskEdf as SenseTask``
! | ``}``
! | ``implementation {``
! | ``// The TaskBasic, written with keywords``
! | ``task void cleanupTask() { ... some logic ... }``
! | ``event void SendTask.runTask() { ... some logic ... }``
! | ``event void SenseTask.runTask() { ... some logic ... }``
! |
! | ``void internal_function() {``
! | ``call SenseTask.postTask(20);``
! | ``call SendTask.postTask(100);``
! | ``post cleanupTask();``
! | ``}``
! | ``}``
If the scheduler provides two instances of the same task interface,
--- 369,390 ----
interface. A component SHOULD use the keywords whenever possible, and it
MUST NOT mix the two syntaxes for a given task. This is an example
! implementation of SomethingP that uses keywords for basic tasks::
! module SomethingP {
! uses interface TaskEdf as SendTask
! uses interface TaskEdf as SenseTask
! }
! implementation {
! // The TaskBasic, written with keywords
! task void cleanupTask() { ... some logic ... }
! event void SendTask.runTask() { ... some logic ... }
! event void SenseTask.runTask() { ... some logic ... }
!
! void internal_function() {
! call SenseTask.postTask(20);
! call SendTask.postTask(100);
! post cleanupTask();
! }
! }
If the scheduler provides two instances of the same task interface,
***************
*** 370,390 ****
a scheduler which provides two instances of TaskBasic: standard
tasks and high-priority tasks. The scheduler always selects a task
! for the high priority queue before the standard queue:
! | ``configuration TinySchedulerC {``
! | ``provides interface Scheduler;``
! | ``provides interface TaskBasic[uint8_t taskID];``
! | ``provides interface TaskBasic[uint8_t taskID] as TaskHighPriority;``
! | ``}``
A component that uses a high priority task would then wire to
! TaskHighPriority with the key "TinySchedulerC.TaskHighPriority":
! | ``configuration SomethingElseC {``
! | ``}``
! | ``implementation {``
! | ``components TinySchedulerC as Sched, SomethingElseP;``
! | ``SomethingElseP.RetransmitTask -> Sched.TaskHighPriority[unique("TinySchedulerC.TaskHighPriority")];``
! | ``}``
--- 393,412 ----
a scheduler which provides two instances of TaskBasic: standard
tasks and high-priority tasks. The scheduler always selects a task
! for the high priority queue before the standard queue::
! configuration TinySchedulerC {
! provides interface Scheduler;
! provides interface TaskBasic[uint8_t taskID];
! provides interface TaskBasic[uint8_t taskID] as TaskHighPriority;
! }
A component that uses a high priority task would then wire to
! TaskHighPriority with the key "TinySchedulerC.TaskHighPriority"::
! configuration SomethingElseC {}
! implementation {
! components TinySchedulerC as Sched, SomethingElseP;
! SomethingElseP.RetransmitTask -> Sched.TaskHighPriority[unique("TinySchedulerC.TaskHighPriority")];
! }
***************
*** 428,432 ****
====================================================================
! The nesC compiler transforms the ``post`` and ``task`` keywords into
nesC interfaces, wirings, and calls. By default, the statement::
--- 450,454 ----
====================================================================
! The nesC compiler transforms the post and task keywords into
nesC interfaces, wirings, and calls. By default, the statement::
***************
*** 463,467 ****
While the fact that tasks are transformed into interfaces is built in
to the nesC compiler, the exact names can be configured. Each
! platform's ``.platform`` file passes the ``-fnesc-scheduler`` option
to the compiler. The standard option is::
--- 485,489 ----
While the fact that tasks are transformed into interfaces is built in
to the nesC compiler, the exact names can be configured. Each
! platform's .platform file passes the -fnesc-scheduler option
to the compiler. The standard option is::
Index: tep107.txt
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/doc/txt/Attic/tep107.txt,v
retrieving revision 1.1.2.7
retrieving revision 1.1.2.8
diff -C2 -d -r1.1.2.7 -r1.1.2.8
*** tep107.txt 22 May 2006 17:10:36 -0000 1.1.2.7
--- tep107.txt 9 Jun 2006 16:51:45 -0000 1.1.2.8
***************
*** 51,80 ****
(TOSSIM has a very different boot sequence, as it is a PC
program). The module RealMain implements main(), and has the following
! signature:
! | ``module RealMain {``
! | ``uses {``
! | ``command result_t hardwareInit();``
! | ``interface StdControl;``
! | ``interface Pot;``
! | ``}``
! | ``}``
! The mote main() function uses a mix of nesC and C:
! | ``int main() __attribute__ ((C, spontaneous)) {``
! | ``call hardwareInit();``
! | ``call Pot.init(10);``
! | ``TOSH_sched_init();``
! | `` ``
! | ``call StdControl.init();``
! | ``call StdControl.start();``
! | ``__nesc_enable_interrupt();``
! | `` ``
! | ``while(1) {``
! | ``TOSH_run_task();``
! | ``}``
! | ``}``
--- 51,80 ----
(TOSSIM has a very different boot sequence, as it is a PC
program). The module RealMain implements main(), and has the following
! signature::
! module RealMain {
! uses {
! command result_t hardwareInit();
! interface StdControl;
! interface Pot;
! }
! }
! The mote main() function uses a mix of nesC and C::
! int main() __attribute__ ((C, spontaneous)) {
! call hardwareInit();
! call Pot.init(10);
! TOSH_sched_init();
!
! call StdControl.init();
! call StdControl.start();
! __nesc_enable_interrupt();
!
! while(1) {
! TOSH_run_task();
! }
! }
***************
*** 115,123 ****
* Boot, for signalling that the system has successfully booted
! The Init interface has a single command, init():
! | ``interface Init {``
! | ``command error_t init();``
! | ``}``
Init provides a synchronous interface, enabling initialization
--- 115,123 ----
* Boot, for signalling that the system has successfully booted
! The Init interface has a single command, init()::
! interface Init {
! command error_t init();
! }
Init provides a synchronous interface, enabling initialization
***************
*** 135,143 ****
The Boot interface has a single event, booted(), which the boot
! sequence signals when it has completed.
! | ``interface Boot {``
! | ``event void booted();``
! | ``}``
--- 135,143 ----
The Boot interface has a single event, booted(), which the boot
! sequence signals when it has completed::
! interface Boot {
! event void booted();
! }
***************
*** 149,194 ****
components that implement standard abstractions and exports the others
that are application specific. Code above the Hardware Independent
! Layer (TEP 2) SHOULD wire to MainC and not RealMainP.
! | ``module RealMainP {``
! | ``provides interface Booted;``
! | ``uses {``
! | ``interface Scheduler;``
! | ``interface Init as PlatformInit;``
! | ``interface Init as SoftwareInit;``
! | ``}``
! | ``}``
! | ``implementation {``
! | ``int main() __attribute__ ((C, spontaneous)) {``
! | ``atomic {``
! | ``call Scheduler.init();``
! | ``call PlatformInit.init();``
! | ``while (call Scheduler.runNextTask());``
! | ``call SoftwareInit.init();``
! | ``while (call Scheduler.runNextTask());``
! | ``}``
! | ``__nesc_enable_interrupt();``
! | ``signal Boot.booted();``
! | ``call Scheduler.taskLoop();``
! | ``return -1;``
! | ``}``
! | ``default command error_t PlatformInit.init() { return SUCCESS; }``
! | ``default command error_t SoftwareInit.init() { return SUCCESS; }``
! | ``default event void Boot.booted() { }``
! | ``}``
4.1 Initialization
--------------------------------------------------------------------
! The first step in the boot sequence is initializing the system:
! | ``atomic {``
! | ``call Scheduler.init();``
! | ``call PlatformInit.init();``
! | ``while (call Scheduler.runNextTask());``
! | ``call SoftwareInit.init();``
! | ``while (call Scheduler.runNextTask());``
! | ``}``
--- 149,194 ----
components that implement standard abstractions and exports the others
that are application specific. Code above the Hardware Independent
! Layer (TEP 2) SHOULD wire to MainC and not RealMainP::
! module RealMainP {
! provides interface Booted;
! uses {
! interface Scheduler;
! interface Init as PlatformInit;
! interface Init as SoftwareInit;
! }
! }
! implementation {
! int main() __attribute__ ((C, spontaneous)) {
! atomic {
! call Scheduler.init();
! call PlatformInit.init();
! while (call Scheduler.runNextTask());
! call SoftwareInit.init();
! while (call Scheduler.runNextTask());
! }
! __nesc_enable_interrupt();
! signal Boot.booted();
! call Scheduler.taskLoop();
! return -1;
! }
! default command error_t PlatformInit.init() { return SUCCESS; }
! default command error_t SoftwareInit.init() { return SUCCESS; }
! default event void Boot.booted() { }
! }
4.1 Initialization
--------------------------------------------------------------------
! The first step in the boot sequence is initializing the system::
! atomic {
! call Scheduler.init();
! call PlatformInit.init();
! while (call Scheduler.runNextTask());
! call SoftwareInit.init();
! while (call Scheduler.runNextTask());
! }
More information about the Tinyos-2-commits
mailing list