2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
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.
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
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
36 #include "lwip/memp.h"
49 sys_mbox_fetch(sys_mbox_t mbox
, void **msg
)
52 struct sys_timeouts
*timeouts
;
53 struct sys_timeout
*tmptimeout
;
54 sys_timeout_handler h
;
59 timeouts
= sys_arch_timeouts();
61 if (!timeouts
|| !timeouts
->next
) {
62 sys_arch_mbox_fetch(mbox
, msg
, 0);
64 if (timeouts
->next
->time
> 0) {
65 time
= sys_arch_mbox_fetch(mbox
, msg
, timeouts
->next
->time
);
67 time
= SYS_ARCH_TIMEOUT
;
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
;
77 arg
= tmptimeout
->arg
;
78 memp_free(MEMP_SYS_TIMEOUT
, tmptimeout
);
80 LWIP_DEBUGF(SYS_DEBUG
, ("smf calling h=%p(%p)\n", (void *)h
, (void *)arg
));
84 /* We try again to fetch a message from the mbox. */
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
;
93 timeouts
->next
->time
= 0;
101 sys_sem_wait(sys_sem_t sem
)
104 struct sys_timeouts
*timeouts
;
105 struct sys_timeout
*tmptimeout
;
106 sys_timeout_handler h
;
109 /* while (sys_arch_sem_wait(sem, 1000) == 0);
114 timeouts
= sys_arch_timeouts();
116 if (!timeouts
|| !timeouts
->next
) {
117 sys_arch_sem_wait(sem
, 0);
119 if (timeouts
->next
->time
> 0) {
120 time
= sys_arch_sem_wait(sem
, timeouts
->next
->time
);
122 time
= SYS_ARCH_TIMEOUT
;
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
;
132 arg
= tmptimeout
->arg
;
133 memp_free(MEMP_SYS_TIMEOUT
, tmptimeout
);
135 LWIP_DEBUGF(SYS_DEBUG
, ("ssw h=%p(%p)\n", (void *)h
, (void *)arg
));
140 /* We try again to fetch a message from the mbox. */
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
;
149 timeouts
->next
->time
= 0;
157 sys_timeout(u32_t msecs
, sys_timeout_handler h
, void *arg
)
159 struct sys_timeouts
*timeouts
;
160 struct sys_timeout
*timeout
, *t
;
162 timeout
= memp_malloc(MEMP_SYS_TIMEOUT
);
163 if (timeout
== NULL
) {
166 timeout
->next
= NULL
;
169 timeout
->time
= msecs
;
171 timeouts
= sys_arch_timeouts();
173 LWIP_DEBUGF(SYS_DEBUG
, ("sys_timeout: %p msecs=%"U32_F
" h=%p arg=%p\n",
174 (void *)timeout
, msecs
, (void *)h
, (void *)arg
));
176 LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts
!= NULL
);
178 if (timeouts
->next
== NULL
) {
179 timeouts
->next
= timeout
;
183 if (timeouts
->next
->time
> msecs
) {
184 timeouts
->next
->time
-= msecs
;
185 timeout
->next
= timeouts
->next
;
186 timeouts
->next
= timeout
;
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
;
194 timeout
->next
= t
->next
;
203 /* Go through timeout list (for this task only) and remove the first matching entry,
204 even though the timeout has not triggered yet.
208 sys_untimeout(sys_timeout_handler h
, void *arg
)
210 struct sys_timeouts
*timeouts
;
211 struct sys_timeout
*prev_t
, *t
;
213 timeouts
= sys_arch_timeouts();
215 if (timeouts
->next
== NULL
)
218 for (t
= timeouts
->next
, prev_t
= NULL
; t
!= NULL
; prev_t
= t
, t
= t
->next
)
220 if ((t
->h
== h
) && (t
->arg
== arg
))
222 /* We have a match */
223 /* Unlink from previous in list */
225 timeouts
->next
= t
->next
;
227 prev_t
->next
= t
->next
;
228 /* If not the last one, add time of this one back to next */
230 t
->next
->time
+= t
->time
;
231 memp_free(MEMP_SYS_TIMEOUT
, t
);
243 sswt_handler(void *arg
)
245 struct sswt_cb
*sswt_cb
= (struct sswt_cb
*) arg
;
247 /* Timeout. Set flag to TRUE and signal semaphore */
248 sswt_cb
->timeflag
= 1;
249 sys_sem_signal(*(sswt_cb
->psem
));
252 /* Wait for a semaphore with timeout (specified in ms) */
253 /* timeout = 0: wait forever */
254 /* Returns 0 on timeout. 1 otherwise */
257 sys_sem_wait_timeout(sys_sem_t sem
, u32_t timeout
)
259 struct sswt_cb sswt_cb
;
262 sswt_cb
.timeflag
= 0;
264 /* If timeout is zero, then just wait forever */
266 /* Create a timer and pass it the address of our flag */
267 sys_timeout(timeout
, sswt_handler
, &sswt_cb
);
269 /* Was it a timeout? */
270 if (sswt_cb
.timeflag
)
275 /* Not a timeout. Remove timeout entry */
276 sys_untimeout(sswt_handler
, &sswt_cb
);
286 sys_sem_t delaysem
= sys_sem_new(0);
288 sys_sem_wait_timeout(delaysem
, ms
);
290 sys_sem_free(delaysem
);