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