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