]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/lwIP_Demo_Rowley_ARM7/lwip-1.1.0/src/core/sys.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / lwIP_Demo_Rowley_ARM7 / lwip-1.1.0 / src / core / sys.c
1 /*\r
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without modification,\r
6  * are permitted provided that the following conditions are met:\r
7  *\r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  *    this list of conditions and the following disclaimer.\r
10  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
11  *    this list of conditions and the following disclaimer in the documentation\r
12  *    and/or other materials provided with the distribution.\r
13  * 3. The name of the author may not be used to endorse or promote products\r
14  *    derived from this software without specific prior written permission.\r
15  *\r
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
25  * OF SUCH DAMAGE.\r
26  *\r
27  * This file is part of the lwIP TCP/IP stack.\r
28  *\r
29  * Author: Adam Dunkels <adam@sics.se>\r
30  *\r
31  */\r
32 \r
33 #include "lwip/sys.h"\r
34 #include "lwip/opt.h"\r
35 #include "lwip/def.h"\r
36 #include "lwip/memp.h"\r
37 \r
38 #if (NO_SYS == 0)\r
39 \r
40 struct sswt_cb\r
41 {\r
42     int timeflag;\r
43     sys_sem_t *psem;\r
44 };\r
45 \r
46 \r
47 \r
48 void\r
49 sys_mbox_fetch(sys_mbox_t mbox, void **msg)\r
50 {\r
51   u32_t time;\r
52   struct sys_timeouts *timeouts;\r
53   struct sys_timeout *tmptimeout;\r
54   sys_timeout_handler h;\r
55   void *arg;\r
56 \r
57 \r
58  again:\r
59   timeouts = sys_arch_timeouts();\r
60 \r
61   if (!timeouts || !timeouts->next) {\r
62     sys_arch_mbox_fetch(mbox, msg, 0);\r
63   } else {\r
64     if (timeouts->next->time > 0) {\r
65       time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);\r
66     } else {\r
67       time = SYS_ARCH_TIMEOUT;\r
68     }\r
69 \r
70     if (time == SYS_ARCH_TIMEOUT) {\r
71       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message\r
72    could be fetched. We should now call the timeout handler and\r
73    deallocate the memory allocated for the timeout. */\r
74       tmptimeout = timeouts->next;\r
75       timeouts->next = tmptimeout->next;\r
76       h = tmptimeout->h;\r
77       arg = tmptimeout->arg;\r
78       memp_free(MEMP_SYS_TIMEOUT, tmptimeout);\r
79       if (h != NULL) {\r
80         LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg));\r
81         h(arg);\r
82       }\r
83 \r
84       /* We try again to fetch a message from the mbox. */\r
85       goto again;\r
86     } else {\r
87       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout\r
88    occured. The time variable is set to the number of\r
89    milliseconds we waited for the message. */\r
90       if (time <= timeouts->next->time) {\r
91   timeouts->next->time -= time;\r
92       } else {\r
93   timeouts->next->time = 0;\r
94       }\r
95     }\r
96 \r
97   }\r
98 }\r
99 \r
100 void\r
101 sys_sem_wait(sys_sem_t sem)\r
102 {\r
103   u32_t time;\r
104   struct sys_timeouts *timeouts;\r
105   struct sys_timeout *tmptimeout;\r
106   sys_timeout_handler h;\r
107   void *arg;\r
108 \r
109   /*  while (sys_arch_sem_wait(sem, 1000) == 0);\r
110       return;*/\r
111 \r
112  again:\r
113 \r
114   timeouts = sys_arch_timeouts();\r
115 \r
116   if (!timeouts || !timeouts->next) {\r
117     sys_arch_sem_wait(sem, 0);\r
118   } else {\r
119     if (timeouts->next->time > 0) {\r
120       time = sys_arch_sem_wait(sem, timeouts->next->time);\r
121     } else {\r
122       time = SYS_ARCH_TIMEOUT;\r
123     }\r
124 \r
125     if (time == SYS_ARCH_TIMEOUT) {\r
126       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message\r
127    could be fetched. We should now call the timeout handler and\r
128    deallocate the memory allocated for the timeout. */\r
129       tmptimeout = timeouts->next;\r
130       timeouts->next = tmptimeout->next;\r
131       h = tmptimeout->h;\r
132       arg = tmptimeout->arg;\r
133       memp_free(MEMP_SYS_TIMEOUT, tmptimeout);\r
134       if (h != NULL) {\r
135         LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void *)h, (void *)arg));\r
136         h(arg);\r
137       }\r
138 \r
139 \r
140       /* We try again to fetch a message from the mbox. */\r
141       goto again;\r
142     } else {\r
143       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout\r
144    occured. The time variable is set to the number of\r
145    milliseconds we waited for the message. */\r
146       if (time <= timeouts->next->time) {\r
147   timeouts->next->time -= time;\r
148       } else {\r
149   timeouts->next->time = 0;\r
150       }\r
151     }\r
152 \r
153   }\r
154 }\r
155 \r
156 void\r
157 sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)\r
158 {\r
159   struct sys_timeouts *timeouts;\r
160   struct sys_timeout *timeout, *t;\r
161 \r
162   timeout = memp_malloc(MEMP_SYS_TIMEOUT);\r
163   if (timeout == NULL) {\r
164     return;\r
165   }\r
166   timeout->next = NULL;\r
167   timeout->h = h;\r
168   timeout->arg = arg;\r
169   timeout->time = msecs;\r
170 \r
171   timeouts = sys_arch_timeouts();\r
172 \r
173   LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%lu h=%p arg=%p\n",\r
174     (void *)timeout, msecs, (void *)h, (void *)arg));\r
175 \r
176   LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);\r
177 \r
178   if (timeouts->next == NULL) {\r
179     timeouts->next = timeout;\r
180     return;\r
181   }\r
182 \r
183   if (timeouts->next->time > msecs) {\r
184     timeouts->next->time -= msecs;\r
185     timeout->next = timeouts->next;\r
186     timeouts->next = timeout;\r
187   } else {\r
188     for(t = timeouts->next; t != NULL; t = t->next) {\r
189       timeout->time -= t->time;\r
190       if (t->next == NULL || t->next->time > timeout->time) {\r
191         if (t->next != NULL) {\r
192           t->next->time -= timeout->time;\r
193         }\r
194         timeout->next = t->next;\r
195         t->next = timeout;\r
196         break;\r
197       }\r
198     }\r
199   }\r
200 \r
201 }\r
202 \r
203 /* Go through timeout list (for this task only) and remove the first matching entry,\r
204    even though the timeout has not triggered yet.\r
205 */\r
206 \r
207 void\r
208 sys_untimeout(sys_timeout_handler h, void *arg)\r
209 {\r
210     struct sys_timeouts *timeouts;\r
211     struct sys_timeout *prev_t, *t;\r
212 \r
213     timeouts = sys_arch_timeouts();\r
214 \r
215     if (timeouts->next == NULL)\r
216         return;\r
217 \r
218     for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next)\r
219     {\r
220         if ((t->h == h) && (t->arg == arg))\r
221         {\r
222             /* We have a match */\r
223             /* Unlink from previous in list */\r
224             if (prev_t == NULL)\r
225                 timeouts->next = t->next;\r
226             else\r
227                 prev_t->next = t->next;\r
228             /* If not the last one, add time of this one back to next */\r
229             if (t->next != NULL)\r
230                 t->next->time += t->time;\r
231             memp_free(MEMP_SYS_TIMEOUT, t);\r
232             return;\r
233         }\r
234     }\r
235     return;\r
236 }\r
237 \r
238 \r
239 \r
240 \r
241 \r
242 static void\r
243 sswt_handler(void *arg)\r
244 {\r
245     struct sswt_cb *sswt_cb = (struct sswt_cb *) arg;\r
246 \r
247     /* Timeout. Set flag to TRUE and signal semaphore */\r
248     sswt_cb->timeflag = 1;\r
249     sys_sem_signal(*(sswt_cb->psem));\r
250 }\r
251 \r
252 /* Wait for a semaphore with timeout (specified in ms) */\r
253 /* timeout = 0: wait forever */\r
254 /* Returns 0 on timeout. 1 otherwise */\r
255 \r
256 int\r
257 sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)\r
258 {\r
259     struct sswt_cb sswt_cb;\r
260 \r
261     sswt_cb.psem = &sem;\r
262     sswt_cb.timeflag = 0;\r
263 \r
264     /* If timeout is zero, then just wait forever */\r
265     if (timeout > 0)\r
266         /* Create a timer and pass it the address of our flag */\r
267         sys_timeout(timeout, sswt_handler, &sswt_cb);\r
268     sys_sem_wait(sem);\r
269     /* Was it a timeout? */\r
270     if (sswt_cb.timeflag)\r
271     {\r
272         /* timeout */\r
273         return 0;\r
274     } else {\r
275         /* Not a timeout. Remove timeout entry */\r
276         sys_untimeout(sswt_handler, &sswt_cb);\r
277         return 1;\r
278     }\r
279 \r
280 }\r
281 \r
282 \r
283 void\r
284 sys_msleep(u32_t ms)\r
285 {\r
286   sys_sem_t delaysem = sys_sem_new(0);\r
287 \r
288   sys_sem_wait_timeout(delaysem, ms);\r
289 \r
290   sys_sem_free(delaysem);\r
291 }\r
292 \r
293 \r
294 #endif /* NO_SYS */\r