123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- /**
- \defgroup pt Protothreads
- Protothreads are a type of lightweight stackless threads designed for
- severly memory constrained systems such as deeply embedded systems or
- sensor network nodes. Protothreads provides linear code execution for
- event-driven systems implemented in C. Protothreads can be used with
- or without an RTOS.
- Protothreads are a extremely lightweight, stackless type of threads
- that provides a blocking context on top of an event-driven system,
- without the overhead of per-thread stacks. The purpose of protothreads
- is to implement sequential flow of control without complex state
- machines or full multi-threading. Protothreads provides conditional
- blocking inside C functions.
- The advantage of protothreads over a purely event-driven approach is
- that protothreads provides a sequential code structure that allows for
- blocking functions. In purely event-driven systems, blocking must be
- implemented by manually breaking the function into two pieces - one
- for the piece of code before the blocking call and one for the code
- after the blocking call. This makes it hard to use control structures
- such as if() conditionals and while() loops.
- The advantage of protothreads over ordinary threads is that a
- protothread do not require a separate stack. In memory constrained
- systems, the overhead of allocating multiple stacks can consume large
- amounts of the available memory. In contrast, each protothread only
- requires between two and twelve bytes of state, depending on the
- architecture.
- \note Because protothreads do not save the stack context across a
- blocking call, <b>local variables are not preserved when the
- protothread blocks</b>. This means that local variables should be used
- with utmost care - <b>if in doubt, do not use local variables inside a
- protothread!</b>
- Main features:
- - No machine specific code - the protothreads library is pure C
- - Does not use error-prone functions such as longjmp()
-
- - Very small RAM overhead - only two bytes per protothread
-
- - Can be used with or without an OS
-
- - Provides blocking wait without full multi-threading or
- stack-switching
- Examples applications:
- - Memory constrained systems
-
- - Event-driven protocol stacks
-
- - Deeply embedded systems
-
- - Sensor network nodes
- The protothreads API consists of four basic operations:
- initialization: PT_INIT(), execution: PT_BEGIN(), conditional
- blocking: PT_WAIT_UNTIL() and exit: PT_END(). On top of these, two
- convenience functions are built: reversed condition blocking:
- PT_WAIT_WHILE() and protothread blocking: PT_WAIT_THREAD().
- \sa \ref pt "Protothreads API documentation"
-
- The protothreads library is released under a BSD-style license that
- allows for both non-commercial and commercial usage. The only
- requirement is that credit is given.
- \section authors Authors
- The protothreads library was written by Adam Dunkels <adam@sics.se>
- with support from Oliver Schmidt <ol.sc@web.de>.
- \section pt-desc Protothreads
- Protothreads are a extremely lightweight, stackless threads that
- provides a blocking context on top of an event-driven system, without
- the overhead of per-thread stacks. The purpose of protothreads is to
- implement sequential flow of control without using complex state
- machines or full multi-threading. Protothreads provides conditional
- blocking inside a C function.
- In memory constrained systems, such as deeply embedded systems,
- traditional multi-threading may have a too large memory overhead. In
- traditional multi-threading, each thread requires its own stack, that
- typically is over-provisioned. The stacks may use large parts of the
- available memory.
- The main advantage of protothreads over ordinary threads is that
- protothreads are very lightweight: a protothread does not require its
- own stack. Rather, all protothreads run on the same stack and context
- switching is done by stack rewinding. This is advantageous in memory
- constrained systems, where a stack for a thread might use a large part
- of the available memory. A protothread only requires only two bytes of
- memory per protothread. Moreover, protothreads are implemented in pure
- C and do not require any machine-specific assembler code.
- A protothread runs within a single C function and cannot span over
- other functions. A protothread may call normal C functions, but cannot
- block inside a called function. Blocking inside nested function calls
- is instead made by spawning a separate protothread for each
- potentially blocking function. The advantage of this approach is that
- blocking is explicit: the programmer knows exactly which functions
- that block that which functions the never blocks.
- Protothreads are similar to asymmetric co-routines. The main
- difference is that co-routines uses a separate stack for each
- co-routine, whereas protothreads are stackless. The most similar
- mechanism to protothreads are Python generators. These are also
- stackless constructs, but have a different purpose. Protothreads
- provides blocking contexts inside a C function, whereas Python
- generators provide multiple exit points from a generator function.
- \section pt-autovars Local variables
- \note
- Because protothreads do not save the stack context across a blocking
- call, local variables are not preserved when the protothread
- blocks. This means that local variables should be used with utmost
- care - if in doubt, do not use local variables inside a protothread!
- \section pt-scheduling Scheduling
- A protothread is driven by repeated calls to the function in which the
- protothread is running. Each time the function is called, the
- protothread will run until it blocks or exits. Thus the scheduling of
- protothreads is done by the application that uses protothreads.
- \section pt-impl Implementation
- Protothreads are implemented using \ref lc "local continuations". A
- local continuation represents the current state of execution at a
- particular place in the program, but does not provide any call history
- or local variables. A local continuation can be set in a specific
- function to capture the state of the function. After a local
- continuation has been set can be resumed in order to restore the state
- of the function at the point where the local continuation was set.
- Local continuations can be implemented in a variety of ways:
- -# by using machine specific assembler code,
- -# by using standard C constructs, or
- -# by using compiler extensions.
- The first way works by saving and restoring the processor state,
- except for stack pointers, and requires between 16 and 32 bytes of
- memory per protothread. The exact amount of memory required depends on
- the architecture.
- The standard C implementation requires only two bytes of state per
- protothread and utilizes the C switch() statement in a non-obvious way
- that is similar to Duff's device. This implementation does, however,
- impose a slight restriction to the code that uses protothreads in that
- the code cannot use switch() statements itself.
- Certain compilers has C extensions that can be used to implement
- protothreads. GCC supports label pointers that can be used for this
- purpose. With this implementation, protothreads require 4 bytes of RAM
- per protothread.
- @{
- */
- /** @} */
|