# uip/pt.h

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
    00003  * All rights reserved.
    00004  *
    00005  * Redistribution and use in source and binary forms, with or without
    00006  * modification, are permitted provided that the following conditions
    00007  * are met:
    00008  * 1. Redistributions of source code must retain the above copyright
    00009  *    notice, this list of conditions and the following disclaimer.
    00010  * 2. Redistributions in binary form must reproduce the above copyright
    00011  *    notice, this list of conditions and the following disclaimer in the
    00012  *    documentation and/or other materials provided with the distribution.
    00013  * 3. Neither the name of the Institute nor the names of its contributors
    00014  *    may be used to endorse or promote products derived from this software
    00015  *    without specific prior written permission.
    00016  *
    00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
    00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
    00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    00027  * SUCH DAMAGE.
    00028  *
    00029  * This file is part of the uIP TCP/IP stack
    00030  *
    00031  * Author: Adam Dunkels <adam@sics.se>
    00032  *
    00033  * $Id: pt.h,v 1.2 2006/06/12 08:00:30 adam Exp $
    00034  */
    00035
    00036 /**
    00037  * \addtogroup pt
    00038  * @{
    00039  */
    00040
    00041 /**
    00042  * \file
    00043  * Protothreads implementation.
    00044  * \author
    00045  * Adam Dunkels <adam@sics.se>
    00046  *
    00047  */
    00048
    00049 #ifndef __PT_H__
    00050 #define __PT_H__
    00051
    00052 #include "lc.h"
    00053
    00054 struct pt {
    00055   lc_t lc;
    00056 };
    00057
    00058 #define PT_WAITING 0
    00059 #define PT_EXITED  1
    00060 #define PT_ENDED   2
    00061 #define PT_YIELDED 3
    00062
    00063 /**
    00064  * \name Initialization
    00065  * @{
    00066  */
    00067
    00068 /**
    00069  * Initialize a protothread.
    00070  *
    00071  * Initializes a protothread. Initialization must be done prior to
    00072  * starting to execute the protothread.
    00073  *
    00074  * \param pt A pointer to the protothread control structure.
    00075  *
    00076  * \sa PT_SPAWN()
    00077  *
    00078  * \hideinitializer
    00079  */
    00080 #define PT_INIT(pt)   LC_INIT((pt)->lc)
    00081
    00082 /** @} */
    00083
    00084 /**
    00085  * \name Declaration and definition
    00086  * @{
    00087  */
    00088
    00089 /**
    00090  * Declaration of a protothread.
    00091  *
    00092  * This macro is used to declare a protothread. All protothreads must
    00093  * be declared with this macro.
    00094  *
    00095  * \param name_args The name and arguments of the C function
    00096  * implementing the protothread.
    00097  *
    00098  * \hideinitializer
    00099  */
    00100 #define PT_THREAD(name_args) char name_args
    00101
    00102 /**
    00103  * Declare the start of a protothread inside the C function
    00104  * implementing the protothread.
    00105  *
    00106  * This macro is used to declare the starting point of a
    00107  * protothread. It should be placed at the start of the function in
    00108  * which the protothread runs. All C statements above the PT_BEGIN()
    00109  * invokation will be executed each time the protothread is scheduled.
    00110  *
    00111  * \param pt A pointer to the protothread control structure.
    00112  *
    00113  * \hideinitializer
    00114  */
    00115 #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
    00116
    00117 /**
    00118  * Declare the end of a protothread.
    00119  *
    00120  * This macro is used for declaring that a protothread ends. It must
    00121  * always be used together with a matching PT_BEGIN() macro.
    00122  *
    00123  * \param pt A pointer to the protothread control structure.
    00124  *
    00125  * \hideinitializer
    00126  */
    00127 #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
    00128                    PT_INIT(pt); return PT_ENDED; }
    00129
    00130 /** @} */
    00131
    00132 /**
    00133  * \name Blocked wait
    00134  * @{
    00135  */
    00136
    00137 /**
    00138  * Block and wait until condition is true.
    00139  *
    00140  * This macro blocks the protothread until the specified condition is
    00141  * true.
    00142  *
    00143  * \param pt A pointer to the protothread control structure.
    00144  * \param condition The condition.
    00145  *
    00146  * \hideinitializer
    00147  */
    00148 #define PT_WAIT_UNTIL(pt, condition)            \
    00149   do {                                          \
    00150     LC_SET((pt)->lc);                           \
    00151     if(!(condition)) {                          \
    00152       return PT_WAITING;                        \
    00153     }                                           \
    00154   } while(0)
    00155
    00156 /**
    00157  * Block and wait while condition is true.
    00158  *
    00159  * This function blocks and waits while condition is true. See
    00160  * PT_WAIT_UNTIL().
    00161  *
    00162  * \param pt A pointer to the protothread control structure.
    00163  * \param cond The condition.
    00164  *
    00165  * \hideinitializer
    00166  */
    00167 #define PT_WAIT_WHILE(pt, cond)  PT_WAIT_UNTIL((pt), !(cond))
    00168
    00169 /** @} */
    00170
    00171 /**
    00172  * \name Hierarchical protothreads
    00173  * @{
    00174  */
    00175
    00176 /**
    00177  * Block and wait until a child protothread completes.
    00178  *
    00179  * This macro schedules a child protothread. The current protothread
    00180  * will block until the child protothread completes.
    00181  *
    00182  * \note The child protothread must be manually initialized with the
    00183  * PT_INIT() function before this function is used.
    00184  *
    00185  * \param pt A pointer to the protothread control structure.
    00186  * \param thread The child protothread with arguments
    00187  *
    00188  * \sa PT_SPAWN()
    00189  *
    00190  * \hideinitializer
    00191  */
    00192 #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
    00193
    00194 /**
    00195  * Spawn a child protothread and wait until it exits.
    00196  *
    00197  * This macro spawns a child protothread and waits until it exits. The
    00198  * macro can only be used within a protothread.
    00199  *
    00200  * \param pt A pointer to the protothread control structure.
    00201  * \param child A pointer to the child protothread's control structure.
    00202  * \param thread The child protothread with arguments
    00203  *
    00204  * \hideinitializer
    00205  */
    00206 #define PT_SPAWN(pt, child, thread)             \
    00207   do {                                          \
    00208     PT_INIT((child));                           \
    00209     PT_WAIT_THREAD((pt), (thread));             \
    00210   } while(0)
    00211
    00212 /** @} */
    00213
    00214 /**
    00215  * \name Exiting and restarting
    00216  * @{
    00217  */
    00218
    00219 /**
    00220  * Restart the protothread.
    00221  *
    00222  * This macro will block and cause the running protothread to restart
    00223  * its execution at the place of the PT_BEGIN() call.
    00224  *
    00225  * \param pt A pointer to the protothread control structure.
    00226  *
    00227  * \hideinitializer
    00228  */
    00229 #define PT_RESTART(pt)                          \
    00230   do {                                          \
    00231     PT_INIT(pt);                                \
    00232     return PT_WAITING;                  \
    00233   } while(0)
    00234
    00235 /**
    00236  * Exit the protothread.
    00237  *
    00238  * This macro causes the protothread to exit. If the protothread was
    00239  * spawned by another protothread, the parent protothread will become
    00240  * unblocked and can continue to run.
    00241  *
    00242  * \param pt A pointer to the protothread control structure.
    00243  *
    00244  * \hideinitializer
    00245  */
    00246 #define PT_EXIT(pt)                             \
    00247   do {                                          \
    00248     PT_INIT(pt);                                \
    00249     return PT_EXITED;                   \
    00250   } while(0)
    00251
    00252 /** @} */
    00253
    00254 /**
    00255  * \name Calling a protothread
    00256  * @{
    00257  */
    00258
    00259 /**
    00260  * Schedule a protothread.
    00261  *
    00262  * This function shedules a protothread. The return value of the
    00263  * function is non-zero if the protothread is running or zero if the
    00264  * protothread has exited.
    00265  *
    00266  * \param f The call to the C function implementing the protothread to
    00267  * be scheduled
    00268  *
    00269  * \hideinitializer
    00270  */
    00271 #define PT_SCHEDULE(f) ((f) == PT_WAITING)
    00272
    00273 /** @} */
    00274
    00275 /**
    00276  * \name Yielding from a protothread
    00277  * @{
    00278  */
    00279
    00280 /**
    00281  * Yield from the current protothread.
    00282  *
    00283  * This function will yield the protothread, thereby allowing other
    00284  * processing to take place in the system.
    00285  *
    00286  * \param pt A pointer to the protothread control structure.
    00287  *
    00288  * \hideinitializer
    00289  */
    00290 #define PT_YIELD(pt)                            \
    00291   do {                                          \
    00292     PT_YIELD_FLAG = 0;                          \
    00293     LC_SET((pt)->lc);                           \
    00294     if(PT_YIELD_FLAG == 0) {                    \
    00295       return PT_YIELDED;                        \
    00296     }                                           \
    00297   } while(0)
    00298
    00299 /**
    00300  * \brief      Yield from the protothread until a condition occurs.
    00301  * \param pt   A pointer to the protothread control structure.
    00302  * \param cond The condition.
    00303  *
    00304  *             This function will yield the protothread, until the
    00305  *             specified condition evaluates to true.
    00306  *
    00307  *
    00308  * \hideinitializer
    00309  */
    00310 #define PT_YIELD_UNTIL(pt, cond)                \
    00311   do {                                          \
    00312     PT_YIELD_FLAG = 0;                          \
    00313     LC_SET((pt)->lc);                           \
    00314     if((PT_YIELD_FLAG == 0) || !(cond)) {       \
    00315       return PT_YIELDED;                        \
    00316     }                                           \
    00317   } while(0)
    00318
    00319 /** @} */
    00320
    00321 #endif /* __PT_H__ */
    00322
    00323 /** @} */