Yan Wang / Mbed 2 deprecated ProtoThread

Dependencies:   mbed

Committer:
phyllis
Date:
Tue Nov 30 22:14:29 2010 +0000
Revision:
0:1690a672d017

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
phyllis 0:1690a672d017 1 /*
phyllis 0:1690a672d017 2 * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
phyllis 0:1690a672d017 3 * All rights reserved.
phyllis 0:1690a672d017 4 *
phyllis 0:1690a672d017 5 * Redistribution and use in source and binary forms, with or without
phyllis 0:1690a672d017 6 * modification, are permitted provided that the following conditions
phyllis 0:1690a672d017 7 * are met:
phyllis 0:1690a672d017 8 * 1. Redistributions of source code must retain the above copyright
phyllis 0:1690a672d017 9 * notice, this list of conditions and the following disclaimer.
phyllis 0:1690a672d017 10 * 2. Redistributions in binary form must reproduce the above copyright
phyllis 0:1690a672d017 11 * notice, this list of conditions and the following disclaimer in the
phyllis 0:1690a672d017 12 * documentation and/or other materials provided with the distribution.
phyllis 0:1690a672d017 13 * 3. Neither the name of the Institute nor the names of its contributors
phyllis 0:1690a672d017 14 * may be used to endorse or promote products derived from this software
phyllis 0:1690a672d017 15 * without specific prior written permission.
phyllis 0:1690a672d017 16 *
phyllis 0:1690a672d017 17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
phyllis 0:1690a672d017 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
phyllis 0:1690a672d017 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
phyllis 0:1690a672d017 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
phyllis 0:1690a672d017 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
phyllis 0:1690a672d017 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
phyllis 0:1690a672d017 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
phyllis 0:1690a672d017 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
phyllis 0:1690a672d017 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
phyllis 0:1690a672d017 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
phyllis 0:1690a672d017 27 * SUCH DAMAGE.
phyllis 0:1690a672d017 28 *
phyllis 0:1690a672d017 29 * This file is part of the Contiki operating system.
phyllis 0:1690a672d017 30 *
phyllis 0:1690a672d017 31 * Author: Adam Dunkels <adam@sics.se>
phyllis 0:1690a672d017 32 *
phyllis 0:1690a672d017 33 * $Id: pt.h,v 1.7 2006/10/02 07:52:56 adam Exp $
phyllis 0:1690a672d017 34 */
phyllis 0:1690a672d017 35
phyllis 0:1690a672d017 36 /**
phyllis 0:1690a672d017 37 * \addtogroup pt
phyllis 0:1690a672d017 38 * @{
phyllis 0:1690a672d017 39 */
phyllis 0:1690a672d017 40
phyllis 0:1690a672d017 41 /**
phyllis 0:1690a672d017 42 * \file
phyllis 0:1690a672d017 43 * Protothreads implementation.
phyllis 0:1690a672d017 44 * \author
phyllis 0:1690a672d017 45 * Adam Dunkels <adam@sics.se>
phyllis 0:1690a672d017 46 *
phyllis 0:1690a672d017 47 */
phyllis 0:1690a672d017 48
phyllis 0:1690a672d017 49 #ifndef __PT_H__
phyllis 0:1690a672d017 50 #define __PT_H__
phyllis 0:1690a672d017 51
phyllis 0:1690a672d017 52 #include "lc.h"
phyllis 0:1690a672d017 53
phyllis 0:1690a672d017 54 struct pt {
phyllis 0:1690a672d017 55 lc_t lc;
phyllis 0:1690a672d017 56 };
phyllis 0:1690a672d017 57
phyllis 0:1690a672d017 58 #define PT_WAITING 0
phyllis 0:1690a672d017 59 #define PT_YIELDED 1
phyllis 0:1690a672d017 60 #define PT_EXITED 2
phyllis 0:1690a672d017 61 #define PT_ENDED 3
phyllis 0:1690a672d017 62
phyllis 0:1690a672d017 63 /**
phyllis 0:1690a672d017 64 * \name Initialization
phyllis 0:1690a672d017 65 * @{
phyllis 0:1690a672d017 66 */
phyllis 0:1690a672d017 67
phyllis 0:1690a672d017 68 /**
phyllis 0:1690a672d017 69 * Initialize a protothread.
phyllis 0:1690a672d017 70 *
phyllis 0:1690a672d017 71 * Initializes a protothread. Initialization must be done prior to
phyllis 0:1690a672d017 72 * starting to execute the protothread.
phyllis 0:1690a672d017 73 *
phyllis 0:1690a672d017 74 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 75 *
phyllis 0:1690a672d017 76 * \sa PT_SPAWN()
phyllis 0:1690a672d017 77 *
phyllis 0:1690a672d017 78 * \hideinitializer
phyllis 0:1690a672d017 79 */
phyllis 0:1690a672d017 80 #define PT_INIT(pt) LC_INIT((pt)->lc)
phyllis 0:1690a672d017 81
phyllis 0:1690a672d017 82 /** @} */
phyllis 0:1690a672d017 83
phyllis 0:1690a672d017 84 /**
phyllis 0:1690a672d017 85 * \name Declaration and definition
phyllis 0:1690a672d017 86 * @{
phyllis 0:1690a672d017 87 */
phyllis 0:1690a672d017 88
phyllis 0:1690a672d017 89 /**
phyllis 0:1690a672d017 90 * Declaration of a protothread.
phyllis 0:1690a672d017 91 *
phyllis 0:1690a672d017 92 * This macro is used to declare a protothread. All protothreads must
phyllis 0:1690a672d017 93 * be declared with this macro.
phyllis 0:1690a672d017 94 *
phyllis 0:1690a672d017 95 * \param name_args The name and arguments of the C function
phyllis 0:1690a672d017 96 * implementing the protothread.
phyllis 0:1690a672d017 97 *
phyllis 0:1690a672d017 98 * \hideinitializer
phyllis 0:1690a672d017 99 */
phyllis 0:1690a672d017 100 #define PT_THREAD(name_args) char name_args
phyllis 0:1690a672d017 101
phyllis 0:1690a672d017 102 /**
phyllis 0:1690a672d017 103 * Declare the start of a protothread inside the C function
phyllis 0:1690a672d017 104 * implementing the protothread.
phyllis 0:1690a672d017 105 *
phyllis 0:1690a672d017 106 * This macro is used to declare the starting point of a
phyllis 0:1690a672d017 107 * protothread. It should be placed at the start of the function in
phyllis 0:1690a672d017 108 * which the protothread runs. All C statements above the PT_BEGIN()
phyllis 0:1690a672d017 109 * invokation will be executed each time the protothread is scheduled.
phyllis 0:1690a672d017 110 *
phyllis 0:1690a672d017 111 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 112 *
phyllis 0:1690a672d017 113 * \hideinitializer
phyllis 0:1690a672d017 114 */
phyllis 0:1690a672d017 115 #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
phyllis 0:1690a672d017 116
phyllis 0:1690a672d017 117 /**
phyllis 0:1690a672d017 118 * Declare the end of a protothread.
phyllis 0:1690a672d017 119 *
phyllis 0:1690a672d017 120 * This macro is used for declaring that a protothread ends. It must
phyllis 0:1690a672d017 121 * always be used together with a matching PT_BEGIN() macro.
phyllis 0:1690a672d017 122 *
phyllis 0:1690a672d017 123 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 124 *
phyllis 0:1690a672d017 125 * \hideinitializer
phyllis 0:1690a672d017 126 */
phyllis 0:1690a672d017 127 #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
phyllis 0:1690a672d017 128 PT_INIT(pt); return PT_ENDED; }
phyllis 0:1690a672d017 129
phyllis 0:1690a672d017 130 /** @} */
phyllis 0:1690a672d017 131
phyllis 0:1690a672d017 132 /**
phyllis 0:1690a672d017 133 * \name Blocked wait
phyllis 0:1690a672d017 134 * @{
phyllis 0:1690a672d017 135 */
phyllis 0:1690a672d017 136
phyllis 0:1690a672d017 137 /**
phyllis 0:1690a672d017 138 * Block and wait until condition is true.
phyllis 0:1690a672d017 139 *
phyllis 0:1690a672d017 140 * This macro blocks the protothread until the specified condition is
phyllis 0:1690a672d017 141 * true.
phyllis 0:1690a672d017 142 *
phyllis 0:1690a672d017 143 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 144 * \param condition The condition.
phyllis 0:1690a672d017 145 *
phyllis 0:1690a672d017 146 * \hideinitializer
phyllis 0:1690a672d017 147 */
phyllis 0:1690a672d017 148 #define PT_WAIT_UNTIL(pt, condition) \
phyllis 0:1690a672d017 149 do { \
phyllis 0:1690a672d017 150 LC_SET((pt)->lc); \
phyllis 0:1690a672d017 151 if(!(condition)) { \
phyllis 0:1690a672d017 152 return PT_WAITING; \
phyllis 0:1690a672d017 153 } \
phyllis 0:1690a672d017 154 } while(0)
phyllis 0:1690a672d017 155
phyllis 0:1690a672d017 156 /**
phyllis 0:1690a672d017 157 * Block and wait while condition is true.
phyllis 0:1690a672d017 158 *
phyllis 0:1690a672d017 159 * This function blocks and waits while condition is true. See
phyllis 0:1690a672d017 160 * PT_WAIT_UNTIL().
phyllis 0:1690a672d017 161 *
phyllis 0:1690a672d017 162 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 163 * \param cond The condition.
phyllis 0:1690a672d017 164 *
phyllis 0:1690a672d017 165 * \hideinitializer
phyllis 0:1690a672d017 166 */
phyllis 0:1690a672d017 167 #define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
phyllis 0:1690a672d017 168
phyllis 0:1690a672d017 169 /** @} */
phyllis 0:1690a672d017 170
phyllis 0:1690a672d017 171 /**
phyllis 0:1690a672d017 172 * \name Hierarchical protothreads
phyllis 0:1690a672d017 173 * @{
phyllis 0:1690a672d017 174 */
phyllis 0:1690a672d017 175
phyllis 0:1690a672d017 176 /**
phyllis 0:1690a672d017 177 * Block and wait until a child protothread completes.
phyllis 0:1690a672d017 178 *
phyllis 0:1690a672d017 179 * This macro schedules a child protothread. The current protothread
phyllis 0:1690a672d017 180 * will block until the child protothread completes.
phyllis 0:1690a672d017 181 *
phyllis 0:1690a672d017 182 * \note The child protothread must be manually initialized with the
phyllis 0:1690a672d017 183 * PT_INIT() function before this function is used.
phyllis 0:1690a672d017 184 *
phyllis 0:1690a672d017 185 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 186 * \param thread The child protothread with arguments
phyllis 0:1690a672d017 187 *
phyllis 0:1690a672d017 188 * \sa PT_SPAWN()
phyllis 0:1690a672d017 189 *
phyllis 0:1690a672d017 190 * \hideinitializer
phyllis 0:1690a672d017 191 */
phyllis 0:1690a672d017 192 #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
phyllis 0:1690a672d017 193
phyllis 0:1690a672d017 194 /**
phyllis 0:1690a672d017 195 * Spawn a child protothread and wait until it exits.
phyllis 0:1690a672d017 196 *
phyllis 0:1690a672d017 197 * This macro spawns a child protothread and waits until it exits. The
phyllis 0:1690a672d017 198 * macro can only be used within a protothread.
phyllis 0:1690a672d017 199 *
phyllis 0:1690a672d017 200 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 201 * \param child A pointer to the child protothread's control structure.
phyllis 0:1690a672d017 202 * \param thread The child protothread with arguments
phyllis 0:1690a672d017 203 *
phyllis 0:1690a672d017 204 * \hideinitializer
phyllis 0:1690a672d017 205 */
phyllis 0:1690a672d017 206 #define PT_SPAWN(pt, child, thread) \
phyllis 0:1690a672d017 207 do { \
phyllis 0:1690a672d017 208 PT_INIT((child)); \
phyllis 0:1690a672d017 209 PT_WAIT_THREAD((pt), (thread)); \
phyllis 0:1690a672d017 210 } while(0)
phyllis 0:1690a672d017 211
phyllis 0:1690a672d017 212 /** @} */
phyllis 0:1690a672d017 213
phyllis 0:1690a672d017 214 /**
phyllis 0:1690a672d017 215 * \name Exiting and restarting
phyllis 0:1690a672d017 216 * @{
phyllis 0:1690a672d017 217 */
phyllis 0:1690a672d017 218
phyllis 0:1690a672d017 219 /**
phyllis 0:1690a672d017 220 * Restart the protothread.
phyllis 0:1690a672d017 221 *
phyllis 0:1690a672d017 222 * This macro will block and cause the running protothread to restart
phyllis 0:1690a672d017 223 * its execution at the place of the PT_BEGIN() call.
phyllis 0:1690a672d017 224 *
phyllis 0:1690a672d017 225 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 226 *
phyllis 0:1690a672d017 227 * \hideinitializer
phyllis 0:1690a672d017 228 */
phyllis 0:1690a672d017 229 #define PT_RESTART(pt) \
phyllis 0:1690a672d017 230 do { \
phyllis 0:1690a672d017 231 PT_INIT(pt); \
phyllis 0:1690a672d017 232 return PT_WAITING; \
phyllis 0:1690a672d017 233 } while(0)
phyllis 0:1690a672d017 234
phyllis 0:1690a672d017 235 /**
phyllis 0:1690a672d017 236 * Exit the protothread.
phyllis 0:1690a672d017 237 *
phyllis 0:1690a672d017 238 * This macro causes the protothread to exit. If the protothread was
phyllis 0:1690a672d017 239 * spawned by another protothread, the parent protothread will become
phyllis 0:1690a672d017 240 * unblocked and can continue to run.
phyllis 0:1690a672d017 241 *
phyllis 0:1690a672d017 242 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 243 *
phyllis 0:1690a672d017 244 * \hideinitializer
phyllis 0:1690a672d017 245 */
phyllis 0:1690a672d017 246 #define PT_EXIT(pt) \
phyllis 0:1690a672d017 247 do { \
phyllis 0:1690a672d017 248 PT_INIT(pt); \
phyllis 0:1690a672d017 249 return PT_EXITED; \
phyllis 0:1690a672d017 250 } while(0)
phyllis 0:1690a672d017 251
phyllis 0:1690a672d017 252 /** @} */
phyllis 0:1690a672d017 253
phyllis 0:1690a672d017 254 /**
phyllis 0:1690a672d017 255 * \name Calling a protothread
phyllis 0:1690a672d017 256 * @{
phyllis 0:1690a672d017 257 */
phyllis 0:1690a672d017 258
phyllis 0:1690a672d017 259 /**
phyllis 0:1690a672d017 260 * Schedule a protothread.
phyllis 0:1690a672d017 261 *
phyllis 0:1690a672d017 262 * This function shedules a protothread. The return value of the
phyllis 0:1690a672d017 263 * function is non-zero if the protothread is running or zero if the
phyllis 0:1690a672d017 264 * protothread has exited.
phyllis 0:1690a672d017 265 *
phyllis 0:1690a672d017 266 * \param f The call to the C function implementing the protothread to
phyllis 0:1690a672d017 267 * be scheduled
phyllis 0:1690a672d017 268 *
phyllis 0:1690a672d017 269 * \hideinitializer
phyllis 0:1690a672d017 270 */
phyllis 0:1690a672d017 271 #define PT_SCHEDULE(f) ((f) < PT_EXITED)
phyllis 0:1690a672d017 272
phyllis 0:1690a672d017 273 /** @} */
phyllis 0:1690a672d017 274
phyllis 0:1690a672d017 275 /**
phyllis 0:1690a672d017 276 * \name Yielding from a protothread
phyllis 0:1690a672d017 277 * @{
phyllis 0:1690a672d017 278 */
phyllis 0:1690a672d017 279
phyllis 0:1690a672d017 280 /**
phyllis 0:1690a672d017 281 * Yield from the current protothread.
phyllis 0:1690a672d017 282 *
phyllis 0:1690a672d017 283 * This function will yield the protothread, thereby allowing other
phyllis 0:1690a672d017 284 * processing to take place in the system.
phyllis 0:1690a672d017 285 *
phyllis 0:1690a672d017 286 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 287 *
phyllis 0:1690a672d017 288 * \hideinitializer
phyllis 0:1690a672d017 289 */
phyllis 0:1690a672d017 290 #define PT_YIELD(pt) \
phyllis 0:1690a672d017 291 do { \
phyllis 0:1690a672d017 292 PT_YIELD_FLAG = 0; \
phyllis 0:1690a672d017 293 LC_SET((pt)->lc); \
phyllis 0:1690a672d017 294 if(PT_YIELD_FLAG == 0) { \
phyllis 0:1690a672d017 295 return PT_YIELDED; \
phyllis 0:1690a672d017 296 } \
phyllis 0:1690a672d017 297 } while(0)
phyllis 0:1690a672d017 298
phyllis 0:1690a672d017 299 /**
phyllis 0:1690a672d017 300 * \brief Yield from the protothread until a condition occurs.
phyllis 0:1690a672d017 301 * \param pt A pointer to the protothread control structure.
phyllis 0:1690a672d017 302 * \param cond The condition.
phyllis 0:1690a672d017 303 *
phyllis 0:1690a672d017 304 * This function will yield the protothread, until the
phyllis 0:1690a672d017 305 * specified condition evaluates to true.
phyllis 0:1690a672d017 306 *
phyllis 0:1690a672d017 307 *
phyllis 0:1690a672d017 308 * \hideinitializer
phyllis 0:1690a672d017 309 */
phyllis 0:1690a672d017 310 #define PT_YIELD_UNTIL(pt, cond) \
phyllis 0:1690a672d017 311 do { \
phyllis 0:1690a672d017 312 PT_YIELD_FLAG = 0; \
phyllis 0:1690a672d017 313 LC_SET((pt)->lc); \
phyllis 0:1690a672d017 314 if((PT_YIELD_FLAG == 0) || !(cond)) { \
phyllis 0:1690a672d017 315 return PT_YIELDED; \
phyllis 0:1690a672d017 316 } \
phyllis 0:1690a672d017 317 } while(0)
phyllis 0:1690a672d017 318
phyllis 0:1690a672d017 319 /** @} */
phyllis 0:1690a672d017 320
phyllis 0:1690a672d017 321 #endif /* __PT_H__ */
phyllis 0:1690a672d017 322
phyllis 0:1690a672d017 323 /** @} */