1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2017 Simon Goldschmidt
3*10465441SEvalZero * All rights reserved.
4*10465441SEvalZero *
5*10465441SEvalZero * Redistribution and use in source and binary forms, with or without modification,
6*10465441SEvalZero * are permitted provided that the following conditions are met:
7*10465441SEvalZero *
8*10465441SEvalZero * 1. Redistributions of source code must retain the above copyright notice,
9*10465441SEvalZero * this list of conditions and the following disclaimer.
10*10465441SEvalZero * 2. Redistributions in binary form must reproduce the above copyright notice,
11*10465441SEvalZero * this list of conditions and the following disclaimer in the documentation
12*10465441SEvalZero * and/or other materials provided with the distribution.
13*10465441SEvalZero * 3. The name of the author may not be used to endorse or promote products
14*10465441SEvalZero * derived from this software without specific prior written permission.
15*10465441SEvalZero *
16*10465441SEvalZero * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17*10465441SEvalZero * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18*10465441SEvalZero * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19*10465441SEvalZero * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20*10465441SEvalZero * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21*10465441SEvalZero * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*10465441SEvalZero * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*10465441SEvalZero * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24*10465441SEvalZero * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25*10465441SEvalZero * OF SUCH DAMAGE.
26*10465441SEvalZero *
27*10465441SEvalZero * This file is part of the lwIP TCP/IP stack.
28*10465441SEvalZero *
29*10465441SEvalZero * Author: Simon Goldschmidt
30*10465441SEvalZero *
31*10465441SEvalZero */
32*10465441SEvalZero
33*10465441SEvalZero
34*10465441SEvalZero #include <lwip/opt.h>
35*10465441SEvalZero #include <lwip/arch.h>
36*10465441SEvalZero #if !NO_SYS
37*10465441SEvalZero #include "sys_arch.h"
38*10465441SEvalZero #endif
39*10465441SEvalZero #include <lwip/stats.h>
40*10465441SEvalZero #include <lwip/debug.h>
41*10465441SEvalZero #include <lwip/sys.h>
42*10465441SEvalZero
43*10465441SEvalZero #include <string.h>
44*10465441SEvalZero
45*10465441SEvalZero u32_t lwip_sys_now;
46*10465441SEvalZero
47*10465441SEvalZero u32_t
sys_jiffies(void)48*10465441SEvalZero sys_jiffies(void)
49*10465441SEvalZero {
50*10465441SEvalZero return lwip_sys_now;
51*10465441SEvalZero }
52*10465441SEvalZero
53*10465441SEvalZero u32_t
sys_now(void)54*10465441SEvalZero sys_now(void)
55*10465441SEvalZero {
56*10465441SEvalZero return lwip_sys_now;
57*10465441SEvalZero }
58*10465441SEvalZero
59*10465441SEvalZero void
sys_init(void)60*10465441SEvalZero sys_init(void)
61*10465441SEvalZero {
62*10465441SEvalZero }
63*10465441SEvalZero
64*10465441SEvalZero #if !NO_SYS
65*10465441SEvalZero
66*10465441SEvalZero test_sys_arch_waiting_fn the_waiting_fn;
67*10465441SEvalZero
68*10465441SEvalZero void
test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn)69*10465441SEvalZero test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn)
70*10465441SEvalZero {
71*10465441SEvalZero the_waiting_fn = waiting_fn;
72*10465441SEvalZero }
73*10465441SEvalZero
74*10465441SEvalZero err_t
sys_sem_new(sys_sem_t * sem,u8_t count)75*10465441SEvalZero sys_sem_new(sys_sem_t *sem, u8_t count)
76*10465441SEvalZero {
77*10465441SEvalZero LWIP_ASSERT("sem != NULL", sem != NULL);
78*10465441SEvalZero *sem = count + 1;
79*10465441SEvalZero return ERR_OK;
80*10465441SEvalZero }
81*10465441SEvalZero
82*10465441SEvalZero void
sys_sem_free(sys_sem_t * sem)83*10465441SEvalZero sys_sem_free(sys_sem_t *sem)
84*10465441SEvalZero {
85*10465441SEvalZero LWIP_ASSERT("sem != NULL", sem != NULL);
86*10465441SEvalZero *sem = 0;
87*10465441SEvalZero }
88*10465441SEvalZero
89*10465441SEvalZero void
sys_sem_set_invalid(sys_sem_t * sem)90*10465441SEvalZero sys_sem_set_invalid(sys_sem_t *sem)
91*10465441SEvalZero {
92*10465441SEvalZero LWIP_ASSERT("sem != NULL", sem != NULL);
93*10465441SEvalZero *sem = 0;
94*10465441SEvalZero }
95*10465441SEvalZero
96*10465441SEvalZero /* semaphores are 1-based because RAM is initialized as 0, which would be valid */
97*10465441SEvalZero u32_t
sys_arch_sem_wait(sys_sem_t * sem,u32_t timeout)98*10465441SEvalZero sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
99*10465441SEvalZero {
100*10465441SEvalZero u32_t ret = 0;
101*10465441SEvalZero LWIP_ASSERT("sem != NULL", sem != NULL);
102*10465441SEvalZero LWIP_ASSERT("*sem > 0", *sem > 0);
103*10465441SEvalZero if (*sem == 1) {
104*10465441SEvalZero /* need to wait */
105*10465441SEvalZero if(!timeout)
106*10465441SEvalZero {
107*10465441SEvalZero /* wait infinite */
108*10465441SEvalZero LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
109*10465441SEvalZero do {
110*10465441SEvalZero int expectSomething = the_waiting_fn(sem, NULL);
111*10465441SEvalZero LWIP_ASSERT("*sem > 0", *sem > 0);
112*10465441SEvalZero LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
113*10465441SEvalZero ret++;
114*10465441SEvalZero if (ret == SYS_ARCH_TIMEOUT) {
115*10465441SEvalZero ret--;
116*10465441SEvalZero }
117*10465441SEvalZero } while(*sem == 1);
118*10465441SEvalZero }
119*10465441SEvalZero else
120*10465441SEvalZero {
121*10465441SEvalZero if (the_waiting_fn) {
122*10465441SEvalZero int expectSomething = the_waiting_fn(sem, NULL);
123*10465441SEvalZero LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
124*10465441SEvalZero }
125*10465441SEvalZero LWIP_ASSERT("*sem > 0", *sem > 0);
126*10465441SEvalZero if (*sem == 1) {
127*10465441SEvalZero return SYS_ARCH_TIMEOUT;
128*10465441SEvalZero }
129*10465441SEvalZero ret = 1;
130*10465441SEvalZero }
131*10465441SEvalZero }
132*10465441SEvalZero LWIP_ASSERT("*sem > 0", *sem > 0);
133*10465441SEvalZero (*sem)--;
134*10465441SEvalZero LWIP_ASSERT("*sem > 0", *sem > 0);
135*10465441SEvalZero /* return the time we waited for the sem */
136*10465441SEvalZero return ret;
137*10465441SEvalZero }
138*10465441SEvalZero
139*10465441SEvalZero void
sys_sem_signal(sys_sem_t * sem)140*10465441SEvalZero sys_sem_signal(sys_sem_t *sem)
141*10465441SEvalZero {
142*10465441SEvalZero LWIP_ASSERT("sem != NULL", sem != NULL);
143*10465441SEvalZero LWIP_ASSERT("*sem > 0", *sem > 0);
144*10465441SEvalZero (*sem)++;
145*10465441SEvalZero LWIP_ASSERT("*sem > 0", *sem > 0);
146*10465441SEvalZero }
147*10465441SEvalZero
148*10465441SEvalZero err_t
sys_mutex_new(sys_mutex_t * mutex)149*10465441SEvalZero sys_mutex_new(sys_mutex_t *mutex)
150*10465441SEvalZero {
151*10465441SEvalZero LWIP_ASSERT("mutex != NULL", mutex != NULL);
152*10465441SEvalZero *mutex = 1; /* 1 allocated */
153*10465441SEvalZero return ERR_OK;
154*10465441SEvalZero }
155*10465441SEvalZero
156*10465441SEvalZero void
sys_mutex_free(sys_mutex_t * mutex)157*10465441SEvalZero sys_mutex_free(sys_mutex_t *mutex)
158*10465441SEvalZero {
159*10465441SEvalZero /* parameter check */
160*10465441SEvalZero LWIP_ASSERT("mutex != NULL", mutex != NULL);
161*10465441SEvalZero LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
162*10465441SEvalZero *mutex = 0;
163*10465441SEvalZero }
164*10465441SEvalZero
165*10465441SEvalZero void
sys_mutex_set_invalid(sys_mutex_t * mutex)166*10465441SEvalZero sys_mutex_set_invalid(sys_mutex_t *mutex)
167*10465441SEvalZero {
168*10465441SEvalZero LWIP_ASSERT("mutex != NULL", mutex != NULL);
169*10465441SEvalZero *mutex = 0;
170*10465441SEvalZero }
171*10465441SEvalZero
172*10465441SEvalZero void
sys_mutex_lock(sys_mutex_t * mutex)173*10465441SEvalZero sys_mutex_lock(sys_mutex_t *mutex)
174*10465441SEvalZero {
175*10465441SEvalZero /* nothing to do, no multithreading supported */
176*10465441SEvalZero LWIP_ASSERT("mutex != NULL", mutex != NULL);
177*10465441SEvalZero /* check that the mutext is valid and unlocked (no nested locking) */
178*10465441SEvalZero LWIP_ASSERT("*mutex >= 1", *mutex == 1);
179*10465441SEvalZero /* we count up just to check the correct pairing of lock/unlock */
180*10465441SEvalZero (*mutex)++;
181*10465441SEvalZero LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
182*10465441SEvalZero }
183*10465441SEvalZero
184*10465441SEvalZero void
sys_mutex_unlock(sys_mutex_t * mutex)185*10465441SEvalZero sys_mutex_unlock(sys_mutex_t *mutex)
186*10465441SEvalZero {
187*10465441SEvalZero /* nothing to do, no multithreading supported */
188*10465441SEvalZero LWIP_ASSERT("mutex != NULL", mutex != NULL);
189*10465441SEvalZero LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
190*10465441SEvalZero /* we count down just to check the correct pairing of lock/unlock */
191*10465441SEvalZero (*mutex)--;
192*10465441SEvalZero LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
193*10465441SEvalZero }
194*10465441SEvalZero
195*10465441SEvalZero
196*10465441SEvalZero sys_thread_t
sys_thread_new(const char * name,lwip_thread_fn function,void * arg,int stacksize,int prio)197*10465441SEvalZero sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
198*10465441SEvalZero {
199*10465441SEvalZero LWIP_UNUSED_ARG(name);
200*10465441SEvalZero LWIP_UNUSED_ARG(function);
201*10465441SEvalZero LWIP_UNUSED_ARG(arg);
202*10465441SEvalZero LWIP_UNUSED_ARG(stacksize);
203*10465441SEvalZero LWIP_UNUSED_ARG(prio);
204*10465441SEvalZero /* threads not supported */
205*10465441SEvalZero return 0;
206*10465441SEvalZero }
207*10465441SEvalZero
208*10465441SEvalZero err_t
sys_mbox_new(sys_mbox_t * mbox,int size)209*10465441SEvalZero sys_mbox_new(sys_mbox_t *mbox, int size)
210*10465441SEvalZero {
211*10465441SEvalZero int mboxsize = size;
212*10465441SEvalZero LWIP_ASSERT("mbox != NULL", mbox != NULL);
213*10465441SEvalZero LWIP_ASSERT("size >= 0", size >= 0);
214*10465441SEvalZero if (size == 0) {
215*10465441SEvalZero mboxsize = 1024;
216*10465441SEvalZero }
217*10465441SEvalZero mbox->head = mbox->tail = 0;
218*10465441SEvalZero mbox->sem = mbox; /* just point to something for sys_mbox_valid() */
219*10465441SEvalZero mbox->q_mem = (void**)malloc(sizeof(void*)*mboxsize);
220*10465441SEvalZero mbox->size = mboxsize;
221*10465441SEvalZero mbox->used = 0;
222*10465441SEvalZero
223*10465441SEvalZero memset(mbox->q_mem, 0, sizeof(void*)*mboxsize);
224*10465441SEvalZero return ERR_OK;
225*10465441SEvalZero }
226*10465441SEvalZero
227*10465441SEvalZero void
sys_mbox_free(sys_mbox_t * mbox)228*10465441SEvalZero sys_mbox_free(sys_mbox_t *mbox)
229*10465441SEvalZero {
230*10465441SEvalZero /* parameter check */
231*10465441SEvalZero LWIP_ASSERT("mbox != NULL", mbox != NULL);
232*10465441SEvalZero LWIP_ASSERT("mbox->sem != NULL", mbox->sem != NULL);
233*10465441SEvalZero LWIP_ASSERT("mbox->sem == mbox", mbox->sem == mbox);
234*10465441SEvalZero LWIP_ASSERT("mbox->q_mem != NULL", mbox->q_mem != NULL);
235*10465441SEvalZero mbox->sem = NULL;
236*10465441SEvalZero free(mbox->q_mem);
237*10465441SEvalZero mbox->q_mem = NULL;
238*10465441SEvalZero }
239*10465441SEvalZero
240*10465441SEvalZero void
sys_mbox_set_invalid(sys_mbox_t * mbox)241*10465441SEvalZero sys_mbox_set_invalid(sys_mbox_t *mbox)
242*10465441SEvalZero {
243*10465441SEvalZero LWIP_ASSERT("mbox != NULL", mbox != NULL);
244*10465441SEvalZero LWIP_ASSERT("mbox->q_mem == NULL", mbox->q_mem == NULL);
245*10465441SEvalZero mbox->sem = NULL;
246*10465441SEvalZero mbox->q_mem = NULL;
247*10465441SEvalZero }
248*10465441SEvalZero
249*10465441SEvalZero void
sys_mbox_post(sys_mbox_t * q,void * msg)250*10465441SEvalZero sys_mbox_post(sys_mbox_t *q, void *msg)
251*10465441SEvalZero {
252*10465441SEvalZero LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
253*10465441SEvalZero LWIP_ASSERT("q->sem == q", q->sem == q);
254*10465441SEvalZero LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
255*10465441SEvalZero LWIP_ASSERT("q->used >= 0", q->used >= 0);
256*10465441SEvalZero LWIP_ASSERT("q->size > 0", q->size > 0);
257*10465441SEvalZero
258*10465441SEvalZero LWIP_ASSERT("mbox already full", q->used < q->size);
259*10465441SEvalZero
260*10465441SEvalZero q->q_mem[q->head] = msg;
261*10465441SEvalZero q->head++;
262*10465441SEvalZero if (q->head >= (unsigned int)q->size) {
263*10465441SEvalZero q->head = 0;
264*10465441SEvalZero }
265*10465441SEvalZero LWIP_ASSERT("mbox is full!", q->head != q->tail);
266*10465441SEvalZero q->used++;
267*10465441SEvalZero }
268*10465441SEvalZero
269*10465441SEvalZero err_t
sys_mbox_trypost(sys_mbox_t * q,void * msg)270*10465441SEvalZero sys_mbox_trypost(sys_mbox_t *q, void *msg)
271*10465441SEvalZero {
272*10465441SEvalZero LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
273*10465441SEvalZero LWIP_ASSERT("q->sem == q", q->sem == q);
274*10465441SEvalZero LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
275*10465441SEvalZero LWIP_ASSERT("q->used >= 0", q->used >= 0);
276*10465441SEvalZero LWIP_ASSERT("q->size > 0", q->size > 0);
277*10465441SEvalZero LWIP_ASSERT("q->used <= q->size", q->used <= q->size);
278*10465441SEvalZero
279*10465441SEvalZero if (q->used == q->size) {
280*10465441SEvalZero return ERR_MEM;
281*10465441SEvalZero }
282*10465441SEvalZero sys_mbox_post(q, msg);
283*10465441SEvalZero return ERR_OK;
284*10465441SEvalZero }
285*10465441SEvalZero
286*10465441SEvalZero err_t
sys_mbox_trypost_fromisr(sys_mbox_t * q,void * msg)287*10465441SEvalZero sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
288*10465441SEvalZero {
289*10465441SEvalZero return sys_mbox_trypost(q, msg);
290*10465441SEvalZero }
291*10465441SEvalZero
292*10465441SEvalZero u32_t
sys_arch_mbox_fetch(sys_mbox_t * q,void ** msg,u32_t timeout)293*10465441SEvalZero sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout)
294*10465441SEvalZero {
295*10465441SEvalZero u32_t ret = 0;
296*10465441SEvalZero u32_t ret2;
297*10465441SEvalZero LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
298*10465441SEvalZero LWIP_ASSERT("q->sem == q", q->sem == q);
299*10465441SEvalZero LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
300*10465441SEvalZero LWIP_ASSERT("q->used >= 0", q->used >= 0);
301*10465441SEvalZero LWIP_ASSERT("q->size > 0", q->size > 0);
302*10465441SEvalZero
303*10465441SEvalZero if (q->used == 0) {
304*10465441SEvalZero /* need to wait */
305*10465441SEvalZero /* need to wait */
306*10465441SEvalZero if(!timeout)
307*10465441SEvalZero {
308*10465441SEvalZero /* wait infinite */
309*10465441SEvalZero LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
310*10465441SEvalZero do {
311*10465441SEvalZero int expectSomething = the_waiting_fn(NULL, q);
312*10465441SEvalZero LWIP_ASSERT("q->used >= 0", q->used >= 0);
313*10465441SEvalZero LWIP_ASSERT("expecting item available but it's 0", !expectSomething || (q->used > 0));
314*10465441SEvalZero ret++;
315*10465441SEvalZero if (ret == SYS_ARCH_TIMEOUT) {
316*10465441SEvalZero ret--;
317*10465441SEvalZero }
318*10465441SEvalZero } while(q->used == 0);
319*10465441SEvalZero }
320*10465441SEvalZero else
321*10465441SEvalZero {
322*10465441SEvalZero if (the_waiting_fn) {
323*10465441SEvalZero int expectSomething = the_waiting_fn(NULL, q);
324*10465441SEvalZero LWIP_ASSERT("expecting item available count but it's 0", !expectSomething || (q->used > 0));
325*10465441SEvalZero }
326*10465441SEvalZero LWIP_ASSERT("q->used >= 0", q->used >= 0);
327*10465441SEvalZero if (q->used == 0) {
328*10465441SEvalZero if(msg) {
329*10465441SEvalZero *msg = NULL;
330*10465441SEvalZero }
331*10465441SEvalZero return SYS_ARCH_TIMEOUT;
332*10465441SEvalZero }
333*10465441SEvalZero ret = 1;
334*10465441SEvalZero }
335*10465441SEvalZero }
336*10465441SEvalZero LWIP_ASSERT("q->used > 0", q->used > 0);
337*10465441SEvalZero ret2 = sys_arch_mbox_tryfetch(q, msg);
338*10465441SEvalZero LWIP_ASSERT("got no message", ret2 == 0);
339*10465441SEvalZero return ret;
340*10465441SEvalZero }
341*10465441SEvalZero
342*10465441SEvalZero u32_t
sys_arch_mbox_tryfetch(sys_mbox_t * q,void ** msg)343*10465441SEvalZero sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
344*10465441SEvalZero {
345*10465441SEvalZero LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
346*10465441SEvalZero LWIP_ASSERT("q->sem == q", q->sem == q);
347*10465441SEvalZero LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
348*10465441SEvalZero LWIP_ASSERT("q->used >= 0", q->used >= 0);
349*10465441SEvalZero LWIP_ASSERT("q->size > 0", q->size > 0);
350*10465441SEvalZero
351*10465441SEvalZero if (!q->used) {
352*10465441SEvalZero return SYS_ARCH_TIMEOUT;
353*10465441SEvalZero }
354*10465441SEvalZero if(msg) {
355*10465441SEvalZero *msg = q->q_mem[q->tail];
356*10465441SEvalZero }
357*10465441SEvalZero
358*10465441SEvalZero q->tail++;
359*10465441SEvalZero if (q->tail >= (unsigned int)q->size) {
360*10465441SEvalZero q->tail = 0;
361*10465441SEvalZero }
362*10465441SEvalZero q->used--;
363*10465441SEvalZero LWIP_ASSERT("q->used >= 0", q->used >= 0);
364*10465441SEvalZero return 0;
365*10465441SEvalZero }
366*10465441SEvalZero
367*10465441SEvalZero #if LWIP_NETCONN_SEM_PER_THREAD
368*10465441SEvalZero #error LWIP_NETCONN_SEM_PER_THREAD==1 not supported
369*10465441SEvalZero #endif /* LWIP_NETCONN_SEM_PER_THREAD */
370*10465441SEvalZero
371*10465441SEvalZero #endif /* !NO_SYS */
372