1/** 2\defgroup pt Protothreads 3 4Protothreads are a type of lightweight stackless threads designed for 5severly memory constrained systems such as deeply embedded systems or 6sensor network nodes. Protothreads provides linear code execution for 7event-driven systems implemented in C. Protothreads can be used with 8or without an RTOS. 9 10Protothreads are a extremely lightweight, stackless type of threads 11that provides a blocking context on top of an event-driven system, 12without the overhead of per-thread stacks. The purpose of protothreads 13is to implement sequential flow of control without complex state 14machines or full multi-threading. Protothreads provides conditional 15blocking inside C functions. 16 17The advantage of protothreads over a purely event-driven approach is 18that protothreads provides a sequential code structure that allows for 19blocking functions. In purely event-driven systems, blocking must be 20implemented by manually breaking the function into two pieces - one 21for the piece of code before the blocking call and one for the code 22after the blocking call. This makes it hard to use control structures 23such as if() conditionals and while() loops. 24 25The advantage of protothreads over ordinary threads is that a 26protothread do not require a separate stack. In memory constrained 27systems, the overhead of allocating multiple stacks can consume large 28amounts of the available memory. In contrast, each protothread only 29requires between two and twelve bytes of state, depending on the 30architecture. 31 32\note Because protothreads do not save the stack context across a 33blocking call, <b>local variables are not preserved when the 34protothread blocks</b>. This means that local variables should be used 35with utmost care - <b>if in doubt, do not use local variables inside a 36protothread!</b> 37 38 39Main features: 40 41 - No machine specific code - the protothreads library is pure C 42 43 - Does not use error-prone functions such as longjmp() 44 45 - Very small RAM overhead - only two bytes per protothread 46 47 - Can be used with or without an OS 48 49 - Provides blocking wait without full multi-threading or 50 stack-switching 51 52Examples applications: 53 54 - Memory constrained systems 55 56 - Event-driven protocol stacks 57 58 - Deeply embedded systems 59 60 - Sensor network nodes 61 62The protothreads API consists of four basic operations: 63initialization: PT_INIT(), execution: PT_BEGIN(), conditional 64blocking: PT_WAIT_UNTIL() and exit: PT_END(). On top of these, two 65convenience functions are built: reversed condition blocking: 66PT_WAIT_WHILE() and protothread blocking: PT_WAIT_THREAD(). 67 68\sa \ref pt "Protothreads API documentation" 69 70The protothreads library is released under a BSD-style license that 71allows for both non-commercial and commercial usage. The only 72requirement is that credit is given. 73 74\section authors Authors 75 76The protothreads library was written by Adam Dunkels <[email protected]> 77with support from Oliver Schmidt <[email protected]>. 78 79\section pt-desc Protothreads 80 81Protothreads are a extremely lightweight, stackless threads that 82provides a blocking context on top of an event-driven system, without 83the overhead of per-thread stacks. The purpose of protothreads is to 84implement sequential flow of control without using complex state 85machines or full multi-threading. Protothreads provides conditional 86blocking inside a C function. 87 88In memory constrained systems, such as deeply embedded systems, 89traditional multi-threading may have a too large memory overhead. In 90traditional multi-threading, each thread requires its own stack, that 91typically is over-provisioned. The stacks may use large parts of the 92available memory. 93 94The main advantage of protothreads over ordinary threads is that 95protothreads are very lightweight: a protothread does not require its 96own stack. Rather, all protothreads run on the same stack and context 97switching is done by stack rewinding. This is advantageous in memory 98constrained systems, where a stack for a thread might use a large part 99of the available memory. A protothread only requires only two bytes of 100memory per protothread. Moreover, protothreads are implemented in pure 101C and do not require any machine-specific assembler code. 102 103A protothread runs within a single C function and cannot span over 104other functions. A protothread may call normal C functions, but cannot 105block inside a called function. Blocking inside nested function calls 106is instead made by spawning a separate protothread for each 107potentially blocking function. The advantage of this approach is that 108blocking is explicit: the programmer knows exactly which functions 109that block that which functions the never blocks. 110 111Protothreads are similar to asymmetric co-routines. The main 112difference is that co-routines uses a separate stack for each 113co-routine, whereas protothreads are stackless. The most similar 114mechanism to protothreads are Python generators. These are also 115stackless constructs, but have a different purpose. Protothreads 116provides blocking contexts inside a C function, whereas Python 117generators provide multiple exit points from a generator function. 118 119\section pt-autovars Local variables 120 121\note 122Because protothreads do not save the stack context across a blocking 123call, local variables are not preserved when the protothread 124blocks. This means that local variables should be used with utmost 125care - if in doubt, do not use local variables inside a protothread! 126 127\section pt-scheduling Scheduling 128 129A protothread is driven by repeated calls to the function in which the 130protothread is running. Each time the function is called, the 131protothread will run until it blocks or exits. Thus the scheduling of 132protothreads is done by the application that uses protothreads. 133 134\section pt-impl Implementation 135 136Protothreads are implemented using \ref lc "local continuations". A 137local continuation represents the current state of execution at a 138particular place in the program, but does not provide any call history 139or local variables. A local continuation can be set in a specific 140function to capture the state of the function. After a local 141continuation has been set can be resumed in order to restore the state 142of the function at the point where the local continuation was set. 143 144 145Local continuations can be implemented in a variety of ways: 146 147 -# by using machine specific assembler code, 148 -# by using standard C constructs, or 149 -# by using compiler extensions. 150 151The first way works by saving and restoring the processor state, 152except for stack pointers, and requires between 16 and 32 bytes of 153memory per protothread. The exact amount of memory required depends on 154the architecture. 155 156The standard C implementation requires only two bytes of state per 157protothread and utilizes the C switch() statement in a non-obvious way 158that is similar to Duff's device. This implementation does, however, 159impose a slight restriction to the code that uses protothreads in that 160the code cannot use switch() statements itself. 161 162Certain compilers has C extensions that can be used to implement 163protothreads. GCC supports label pointers that can be used for this 164purpose. With this implementation, protothreads require 4 bytes of RAM 165per protothread. 166 167@{ 168 169 170*/ 171 172/** @} */ 173 174