HW2 implemented using protothread

Dependencies:   mbed

Committer:
the729
Date:
Wed Dec 01 02:53:56 2010 +0000
Revision:
0:e2cc8ae74a24

        

Who changed what in which revision?

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