Top Banner
Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices Andrew Barton-Sweeney September 21, 2006
24

Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Jan 19, 2016

Download

Documents

aerona

Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices. Andrew Barton-Sweeney September 21, 2006. Why Threading?. Many tasks running on a sensor node Short sensor sample and hardware drivers Communication and radio network Long data processing algorithms - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Threading Abstractions for Embedded Operating Systems

on Memory Constrained Devices

Andrew Barton-Sweeney

September 21, 2006

Page 2: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Why Threading?• Many tasks running on a sensor node

– Short sensor sample and hardware drivers– Communication and radio network– Long data processing algorithms

• Without threading or concurrency, a long-running task can block other tasks from running.– Ex. A compression algorithm may prevent the node from receiving

critical messages from the radio network.• Solution:

– The programmer can write only short routines that always run quickly. This is not always feasible for certain routines.

– The programmer can explicitly breakup a routine in sections, and maintain a state-machine that runs the sections in a sequence.

– Use threading: the programmers design the routine using the natural logic of the algorithm, and familiar control constructs such as infinite loops. The scheduler will handle multiple routines concurrently.

Page 3: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Overview

• Threading and Scheduler Flavors– Preemptive Scheduling vs. Non-Preemptive

Scheduling– Advantages and Disadvantages

• Examples of Threading Abstractions– eCos and uCOS-II– Mantis– Contiki– TinyOS and TinyMOS– Protothreads

Page 4: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Non-Preemptive (Event-Driven) Scheduler

• Support multiple threads of execution as different event handlers.

• Task Threads may be started by an event.

• Current Thread of Execution runs to completion, blocking other threads from running.

Page 5: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Preemptive Scheduler

• Threads have priority levels.

• Task Threads must be started by the program.

• Higher priority threads cause a running lower priority threads to suspend execution and the processor runs the higher priority thread. (context switch) When the higher priority thread is finished, the lower priority thread resumes where it was interrupted.

Page 6: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Differences between Threading Models

• Preemptive Scheduler– Stack (Memory)

• Each thread requires a unique stack to store the procedure call sequence and automatic variables.

• This is a large memory overhead.– Synchronization

• Threads may execute concurrently and require synchronization to protect shared resources.

• Introduces many potential run-time errors. Difficult to debug. Requires careful programming and use of the synchronization mechanisms,

– Continuous Program Model• The algorithm of a thread is programmed in a logical sequence. The

programmer does not concern with blocking other threads- the scheduler will handle this.

• Overhead from context switching between threads. Requires a more complex scheduler, with latency to save the context of one thread and load the context of the next.

Page 7: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Differences between Threading Models

• Non-preemeptive (Event-Driven)– Stack (Memory)

• Requires a single stack. (stores automatic variable and call-trace of the programs execution).

• Switching task threads causes the stack to unwind. (The calls made in the task thread are returned, and the stack is returned to the original caller of the event-handler task thread- ie. The scheduler)

– Synchronization• A single task thread executes at any time without interruption by other tasks.

No synchronization is needed between tasks.• Must protect resources used by the task thread only from interrupts. (Careful

design of interrupt code can reduce concurrency issues by letting the interrupt schedule a new task thread to handle the interrupt’s activity)

– Run-to-completion Model (State-Machine)• Task thread must be designed to execute quickly and return without blocking

the processor for a long time.• A long algorithm must be broken into smaller pieces and the task must

reschedule itself to run all pieces of the algorithm, allowing other tasks to run in between. A state machine is used to manage running the long algorithm.

Page 8: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

eCos and uCOS-II• Scheduler

– Multilevel Priorities• (Linked list, threads may share same priority level)

– Bitmap Priorities• (Bitmap, threads have a unique priority level)

• Conventional Threading– Traditional preemptive threading paradigm as in UNIX– Priority based Preemption.– Timeslicing with multilevel priorities.

• Synchronization– Scheduler Lock– Mutex– Sempahore– Conditional Variable– Flags– Message Boxes

Page 9: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

eCos Example• #include <cyg/kernel/kapi.h>

• #define MONITOR_THREAD_STACK_SIZE ( 2048 / sizeof(int) )

• int monitor_thread_stack[ MONITOR_THEAD_STACK_SIZE ];• cug_handle_t monitor_thread_handle;• cyg_thread monitor_thread_obj;

• //• // Monitoring thread.• //• void monitor_thread( cyg_addrword_t index )• {• unsigned long monitor_counter = 0;•• // Infinite loop for monitor thread.• while ( 1 )• {• // Delay for 1000 ticks.• cyg_thread_delay( 1000 );•• // Increment the counter.• monitor_counter++;• }• }

• //• // Main starting point for the application.• //• void cyg_user_start( void )• {• // Create the Monitor thread.• cyg_thread_create(• 12,• monitor_thread,• 0,• "Monitor Thread",• &monitor_thread_stack,• MONITOR_THREAD_STACK_SIZE,• &monitor_thread_handle,• &monitor_thread_obj );•• // Let thre thread run when the scheduler starts.• cyg_thread_resume( monitor_thread_handle );• }

Page 10: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

MantisOS

• Scheduler– Power-aware (sleep when no active threads).– Preemptive time-slicing with priority levels.

• Threading– Subset of POSIX threads: priority-based thread

scheduling with round-robin semantics within a priority level.

• Synchronization– Semaphores

Page 11: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Mantis OS Example• void start( void ){

• Packet data;• uint8_t i, size;•• mos_enable_power_mgt();•• while( 1 ){• size = flooding_recv( (char*)&data, 0x02 );• if( size < 1)• mos_led_toggle( 0 );• else{• for( i=0; i<size; i++ )• mos_uart_send(0, ((char*)&data[i] );• mos_led_toggle( 2 );• }•• mos_thread_sleep( 32 );• }• }

Page 12: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Contiki

• Scheduler (Kernel)– Event-driven, non-preemptive

• Threading– Optional Application layer library– An application task includes the threading library. The task

creates an runs application threads when the task is run from the scheduler.

– No priorities. Preemption is implemented through time-slicing.

• Synchronization– Post and wait primitives allow a thread to signal to another

thread. Concurrency issues are left to the programmer to provides application specific resource protections.

Page 13: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

TinyOS and TinyMOS

• TinyOS– Uses a scheduler in a single thread to run tasks on an

event. A task runs to completion, blocking other tasks, until it returns to the scheduler.

• TinyMOS– Gives preemptive threading features to TinyOS– Run the TinyOS scheduler as a single thread inside a

master preemptive scheduler.– Tasks in the TinyOS scheduler can schedule threads

to run in the master scheduler.

Page 14: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Protothreads Library

• Application layer threading library.

• A threading abstraction that provides preemptive threading-like features.

• Allow a programmer to simulate concurrent processes in an event-driven operating system (non-preemptive).

• A long running task can yield to others tasks, and resume operation at a later time.

Page 15: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Protothreads in C

• The threading features are implemented as macros in C language, inserted into a routine.

• The macros create automatically generate a switch statement, and state-machine. – The state-machine allows the routine to save its current state in

the middle of operation and return to the caller (yield). – In the future, the routine is called again, and uses the saved

state to resume at the last point of operation.– The state per protothread is only two bytes.

• The programmer does not need to explicitly create the state machine. This greatly simplifies the design of the routine.

Page 16: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Advantages

• Very small memory overhead per thread– No stack per thread– No latency for context switching– No preemption. The thread will run to completion until

it explicitly yeilds. This prevents concurrency issues, since a protothread will never be interrupted. (except for hardware interrupts…)

• Simplify the creation of the state-machine to break-up long-running routines.

Page 17: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Disadvantages

• No preemption. The thread will run to completion until it explicitly yields. It is possible for a BAD routine to block a protothread and stall the entire system.

• No automatic variables. They would require a separate stack.– All threads run in a single stack.– When a thread yields, the routine returns to the caller before

another thread is run. This is called stack rewinding. Any automatic variables are lost.

• The current implementation of Protothreads does not allow a routine to use switch statements.

Page 18: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Example: Radio Task using Event Driven Task

• enum {• ON,• WAITING,• OFF• } state;

• void radio_wake_eventhandler() {• switch( state ){•• case OFF:• if( timer_expired( &timer ) ) {• radio_on();• state = ON;• timer_set( &timer, T_AWAKE );• }• break;•• case ON:• if( timer_expired( &timer ) ) {• timer_set( &timer, T_SLEEP );• if( !communication_complete() ) {• state = WAITING;• } else {• radio_off();• state = OFF;• }• }• break;•• case WAITING:• if( communication_complete()• || timer_expired( &timer ) ) {• state = ON;• timer_set( &timer, T_AWAKE );• } else {• radio_off();• state = OFF;• }• break;• }• }

Page 19: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Example: Radio Task using Protothreads

• PT_THREAD( radio_wake_thread( struct pt *pt )) {• PT_BEGIN( pt );•• while( 1 ) {• radio_on();• timer_set( &timer, T_AWAKE );• PT_WAIT_UNTIL( pt, timer_expired( &timer ));•• timer_set( &timer, T_SLEEP );• if( !communication_complete()) {• PT_WAIT_UNTIL( pt, communication_complete()• || timer_expired( &timer ));• }•• if( !timer_expired( &timer )) {• radio_off();• PT_WAIT_UNTIL( pt, timer_expired( &timer ));• }• }•• PT_END( pt );• }

Page 20: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Code Generated by Protothreads Library

• void radio_wake_thread( struct pt *pt ) {

• switch( pt->lc ) {•• case 0:•• while( 1 ) {• radio_on();• timer_set( &timer, T_AWAKE );•• pt->lc = 8;• case 8:• if( !timer_expired( &timer )) {• return;• }•• timer_set( &timer, T_SLEEP );• if( !communication_complete() ) {•• pc->lc = 13;• case 13:• if( !(communication_complete() ||• timer_expired( &timer ))) {• return;• }• }•• if( !timer_expired( &timer )) {• radio_off();•• pt->lc = 18;• case 18:• if( !timer_expired( &timer )) {• return;• }• }• }• }• }

Page 21: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Review of Threading Abstractions

• Kernel Layer Preemptive Scheduler– Traditional preemptive threading, like UNIX

• Kernel Layer Non-Preemptive Scheduler– Event-driven operating system

• Application Layer Preemptive Scheduler

• Application Layer Event-Driven Scheduler

• Compile-time Generation of a State-Machine for a Concurrency Abstraction in a Non-preemptive Scheduler.

Page 22: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

The State of the Art• eCos and uCOS-II

– Traditional Preemptive Threading, like UNIX• Mantis

– Subset of Traditional Preemptive Threading– Power-aware scheduler

• Contiki– Application Layer Threading Library– Event-driven scheduler

• TinyOS and SOS– Event-driven scheduler– No preemptive threading

• TinyMOS– Master preemptive scheduler– Run TinyOS scheduler (event-driven) in a preemptive thread

• Protothreads– Application layer library for Non-preemptive concurrency abstraction– Automatically generate state-machine to break up long sections of code.– Yield to other tasks, use state-machine to resume to last point of operation

Page 23: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

Threading in SOS

• A Protothreads Library is available for SOS.

• Similar to Application Layer threads in Contiki.

• Cannot use Protothreads in a module message handler!– The Protothreads State-Machine conflicts the message switch

statement.– The message handler is an event scheduler!

• Use Protothreads in a sub-routine! – Create a Protothread in a sub-routine.– Let a Module repeatedly call the sub-routine, until the

Protothread is finished.

Page 24: Threading Abstractions for Embedded Operating Systems on Memory Constrained Devices

References• eCos

– http://ecos.sourceware.org/• uCOS-II

– http://www.geocities.com/michaelanburaj/uCOS/index.html– Papers

• http://www.ovro.caltech.edu/~dwh/ucos/project_AR1803.pdf#search=%22uCos%20paper%22• http://micrium.com/downloads/appnotes/NS-CR16C-uCOS-II.pdf#search=%22explain%20ucos-ii%22

– Micrium – Commercial site• http://www.micrium.com/

• Mantis– http://mantis.cs.colorado.edu/index.php/tiki-pagehistory.php?page=HomePage&diff=83

• Contiki– http://www.sics.se/~adam/contiki/

• TinyOS– http://www.tinyos.net/

• TinyMOS– http://www.eecs.harvard.edu/emnets/papers/trumplerEmnets06.pdf#search=%22tinymos%22

• Protothreads– http://www.sics.se/~adam/pt/

• SOS– http://nesl.ee.ucla.edu/projects/sos-1.x/publications/