Homework2_3Multithreads_YuwenSun

Dependencies:   mbed

Committer:
sun831011
Date:
Tue Nov 30 22:19:29 2010 +0000
Revision:
0:edab293d7652

        

Who changed what in which revision?

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