dol: initial dol commit
[jump.git] / dol / src / dol / visitor / protothread / lib / pt.h
1 /*
2  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
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  *
33  * $Id: pt.h 1 2010-02-24 13:03:05Z haidw $
34  */
35
36 /**
37  * \addtogroup pt
38  * @{
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 typedef struct _pt {
55   lc_t lc;
56 } pt;
57
58 #define PT_WAITING 0
59 #define PT_YIELDED 1
60 #define PT_EXITED  2
61 #define PT_ENDED   3
62
63 /**
64  * \name Initialization
65  * @{
66  */
67
68 /**
69  * Initialize a protothread.
70  *
71  * Initializes a protothread. Initialization must be done prior to
72  * starting to execute the protothread.
73  *
74  * \param pt A pointer to the protothread control structure.
75  *
76  * \sa PT_SPAWN()
77  *
78  * \hideinitializer
79  */
80 #define PT_INIT(pt)   LC_INIT((pt)->lc)
81
82 /** @} */
83
84 /**
85  * \name Declaration and definition
86  * @{
87  */
88
89 /**
90  * Declaration of a protothread.
91  *
92  * This macro is used to declare a protothread. All protothreads must
93  * be declared with this macro.
94  *
95  * \param name_args The name and arguments of the C function
96  * implementing the protothread.
97  *
98  * \hideinitializer
99  */
100 #define PT_THREAD(name_args) char name_args
101
102 /**
103  * Declare the start of a protothread inside the C function
104  * implementing the protothread.
105  *
106  * This macro is used to declare the starting point of a
107  * protothread. It should be placed at the start of the function in
108  * which the protothread runs. All C statements above the PT_BEGIN()
109  * invokation will be executed each time the protothread is scheduled.
110  *
111  * \param pt A pointer to the protothread control structure.
112  *
113  * \hideinitializer
114  */
115 #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
116
117 /**
118  * Declare the end of a protothread.
119  *
120  * This macro is used for declaring that a protothread ends. It must
121  * always be used together with a matching PT_BEGIN() macro.
122  *
123  * \param pt A pointer to the protothread control structure.
124  *
125  * \hideinitializer
126  */
127 #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
128                    PT_INIT(pt); return PT_ENDED; }
129
130 /** @} */
131
132 /**
133  * \name Blocked wait
134  * @{
135  */
136
137 /**
138  * Block and wait until condition is true.
139  *
140  * This macro blocks the protothread until the specified condition is
141  * true.
142  *
143  * \param pt A pointer to the protothread control structure.
144  * \param condition The condition.
145  *
146  * \hideinitializer
147  */
148 #define PT_WAIT_UNTIL(pt, condition)            \
149   do {                                          \
150     LC_SET((pt)->lc);                           \
151     if(!(condition)) {                          \
152       return PT_WAITING;                        \
153     }                                           \
154   } while(0)
155
156 /**
157  * Block and wait while condition is true.
158  *
159  * This function blocks and waits while condition is true. See
160  * PT_WAIT_UNTIL().
161  *
162  * \param pt A pointer to the protothread control structure.
163  * \param cond The condition.
164  *
165  * \hideinitializer
166  */
167 #define PT_WAIT_WHILE(pt, cond)  PT_WAIT_UNTIL((pt), !(cond))
168
169 /** @} */
170
171 /**
172  * \name Hierarchical protothreads
173  * @{
174  */
175
176 /**
177  * Block and wait until a child protothread completes.
178  *
179  * This macro schedules a child protothread. The current protothread
180  * will block until the child protothread completes.
181  *
182  * \note The child protothread must be manually initialized with the
183  * PT_INIT() function before this function is used.
184  *
185  * \param pt A pointer to the protothread control structure.
186  * \param thread The child protothread with arguments
187  *
188  * \sa PT_SPAWN()
189  *
190  * \hideinitializer
191  */
192 #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
193
194 /**
195  * Spawn a child protothread and wait until it exits.
196  *
197  * This macro spawns a child protothread and waits until it exits. The
198  * macro can only be used within a protothread.
199  *
200  * \param pt A pointer to the protothread control structure.
201  * \param child A pointer to the child protothread's control structure.
202  * \param thread The child protothread with arguments
203  *
204  * \hideinitializer
205  */
206 #define PT_SPAWN(pt, child, thread)             \
207   do {                                          \
208     PT_INIT((child));                           \
209     PT_WAIT_THREAD((pt), (thread));             \
210   } while(0)
211
212 /** @} */
213
214 /**
215  * \name Exiting and restarting
216  * @{
217  */
218
219 /**
220  * Restart the protothread.
221  *
222  * This macro will block and cause the running protothread to restart
223  * its execution at the place of the PT_BEGIN() call.
224  *
225  * \param pt A pointer to the protothread control structure.
226  *
227  * \hideinitializer
228  */
229 #define PT_RESTART(pt)                          \
230   do {                                          \
231     PT_INIT(pt);                                \
232     return PT_WAITING;                  \
233   } while(0)
234
235 /**
236  * Exit the protothread.
237  *
238  * This macro causes the protothread to exit. If the protothread was
239  * spawned by another protothread, the parent protothread will become
240  * unblocked and can continue to run.
241  *
242  * \param pt A pointer to the protothread control structure.
243  *
244  * \hideinitializer
245  */
246 #define PT_EXIT(pt)                             \
247   do {                                          \
248     PT_INIT(pt);                                \
249     return PT_EXITED;                   \
250   } while(0)
251
252 /** @} */
253
254 /**
255  * \name Calling a protothread
256  * @{
257  */
258
259 /**
260  * Schedule a protothread.
261  *
262  * This function shedules a protothread. The return value of the
263  * function is non-zero if the protothread is running or zero if the
264  * protothread has exited.
265  *
266  * \param f The call to the C function implementing the protothread to
267  * be scheduled
268  *
269  * \hideinitializer
270  */
271 #define PT_SCHEDULE(f) ((f) < PT_EXITED)
272
273 /** @} */
274
275 /**
276  * \name Yielding from a protothread
277  * @{
278  */
279
280 /**
281  * Yield from the current protothread.
282  *
283  * This function will yield the protothread, thereby allowing other
284  * processing to take place in the system.
285  *
286  * \param pt A pointer to the protothread control structure.
287  *
288  * \hideinitializer
289  */
290 #define PT_YIELD(pt)                            \
291   do {                                          \
292     PT_YIELD_FLAG = 0;                          \
293     LC_SET((pt)->lc);                           \
294     if(PT_YIELD_FLAG == 0) {                    \
295       return PT_YIELDED;                        \
296     }                                           \
297   } while(0)
298
299 /**
300  * \brief      Yield from the protothread until a condition occurs.
301  * \param pt   A pointer to the protothread control structure.
302  * \param cond The condition.
303  *
304  *             This function will yield the protothread, until the
305  *             specified condition evaluates to true.
306  *
307  *
308  * \hideinitializer
309  */
310 #define PT_YIELD_UNTIL(pt, cond)                \
311   do {                                          \
312     PT_YIELD_FLAG = 0;                          \
313     LC_SET((pt)->lc);                           \
314     if((PT_YIELD_FLAG == 0) || !(cond)) {       \
315       return PT_YIELDED;                        \
316     }                                           \
317   } while(0)
318
319 /** @} */
320
321 #endif /* __PT_H__ */
322
323 /** @} */