1*10465441SEvalZero /**
2*10465441SEvalZero * @file
3*10465441SEvalZero * Sequential API Main thread module
4*10465441SEvalZero *
5*10465441SEvalZero */
6*10465441SEvalZero
7*10465441SEvalZero /*
8*10465441SEvalZero * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9*10465441SEvalZero * All rights reserved.
10*10465441SEvalZero *
11*10465441SEvalZero * Redistribution and use in source and binary forms, with or without modification,
12*10465441SEvalZero * are permitted provided that the following conditions are met:
13*10465441SEvalZero *
14*10465441SEvalZero * 1. Redistributions of source code must retain the above copyright notice,
15*10465441SEvalZero * this list of conditions and the following disclaimer.
16*10465441SEvalZero * 2. Redistributions in binary form must reproduce the above copyright notice,
17*10465441SEvalZero * this list of conditions and the following disclaimer in the documentation
18*10465441SEvalZero * and/or other materials provided with the distribution.
19*10465441SEvalZero * 3. The name of the author may not be used to endorse or promote products
20*10465441SEvalZero * derived from this software without specific prior written permission.
21*10465441SEvalZero *
22*10465441SEvalZero * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23*10465441SEvalZero * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24*10465441SEvalZero * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25*10465441SEvalZero * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26*10465441SEvalZero * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27*10465441SEvalZero * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*10465441SEvalZero * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*10465441SEvalZero * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30*10465441SEvalZero * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31*10465441SEvalZero * OF SUCH DAMAGE.
32*10465441SEvalZero *
33*10465441SEvalZero * This file is part of the lwIP TCP/IP stack.
34*10465441SEvalZero *
35*10465441SEvalZero * Author: Adam Dunkels <[email protected]>
36*10465441SEvalZero *
37*10465441SEvalZero */
38*10465441SEvalZero
39*10465441SEvalZero #include "lwip/opt.h"
40*10465441SEvalZero
41*10465441SEvalZero #if !NO_SYS /* don't build if not configured for use in lwipopts.h */
42*10465441SEvalZero
43*10465441SEvalZero #include "lwip/sys.h"
44*10465441SEvalZero #include "lwip/memp.h"
45*10465441SEvalZero #include "lwip/mem.h"
46*10465441SEvalZero #include "lwip/pbuf.h"
47*10465441SEvalZero #include "lwip/tcpip.h"
48*10465441SEvalZero #include "lwip/init.h"
49*10465441SEvalZero #include "netif/etharp.h"
50*10465441SEvalZero #include "netif/ppp_oe.h"
51*10465441SEvalZero
52*10465441SEvalZero /* global variables */
53*10465441SEvalZero static tcpip_init_done_fn tcpip_init_done;
54*10465441SEvalZero static void *tcpip_init_done_arg;
55*10465441SEvalZero static sys_mbox_t mbox;
56*10465441SEvalZero
57*10465441SEvalZero #if LWIP_TCPIP_CORE_LOCKING
58*10465441SEvalZero /** The global semaphore to lock the stack. */
59*10465441SEvalZero sys_mutex_t lock_tcpip_core;
60*10465441SEvalZero #endif /* LWIP_TCPIP_CORE_LOCKING */
61*10465441SEvalZero
62*10465441SEvalZero
63*10465441SEvalZero /**
64*10465441SEvalZero * The main lwIP thread. This thread has exclusive access to lwIP core functions
65*10465441SEvalZero * (unless access to them is not locked). Other threads communicate with this
66*10465441SEvalZero * thread using message boxes.
67*10465441SEvalZero *
68*10465441SEvalZero * It also starts all the timers to make sure they are running in the right
69*10465441SEvalZero * thread context.
70*10465441SEvalZero *
71*10465441SEvalZero * @param arg unused argument
72*10465441SEvalZero */
73*10465441SEvalZero static void
tcpip_thread(void * arg)74*10465441SEvalZero tcpip_thread(void *arg)
75*10465441SEvalZero {
76*10465441SEvalZero struct tcpip_msg *msg;
77*10465441SEvalZero LWIP_UNUSED_ARG(arg);
78*10465441SEvalZero
79*10465441SEvalZero if (tcpip_init_done != NULL) {
80*10465441SEvalZero tcpip_init_done(tcpip_init_done_arg);
81*10465441SEvalZero }
82*10465441SEvalZero
83*10465441SEvalZero LOCK_TCPIP_CORE();
84*10465441SEvalZero while (1) { /* MAIN Loop */
85*10465441SEvalZero UNLOCK_TCPIP_CORE();
86*10465441SEvalZero LWIP_TCPIP_THREAD_ALIVE();
87*10465441SEvalZero /* wait for a message, timeouts are processed while waiting */
88*10465441SEvalZero sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
89*10465441SEvalZero LOCK_TCPIP_CORE();
90*10465441SEvalZero switch (msg->type) {
91*10465441SEvalZero #if LWIP_NETCONN
92*10465441SEvalZero case TCPIP_MSG_API:
93*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
94*10465441SEvalZero msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
95*10465441SEvalZero break;
96*10465441SEvalZero #endif /* LWIP_NETCONN */
97*10465441SEvalZero
98*10465441SEvalZero #if !LWIP_TCPIP_CORE_LOCKING_INPUT
99*10465441SEvalZero case TCPIP_MSG_INPKT:
100*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
101*10465441SEvalZero #if LWIP_ETHERNET
102*10465441SEvalZero if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
103*10465441SEvalZero ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
104*10465441SEvalZero } else
105*10465441SEvalZero #endif /* LWIP_ETHERNET */
106*10465441SEvalZero {
107*10465441SEvalZero ip_input(msg->msg.inp.p, msg->msg.inp.netif);
108*10465441SEvalZero }
109*10465441SEvalZero memp_free(MEMP_TCPIP_MSG_INPKT, msg);
110*10465441SEvalZero break;
111*10465441SEvalZero #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
112*10465441SEvalZero
113*10465441SEvalZero #if LWIP_NETIF_API
114*10465441SEvalZero case TCPIP_MSG_NETIFAPI:
115*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
116*10465441SEvalZero msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg));
117*10465441SEvalZero break;
118*10465441SEvalZero #endif /* LWIP_NETIF_API */
119*10465441SEvalZero
120*10465441SEvalZero #if LWIP_TCPIP_TIMEOUT
121*10465441SEvalZero case TCPIP_MSG_TIMEOUT:
122*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
123*10465441SEvalZero sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
124*10465441SEvalZero memp_free(MEMP_TCPIP_MSG_API, msg);
125*10465441SEvalZero break;
126*10465441SEvalZero case TCPIP_MSG_UNTIMEOUT:
127*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
128*10465441SEvalZero sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
129*10465441SEvalZero memp_free(MEMP_TCPIP_MSG_API, msg);
130*10465441SEvalZero break;
131*10465441SEvalZero #endif /* LWIP_TCPIP_TIMEOUT */
132*10465441SEvalZero
133*10465441SEvalZero case TCPIP_MSG_CALLBACK:
134*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
135*10465441SEvalZero msg->msg.cb.function(msg->msg.cb.ctx);
136*10465441SEvalZero memp_free(MEMP_TCPIP_MSG_API, msg);
137*10465441SEvalZero break;
138*10465441SEvalZero
139*10465441SEvalZero case TCPIP_MSG_CALLBACK_STATIC:
140*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
141*10465441SEvalZero msg->msg.cb.function(msg->msg.cb.ctx);
142*10465441SEvalZero break;
143*10465441SEvalZero
144*10465441SEvalZero default:
145*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
146*10465441SEvalZero LWIP_ASSERT("tcpip_thread: invalid message", 0);
147*10465441SEvalZero break;
148*10465441SEvalZero }
149*10465441SEvalZero }
150*10465441SEvalZero }
151*10465441SEvalZero
152*10465441SEvalZero /**
153*10465441SEvalZero * Pass a received packet to tcpip_thread for input processing
154*10465441SEvalZero *
155*10465441SEvalZero * @param p the received packet, p->payload pointing to the Ethernet header or
156*10465441SEvalZero * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
157*10465441SEvalZero * NETIF_FLAG_ETHERNET flags)
158*10465441SEvalZero * @param inp the network interface on which the packet was received
159*10465441SEvalZero */
160*10465441SEvalZero err_t
tcpip_input(struct pbuf * p,struct netif * inp)161*10465441SEvalZero tcpip_input(struct pbuf *p, struct netif *inp)
162*10465441SEvalZero {
163*10465441SEvalZero #if LWIP_TCPIP_CORE_LOCKING_INPUT
164*10465441SEvalZero err_t ret;
165*10465441SEvalZero LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp));
166*10465441SEvalZero LOCK_TCPIP_CORE();
167*10465441SEvalZero #if LWIP_ETHERNET
168*10465441SEvalZero if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
169*10465441SEvalZero ret = ethernet_input(p, inp);
170*10465441SEvalZero } else
171*10465441SEvalZero #endif /* LWIP_ETHERNET */
172*10465441SEvalZero {
173*10465441SEvalZero ret = ip_input(p, inp);
174*10465441SEvalZero }
175*10465441SEvalZero UNLOCK_TCPIP_CORE();
176*10465441SEvalZero return ret;
177*10465441SEvalZero #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
178*10465441SEvalZero struct tcpip_msg *msg;
179*10465441SEvalZero
180*10465441SEvalZero if (!sys_mbox_valid(&mbox)) {
181*10465441SEvalZero return ERR_VAL;
182*10465441SEvalZero }
183*10465441SEvalZero msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
184*10465441SEvalZero if (msg == NULL) {
185*10465441SEvalZero return ERR_MEM;
186*10465441SEvalZero }
187*10465441SEvalZero
188*10465441SEvalZero msg->type = TCPIP_MSG_INPKT;
189*10465441SEvalZero msg->msg.inp.p = p;
190*10465441SEvalZero msg->msg.inp.netif = inp;
191*10465441SEvalZero if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
192*10465441SEvalZero memp_free(MEMP_TCPIP_MSG_INPKT, msg);
193*10465441SEvalZero return ERR_MEM;
194*10465441SEvalZero }
195*10465441SEvalZero return ERR_OK;
196*10465441SEvalZero #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
197*10465441SEvalZero }
198*10465441SEvalZero
199*10465441SEvalZero /**
200*10465441SEvalZero * Call a specific function in the thread context of
201*10465441SEvalZero * tcpip_thread for easy access synchronization.
202*10465441SEvalZero * A function called in that way may access lwIP core code
203*10465441SEvalZero * without fearing concurrent access.
204*10465441SEvalZero *
205*10465441SEvalZero * @param f the function to call
206*10465441SEvalZero * @param ctx parameter passed to f
207*10465441SEvalZero * @param block 1 to block until the request is posted, 0 to non-blocking mode
208*10465441SEvalZero * @return ERR_OK if the function was called, another err_t if not
209*10465441SEvalZero */
210*10465441SEvalZero err_t
tcpip_callback_with_block(tcpip_callback_fn function,void * ctx,u8_t block)211*10465441SEvalZero tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
212*10465441SEvalZero {
213*10465441SEvalZero struct tcpip_msg *msg;
214*10465441SEvalZero
215*10465441SEvalZero if (sys_mbox_valid(&mbox)) {
216*10465441SEvalZero msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
217*10465441SEvalZero if (msg == NULL) {
218*10465441SEvalZero return ERR_MEM;
219*10465441SEvalZero }
220*10465441SEvalZero
221*10465441SEvalZero msg->type = TCPIP_MSG_CALLBACK;
222*10465441SEvalZero msg->msg.cb.function = function;
223*10465441SEvalZero msg->msg.cb.ctx = ctx;
224*10465441SEvalZero if (block) {
225*10465441SEvalZero sys_mbox_post(&mbox, msg);
226*10465441SEvalZero } else {
227*10465441SEvalZero if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
228*10465441SEvalZero memp_free(MEMP_TCPIP_MSG_API, msg);
229*10465441SEvalZero return ERR_MEM;
230*10465441SEvalZero }
231*10465441SEvalZero }
232*10465441SEvalZero return ERR_OK;
233*10465441SEvalZero }
234*10465441SEvalZero return ERR_VAL;
235*10465441SEvalZero }
236*10465441SEvalZero
237*10465441SEvalZero #if LWIP_TCPIP_TIMEOUT
238*10465441SEvalZero /**
239*10465441SEvalZero * call sys_timeout in tcpip_thread
240*10465441SEvalZero *
241*10465441SEvalZero * @param msec time in milliseconds for timeout
242*10465441SEvalZero * @param h function to be called on timeout
243*10465441SEvalZero * @param arg argument to pass to timeout function h
244*10465441SEvalZero * @return ERR_MEM on memory error, ERR_OK otherwise
245*10465441SEvalZero */
246*10465441SEvalZero err_t
tcpip_timeout(u32_t msecs,sys_timeout_handler h,void * arg)247*10465441SEvalZero tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
248*10465441SEvalZero {
249*10465441SEvalZero struct tcpip_msg *msg;
250*10465441SEvalZero
251*10465441SEvalZero if (sys_mbox_valid(&mbox)) {
252*10465441SEvalZero msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
253*10465441SEvalZero if (msg == NULL) {
254*10465441SEvalZero return ERR_MEM;
255*10465441SEvalZero }
256*10465441SEvalZero
257*10465441SEvalZero msg->type = TCPIP_MSG_TIMEOUT;
258*10465441SEvalZero msg->msg.tmo.msecs = msecs;
259*10465441SEvalZero msg->msg.tmo.h = h;
260*10465441SEvalZero msg->msg.tmo.arg = arg;
261*10465441SEvalZero sys_mbox_post(&mbox, msg);
262*10465441SEvalZero return ERR_OK;
263*10465441SEvalZero }
264*10465441SEvalZero return ERR_VAL;
265*10465441SEvalZero }
266*10465441SEvalZero
267*10465441SEvalZero /**
268*10465441SEvalZero * call sys_untimeout in tcpip_thread
269*10465441SEvalZero *
270*10465441SEvalZero * @param msec time in milliseconds for timeout
271*10465441SEvalZero * @param h function to be called on timeout
272*10465441SEvalZero * @param arg argument to pass to timeout function h
273*10465441SEvalZero * @return ERR_MEM on memory error, ERR_OK otherwise
274*10465441SEvalZero */
275*10465441SEvalZero err_t
tcpip_untimeout(sys_timeout_handler h,void * arg)276*10465441SEvalZero tcpip_untimeout(sys_timeout_handler h, void *arg)
277*10465441SEvalZero {
278*10465441SEvalZero struct tcpip_msg *msg;
279*10465441SEvalZero
280*10465441SEvalZero if (sys_mbox_valid(&mbox)) {
281*10465441SEvalZero msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
282*10465441SEvalZero if (msg == NULL) {
283*10465441SEvalZero return ERR_MEM;
284*10465441SEvalZero }
285*10465441SEvalZero
286*10465441SEvalZero msg->type = TCPIP_MSG_UNTIMEOUT;
287*10465441SEvalZero msg->msg.tmo.h = h;
288*10465441SEvalZero msg->msg.tmo.arg = arg;
289*10465441SEvalZero sys_mbox_post(&mbox, msg);
290*10465441SEvalZero return ERR_OK;
291*10465441SEvalZero }
292*10465441SEvalZero return ERR_VAL;
293*10465441SEvalZero }
294*10465441SEvalZero #endif /* LWIP_TCPIP_TIMEOUT */
295*10465441SEvalZero
296*10465441SEvalZero #if LWIP_NETCONN
297*10465441SEvalZero /**
298*10465441SEvalZero * Call the lower part of a netconn_* function
299*10465441SEvalZero * This function is then running in the thread context
300*10465441SEvalZero * of tcpip_thread and has exclusive access to lwIP core code.
301*10465441SEvalZero *
302*10465441SEvalZero * @param apimsg a struct containing the function to call and its parameters
303*10465441SEvalZero * @return ERR_OK if the function was called, another err_t if not
304*10465441SEvalZero */
305*10465441SEvalZero err_t
tcpip_apimsg(struct api_msg * apimsg)306*10465441SEvalZero tcpip_apimsg(struct api_msg *apimsg)
307*10465441SEvalZero {
308*10465441SEvalZero struct tcpip_msg msg;
309*10465441SEvalZero #ifdef LWIP_DEBUG
310*10465441SEvalZero /* catch functions that don't set err */
311*10465441SEvalZero apimsg->msg.err = ERR_VAL;
312*10465441SEvalZero #endif
313*10465441SEvalZero
314*10465441SEvalZero if (sys_mbox_valid(&mbox)) {
315*10465441SEvalZero msg.type = TCPIP_MSG_API;
316*10465441SEvalZero msg.msg.apimsg = apimsg;
317*10465441SEvalZero sys_mbox_post(&mbox, &msg);
318*10465441SEvalZero sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0);
319*10465441SEvalZero return apimsg->msg.err;
320*10465441SEvalZero }
321*10465441SEvalZero return ERR_VAL;
322*10465441SEvalZero }
323*10465441SEvalZero
324*10465441SEvalZero #if LWIP_TCPIP_CORE_LOCKING
325*10465441SEvalZero /**
326*10465441SEvalZero * Call the lower part of a netconn_* function
327*10465441SEvalZero * This function has exclusive access to lwIP core code by locking it
328*10465441SEvalZero * before the function is called.
329*10465441SEvalZero *
330*10465441SEvalZero * @param apimsg a struct containing the function to call and its parameters
331*10465441SEvalZero * @return ERR_OK (only for compatibility fo tcpip_apimsg())
332*10465441SEvalZero */
333*10465441SEvalZero err_t
tcpip_apimsg_lock(struct api_msg * apimsg)334*10465441SEvalZero tcpip_apimsg_lock(struct api_msg *apimsg)
335*10465441SEvalZero {
336*10465441SEvalZero #ifdef LWIP_DEBUG
337*10465441SEvalZero /* catch functions that don't set err */
338*10465441SEvalZero apimsg->msg.err = ERR_VAL;
339*10465441SEvalZero #endif
340*10465441SEvalZero
341*10465441SEvalZero LOCK_TCPIP_CORE();
342*10465441SEvalZero apimsg->function(&(apimsg->msg));
343*10465441SEvalZero UNLOCK_TCPIP_CORE();
344*10465441SEvalZero return apimsg->msg.err;
345*10465441SEvalZero
346*10465441SEvalZero }
347*10465441SEvalZero #endif /* LWIP_TCPIP_CORE_LOCKING */
348*10465441SEvalZero #endif /* LWIP_NETCONN */
349*10465441SEvalZero
350*10465441SEvalZero #if LWIP_NETIF_API
351*10465441SEvalZero #if !LWIP_TCPIP_CORE_LOCKING
352*10465441SEvalZero /**
353*10465441SEvalZero * Much like tcpip_apimsg, but calls the lower part of a netifapi_*
354*10465441SEvalZero * function.
355*10465441SEvalZero *
356*10465441SEvalZero * @param netifapimsg a struct containing the function to call and its parameters
357*10465441SEvalZero * @return error code given back by the function that was called
358*10465441SEvalZero */
359*10465441SEvalZero err_t
tcpip_netifapi(struct netifapi_msg * netifapimsg)360*10465441SEvalZero tcpip_netifapi(struct netifapi_msg* netifapimsg)
361*10465441SEvalZero {
362*10465441SEvalZero struct tcpip_msg msg;
363*10465441SEvalZero
364*10465441SEvalZero if (sys_mbox_valid(&mbox)) {
365*10465441SEvalZero err_t err = sys_sem_new(&netifapimsg->msg.sem, 0);
366*10465441SEvalZero if (err != ERR_OK) {
367*10465441SEvalZero netifapimsg->msg.err = err;
368*10465441SEvalZero return err;
369*10465441SEvalZero }
370*10465441SEvalZero
371*10465441SEvalZero msg.type = TCPIP_MSG_NETIFAPI;
372*10465441SEvalZero msg.msg.netifapimsg = netifapimsg;
373*10465441SEvalZero sys_mbox_post(&mbox, &msg);
374*10465441SEvalZero sys_sem_wait(&netifapimsg->msg.sem);
375*10465441SEvalZero sys_sem_free(&netifapimsg->msg.sem);
376*10465441SEvalZero return netifapimsg->msg.err;
377*10465441SEvalZero }
378*10465441SEvalZero return ERR_VAL;
379*10465441SEvalZero }
380*10465441SEvalZero #else /* !LWIP_TCPIP_CORE_LOCKING */
381*10465441SEvalZero /**
382*10465441SEvalZero * Call the lower part of a netifapi_* function
383*10465441SEvalZero * This function has exclusive access to lwIP core code by locking it
384*10465441SEvalZero * before the function is called.
385*10465441SEvalZero *
386*10465441SEvalZero * @param netifapimsg a struct containing the function to call and its parameters
387*10465441SEvalZero * @return ERR_OK (only for compatibility fo tcpip_netifapi())
388*10465441SEvalZero */
389*10465441SEvalZero err_t
tcpip_netifapi_lock(struct netifapi_msg * netifapimsg)390*10465441SEvalZero tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
391*10465441SEvalZero {
392*10465441SEvalZero LOCK_TCPIP_CORE();
393*10465441SEvalZero netifapimsg->function(&(netifapimsg->msg));
394*10465441SEvalZero UNLOCK_TCPIP_CORE();
395*10465441SEvalZero return netifapimsg->msg.err;
396*10465441SEvalZero }
397*10465441SEvalZero #endif /* !LWIP_TCPIP_CORE_LOCKING */
398*10465441SEvalZero #endif /* LWIP_NETIF_API */
399*10465441SEvalZero
400*10465441SEvalZero /**
401*10465441SEvalZero * Allocate a structure for a static callback message and initialize it.
402*10465441SEvalZero * This is intended to be used to send "static" messages from interrupt context.
403*10465441SEvalZero *
404*10465441SEvalZero * @param function the function to call
405*10465441SEvalZero * @param ctx parameter passed to function
406*10465441SEvalZero * @return a struct pointer to pass to tcpip_trycallback().
407*10465441SEvalZero */
tcpip_callbackmsg_new(tcpip_callback_fn function,void * ctx)408*10465441SEvalZero struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
409*10465441SEvalZero {
410*10465441SEvalZero struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
411*10465441SEvalZero if (msg == NULL) {
412*10465441SEvalZero return NULL;
413*10465441SEvalZero }
414*10465441SEvalZero msg->type = TCPIP_MSG_CALLBACK_STATIC;
415*10465441SEvalZero msg->msg.cb.function = function;
416*10465441SEvalZero msg->msg.cb.ctx = ctx;
417*10465441SEvalZero return (struct tcpip_callback_msg*)msg;
418*10465441SEvalZero }
419*10465441SEvalZero
420*10465441SEvalZero /**
421*10465441SEvalZero * Free a callback message allocated by tcpip_callbackmsg_new().
422*10465441SEvalZero *
423*10465441SEvalZero * @param msg the message to free
424*10465441SEvalZero */
tcpip_callbackmsg_delete(struct tcpip_callback_msg * msg)425*10465441SEvalZero void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
426*10465441SEvalZero {
427*10465441SEvalZero memp_free(MEMP_TCPIP_MSG_API, msg);
428*10465441SEvalZero }
429*10465441SEvalZero
430*10465441SEvalZero /**
431*10465441SEvalZero * Try to post a callback-message to the tcpip_thread mbox
432*10465441SEvalZero * This is intended to be used to send "static" messages from interrupt context.
433*10465441SEvalZero *
434*10465441SEvalZero * @param msg pointer to the message to post
435*10465441SEvalZero * @return sys_mbox_trypost() return code
436*10465441SEvalZero */
437*10465441SEvalZero err_t
tcpip_trycallback(struct tcpip_callback_msg * msg)438*10465441SEvalZero tcpip_trycallback(struct tcpip_callback_msg* msg)
439*10465441SEvalZero {
440*10465441SEvalZero if (!sys_mbox_valid(&mbox)) {
441*10465441SEvalZero return ERR_VAL;
442*10465441SEvalZero }
443*10465441SEvalZero return sys_mbox_trypost(&mbox, msg);
444*10465441SEvalZero }
445*10465441SEvalZero
446*10465441SEvalZero /**
447*10465441SEvalZero * Initialize this module:
448*10465441SEvalZero * - initialize all sub modules
449*10465441SEvalZero * - start the tcpip_thread
450*10465441SEvalZero *
451*10465441SEvalZero * @param initfunc a function to call when tcpip_thread is running and finished initializing
452*10465441SEvalZero * @param arg argument to pass to initfunc
453*10465441SEvalZero */
454*10465441SEvalZero void
tcpip_init(tcpip_init_done_fn initfunc,void * arg)455*10465441SEvalZero tcpip_init(tcpip_init_done_fn initfunc, void *arg)
456*10465441SEvalZero {
457*10465441SEvalZero lwip_init();
458*10465441SEvalZero
459*10465441SEvalZero tcpip_init_done = initfunc;
460*10465441SEvalZero tcpip_init_done_arg = arg;
461*10465441SEvalZero if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
462*10465441SEvalZero LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
463*10465441SEvalZero }
464*10465441SEvalZero #if LWIP_TCPIP_CORE_LOCKING
465*10465441SEvalZero if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
466*10465441SEvalZero LWIP_ASSERT("failed to create lock_tcpip_core", 0);
467*10465441SEvalZero }
468*10465441SEvalZero #endif /* LWIP_TCPIP_CORE_LOCKING */
469*10465441SEvalZero
470*10465441SEvalZero sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
471*10465441SEvalZero }
472*10465441SEvalZero
473*10465441SEvalZero /**
474*10465441SEvalZero * Simple callback function used with tcpip_callback to free a pbuf
475*10465441SEvalZero * (pbuf_free has a wrong signature for tcpip_callback)
476*10465441SEvalZero *
477*10465441SEvalZero * @param p The pbuf (chain) to be dereferenced.
478*10465441SEvalZero */
479*10465441SEvalZero static void
pbuf_free_int(void * p)480*10465441SEvalZero pbuf_free_int(void *p)
481*10465441SEvalZero {
482*10465441SEvalZero struct pbuf *q = (struct pbuf *)p;
483*10465441SEvalZero pbuf_free(q);
484*10465441SEvalZero }
485*10465441SEvalZero
486*10465441SEvalZero /**
487*10465441SEvalZero * A simple wrapper function that allows you to free a pbuf from interrupt context.
488*10465441SEvalZero *
489*10465441SEvalZero * @param p The pbuf (chain) to be dereferenced.
490*10465441SEvalZero * @return ERR_OK if callback could be enqueued, an err_t if not
491*10465441SEvalZero */
492*10465441SEvalZero err_t
pbuf_free_callback(struct pbuf * p)493*10465441SEvalZero pbuf_free_callback(struct pbuf *p)
494*10465441SEvalZero {
495*10465441SEvalZero return tcpip_callback_with_block(pbuf_free_int, p, 0);
496*10465441SEvalZero }
497*10465441SEvalZero
498*10465441SEvalZero /**
499*10465441SEvalZero * A simple wrapper function that allows you to free heap memory from
500*10465441SEvalZero * interrupt context.
501*10465441SEvalZero *
502*10465441SEvalZero * @param m the heap memory to free
503*10465441SEvalZero * @return ERR_OK if callback could be enqueued, an err_t if not
504*10465441SEvalZero */
505*10465441SEvalZero err_t
mem_free_callback(void * m)506*10465441SEvalZero mem_free_callback(void *m)
507*10465441SEvalZero {
508*10465441SEvalZero return tcpip_callback_with_block(mem_free, m, 0);
509*10465441SEvalZero }
510*10465441SEvalZero
511*10465441SEvalZero #endif /* !NO_SYS */
512