adamdunkels | a2f3c42 | 2004-09-12 20:24:53 +0000 | [diff] [blame] | 1 | /* |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 2 | * Copyright (c) 2004-2005, Swedish Institute of Computer Science. |
adamdunkels | a2f3c42 | 2004-09-12 20:24:53 +0000 | [diff] [blame] | 3 | * All rights reserved. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions |
| 7 | * are met: |
| 8 | * 1. Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer in the |
| 12 | * documentation and/or other materials provided with the distribution. |
| 13 | * 3. Neither the name of the Institute nor the names of its contributors |
| 14 | * may be used to endorse or promote products derived from this software |
| 15 | * without specific prior written permission. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
| 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 | * SUCH DAMAGE. |
| 28 | * |
| 29 | * This file is part of the Contiki operating system. |
| 30 | * |
| 31 | * Author: Adam Dunkels <adam@sics.se> |
| 32 | * |
adamdunkels | 2caed81 | 2005-04-01 09:07:49 +0000 | [diff] [blame] | 33 | * $Id: pt.h,v 1.10 2005/04/01 09:07:49 adamdunkels Exp $ |
adamdunkels | a2f3c42 | 2004-09-12 20:24:53 +0000 | [diff] [blame] | 34 | */ |
| 35 | |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 36 | /** |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 37 | * \addtogroup pt |
| 38 | * @{ |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 39 | */ |
| 40 | |
| 41 | /** |
| 42 | * \file |
| 43 | * Protothreads implementation. |
| 44 | * \author |
| 45 | * Adam Dunkels <adam@sics.se> |
| 46 | * |
| 47 | */ |
| 48 | |
| 49 | #ifndef __PT_H__ |
| 50 | #define __PT_H__ |
| 51 | |
| 52 | #include "lc.h" |
| 53 | |
| 54 | struct pt { |
| 55 | lc_t lc; |
| 56 | }; |
| 57 | |
| 58 | #define PT_THREAD_WAITING 0 |
| 59 | #define PT_THREAD_EXITED 1 |
| 60 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 61 | /** |
| 62 | * Declaration of a protothread. |
| 63 | * |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 64 | * This macro is used to declare a protothread. All protothreads must |
| 65 | * be declared with this macro. |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 66 | * |
| 67 | * Example: |
| 68 | \code |
| 69 | PT_THREAD(consumer(struct pt *p, int event)) { |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 70 | PT_BEGIN(p); |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 71 | while(1) { |
adamdunkels | a5f1e79 | 2005-04-01 08:13:45 +0000 | [diff] [blame] | 72 | PT_WAIT_UNTIL(p, event == AVAILABLE); |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 73 | consume(); |
adamdunkels | a5f1e79 | 2005-04-01 08:13:45 +0000 | [diff] [blame] | 74 | PT_WAIT_UNTIL(p, event == CONSUMED); |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 75 | acknowledge_consumed(); |
| 76 | } |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 77 | PT_END(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 78 | } |
| 79 | \endcode |
| 80 | * |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 81 | * \param name_args The name and arguments of the C function |
| 82 | * implementing the protothread. |
| 83 | * |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 84 | * \hideinitializer |
| 85 | */ |
| 86 | #define PT_THREAD(name_args) char name_args |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 87 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 88 | /** |
| 89 | * Initialize a protothread. |
| 90 | * |
| 91 | * Initializes a protothread. Initialization must be done prior to |
| 92 | * starting to execute the protothread. |
| 93 | * |
| 94 | * \param pt A pointer to the protothread control structure. |
| 95 | * |
| 96 | * Example: |
| 97 | * |
| 98 | \code |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 99 | void main(void) { |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 100 | struct pt p; |
| 101 | int event; |
| 102 | |
| 103 | PT_INIT(&p); |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 104 | while(PT_SCHEDULE(consumer(&p, event))) { |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 105 | event = get_event(); |
| 106 | } |
| 107 | } |
| 108 | \endcode |
| 109 | * |
adamdunkels | a5f1e79 | 2005-04-01 08:13:45 +0000 | [diff] [blame] | 110 | * \sa PT_SPAWN() |
| 111 | * |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 112 | * \hideinitializer |
| 113 | */ |
adamdunkels | 1f7f652 | 2005-03-14 13:53:37 +0000 | [diff] [blame] | 114 | #define PT_INIT(pt) LC_INIT((pt)->lc) |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 115 | |
| 116 | /** |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 117 | * Declare the start of a protothread inside the C function |
| 118 | * implementing the protothread. |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 119 | * |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 120 | * This macro is used to declare the starting point of a |
| 121 | * protothread. It should be placed at the start of the function in |
| 122 | * which the protothread runs. All C statements above the PT_BEGIN() |
| 123 | * invokation will be executed each time the protothread is scheduled. |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 124 | * |
| 125 | * \param pt A pointer to the protothread control structure. |
| 126 | * |
| 127 | * Example: |
| 128 | * |
| 129 | \code |
| 130 | PT_THREAD(producer(struct pt *p, int event)) { |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 131 | PT_BEGIN(p); |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 132 | while(1) { |
adamdunkels | a5f1e79 | 2005-04-01 08:13:45 +0000 | [diff] [blame] | 133 | PT_WAIT_UNTIL(p, event == CONSUMED || event == DROPPED); |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 134 | produce(); |
adamdunkels | a5f1e79 | 2005-04-01 08:13:45 +0000 | [diff] [blame] | 135 | PT_WAIT_UNTIL(p, event == PRODUCED); |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 136 | } |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 137 | |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 138 | PT_END(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 139 | } |
| 140 | \endcode |
| 141 | * |
| 142 | * \hideinitializer |
| 143 | */ |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 144 | #define PT_BEGIN(pt) LC_RESUME((pt)->lc) |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 145 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 146 | /** |
| 147 | * Block and wait until condition is true. |
| 148 | * |
| 149 | * This macro blocks the protothread until the specified condition is |
| 150 | * true. |
| 151 | * |
| 152 | * \param pt A pointer to the protothread control structure. |
| 153 | * \param condition The condition. |
| 154 | * |
| 155 | * Example: |
| 156 | \code |
| 157 | PT_THREAD(seconds(struct pt *p)) { |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 158 | PT_BEGIN(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 159 | |
| 160 | PT_WAIT_UNTIL(p, time >= 2 * SECOND); |
| 161 | printf("Two seconds have passed\n"); |
| 162 | |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 163 | PT_END(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 164 | } |
| 165 | \endcode |
| 166 | * |
| 167 | * \hideinitializer |
| 168 | */ |
| 169 | #define PT_WAIT_UNTIL(pt, condition) \ |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 170 | do { \ |
| 171 | LC_SET((pt)->lc); \ |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 172 | if(!(condition)) { \ |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 173 | return PT_THREAD_WAITING; \ |
| 174 | } \ |
| 175 | } while(0) |
| 176 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 177 | /** |
| 178 | * Block and wait while condition is true. |
| 179 | * |
| 180 | * This function blocks and waits while condition is true. See |
| 181 | * PT_WAIT_UNTIL(). |
| 182 | * |
| 183 | * \param pt A pointer to the protothread control structure. |
| 184 | * \param cond The condition. |
| 185 | * |
| 186 | * \hideinitializer |
| 187 | */ |
adamdunkels | 1f7f652 | 2005-03-14 13:53:37 +0000 | [diff] [blame] | 188 | #define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond)) |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 189 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 190 | |
| 191 | /** |
| 192 | * Block and wait until a child protothread completes. |
| 193 | * |
| 194 | * This macro schedules a child protothread. The current protothread |
adamdunkels | c7fd77d | 2004-08-17 20:35:46 +0000 | [diff] [blame] | 195 | * will block until the child protothread completes. |
| 196 | * |
| 197 | * \note The child protothread must be manually initialized with the |
| 198 | * PT_INIT() function before this function is used. |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 199 | * |
| 200 | * \param pt A pointer to the protothread control structure. |
adamdunkels | c7fd77d | 2004-08-17 20:35:46 +0000 | [diff] [blame] | 201 | * \param thread The child protothread with arguments |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 202 | * |
| 203 | * Example: |
| 204 | \code |
| 205 | PT_THREAD(child(struct pt *p, int event)) { |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 206 | PT_BEGIN(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 207 | |
adamdunkels | a5f1e79 | 2005-04-01 08:13:45 +0000 | [diff] [blame] | 208 | PT_WAIT_UNTIL(p, event == EVENT1); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 209 | |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 210 | PT_END(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | PT_THREAD(parent(struct pt *p, struct pt *child_pt, int event)) { |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 214 | PT_BEGIN(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 215 | |
| 216 | PT_INIT(child_pt); |
| 217 | |
| 218 | PT_WAIT_THREAD(p, child(child_pt, event)); |
| 219 | |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 220 | PT_END(p); |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 221 | } |
| 222 | \endcode |
| 223 | * |
adamdunkels | a5f1e79 | 2005-04-01 08:13:45 +0000 | [diff] [blame] | 224 | * \sa PT_SPAWN() |
| 225 | * |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 226 | * \hideinitializer |
| 227 | */ |
adamdunkels | 1f7f652 | 2005-03-14 13:53:37 +0000 | [diff] [blame] | 228 | #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread)) |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 229 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 230 | /** |
adamdunkels | 73e70f4 | 2004-08-20 21:26:02 +0000 | [diff] [blame] | 231 | * Spawn a child protothread and wait until it exits. |
| 232 | * |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 233 | * This macro spawns a child protothread and waits until it exits. The |
| 234 | * macro can only be used within a protothread. |
adamdunkels | 73e70f4 | 2004-08-20 21:26:02 +0000 | [diff] [blame] | 235 | * |
adamdunkels | 2caed81 | 2005-04-01 09:07:49 +0000 | [diff] [blame] | 236 | * Example: |
| 237 | \code |
| 238 | static struct pt parent_pt, child_pt; |
| 239 | int should_spawn_flag; |
| 240 | |
| 241 | PT_THREAD(child(struct pt *pt)) { |
| 242 | PT_BEGIN(pt); |
| 243 | |
| 244 | while(all_items_processed()) { |
| 245 | process_item(); |
| 246 | PT_WAIT_UNTIL(pt, item_processed()); |
| 247 | } |
| 248 | |
| 249 | PT_END(pt); |
| 250 | } |
| 251 | |
| 252 | PT_THREAD(parent(void)) { |
| 253 | PT_BEGIN(&parent_pt); |
| 254 | |
| 255 | if(should_spawn_flag) { |
| 256 | PT_SPAWN(&parent_pt, &child_pt, child(&child_pt)); |
| 257 | } |
| 258 | |
| 259 | PT_END(&parent_pt); |
| 260 | } |
| 261 | \endcode |
| 262 | * |
| 263 | * |
adamdunkels | 73e70f4 | 2004-08-20 21:26:02 +0000 | [diff] [blame] | 264 | * \param pt A pointer to the protothread control structure. |
adamdunkels | 1f7f652 | 2005-03-14 13:53:37 +0000 | [diff] [blame] | 265 | * \param child A pointer to the child protothread's control structure. |
adamdunkels | 73e70f4 | 2004-08-20 21:26:02 +0000 | [diff] [blame] | 266 | * \param thread The child protothread with arguments |
| 267 | * |
| 268 | * \hideinitializer |
| 269 | */ |
adamdunkels | 1f7f652 | 2005-03-14 13:53:37 +0000 | [diff] [blame] | 270 | #define PT_SPAWN(pt, child, thread) \ |
adamdunkels | 73e70f4 | 2004-08-20 21:26:02 +0000 | [diff] [blame] | 271 | do { \ |
adamdunkels | 1f7f652 | 2005-03-14 13:53:37 +0000 | [diff] [blame] | 272 | PT_INIT((child)); \ |
adamdunkels | 73e70f4 | 2004-08-20 21:26:02 +0000 | [diff] [blame] | 273 | PT_WAIT_THREAD((pt), (thread)); \ |
| 274 | } while(0) |
| 275 | |
| 276 | /** |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 277 | * Restart the protothread. |
| 278 | * |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 279 | * This macro will block and cause the running protothread to restart |
| 280 | * its execution at the place of the PT_BEGIN() call. |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 281 | * |
| 282 | * \param pt A pointer to the protothread control structure. |
| 283 | * |
| 284 | * \hideinitializer |
| 285 | */ |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 286 | #define PT_RESTART(pt) \ |
| 287 | do { \ |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 288 | PT_INIT(pt); \ |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 289 | return PT_THREAD_WAITING; \ |
| 290 | } while(0) |
| 291 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 292 | /** |
| 293 | * Exit the protothread. |
| 294 | * |
| 295 | * This macro causes the protothread to exit. If the protothread was |
| 296 | * spawned by another protothread, the parent protothread will become |
| 297 | * unblocked and can continue to run. |
| 298 | * |
| 299 | * \param pt A pointer to the protothread control structure. |
| 300 | * |
| 301 | * \hideinitializer |
| 302 | */ |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 303 | #define PT_EXIT(pt) \ |
| 304 | do { \ |
| 305 | PT_INIT(pt); \ |
| 306 | return PT_THREAD_EXITED; \ |
| 307 | } while(0) |
| 308 | |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 309 | /** |
| 310 | * Declare the end of a protothread. |
| 311 | * |
| 312 | * This macro is used for declaring that a protothread ends. It should |
| 313 | * always be used together with a matching PT_BEGIN() macro. |
| 314 | * |
| 315 | * \param pt A pointer to the protothread control structure. |
| 316 | * |
| 317 | * \hideinitializer |
| 318 | */ |
| 319 | #define PT_END(pt) LC_END((pt)->lc); PT_EXIT(pt) |
| 320 | |
adamdunkels | 70316a9 | 2005-02-22 22:41:04 +0000 | [diff] [blame] | 321 | |
| 322 | /** |
| 323 | * Schedule a protothread. |
| 324 | * |
| 325 | * This function shedules a protothread. The return value of the |
| 326 | * function is non-zero if the protothread is running or zero if the |
| 327 | * protothread has exited. |
| 328 | * |
| 329 | * Example |
| 330 | \code |
| 331 | void main(void) { |
| 332 | struct pt p; |
| 333 | int event; |
| 334 | |
| 335 | PT_INIT(&p); |
| 336 | while(PT_SCHEDULE(consumer(&p, event))) { |
| 337 | event = get_event(); |
| 338 | } |
| 339 | } |
| 340 | \endcode |
| 341 | * |
| 342 | * \param f The call to the C function implementing the protothread to |
| 343 | * be scheduled |
| 344 | * |
| 345 | * \hideinitializer |
| 346 | */ |
| 347 | #define PT_SCHEDULE(f) (f == PT_THREAD_WAITING) |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 348 | |
adamdunkels | 1f7f652 | 2005-03-14 13:53:37 +0000 | [diff] [blame] | 349 | /** |
| 350 | * Declarare that a protothread can yield. |
| 351 | * |
| 352 | * If a protothread should be able to yield with the PT_YIELD() |
| 353 | * statement, this flag must be placed first in the protothread's |
| 354 | * function body. |
| 355 | * |
| 356 | * Example: |
| 357 | \code |
| 358 | static |
| 359 | PT_THREAD(loop_thread(struct pt *pt)) |
| 360 | { |
| 361 | PT_YIELDING(); |
| 362 | static int i; |
| 363 | |
| 364 | PT_BEGIN(pt); |
| 365 | |
| 366 | for(i = 0; i < 200; ++i) { |
| 367 | handle_item(i); |
| 368 | PT_YIELD(pt); |
| 369 | } |
| 370 | |
| 371 | PT_END(pt); |
| 372 | } |
| 373 | \endcode |
| 374 | * |
| 375 | * \hideinitializer |
| 376 | */ |
| 377 | #define PT_YIELDING() char pt_yielded = 1 |
| 378 | |
| 379 | /** |
| 380 | * Yield from the current protothread. |
| 381 | * |
| 382 | * This function will yield the protothread, thereby allowing other |
| 383 | * processing to take place in the system. |
| 384 | * |
| 385 | * \note The PT_YIELDING() flag must be placed first in the |
| 386 | * protothread's body if the PT_YIELD() function should be used. |
| 387 | * |
| 388 | * Example |
| 389 | \code |
| 390 | static |
| 391 | PT_THREAD(fade(struct pt *pt)) |
| 392 | { |
| 393 | PT_YIELDING(); |
| 394 | static int delay; |
| 395 | |
| 396 | PT_BEGIN(pt); |
| 397 | |
| 398 | for(delay = 3980; delay > 20; delay -= 20) { |
| 399 | leds_red(LEDS_ON); |
| 400 | clock_delay(4000 - delay); |
| 401 | leds_red(LEDS_OFF); |
| 402 | clock_delay(delay); |
| 403 | PT_YIELD(pt); |
| 404 | } |
| 405 | |
| 406 | PT_END(pt); |
| 407 | } |
| 408 | \endcode |
| 409 | * \param pt A pointer to the protothread control structure. |
| 410 | * |
| 411 | * \hideinitializer |
| 412 | */ |
| 413 | #define PT_YIELD(pt) \ |
| 414 | do { \ |
| 415 | pt_yielded = 0; \ |
| 416 | PT_WAIT_UNTIL(pt, pt_yielded); \ |
| 417 | } while(0) |
| 418 | |
adamdunkels | ebd157c | 2004-08-14 21:52:09 +0000 | [diff] [blame] | 419 | #endif /* __PT_H__ */ |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 420 | |
adamdunkels | f2fd9c1 | 2004-09-01 18:24:04 +0000 | [diff] [blame] | 421 | |
adamdunkels | 1706254 | 2004-08-15 22:04:43 +0000 | [diff] [blame] | 422 | /** @} */ |