1195972f6Sopenharmony_ci/**
2195972f6Sopenharmony_ci * @file
3195972f6Sopenharmony_ci * Sequential API Main thread module
4195972f6Sopenharmony_ci *
5195972f6Sopenharmony_ci */
6195972f6Sopenharmony_ci
7195972f6Sopenharmony_ci/*
8195972f6Sopenharmony_ci * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9195972f6Sopenharmony_ci * All rights reserved.
10195972f6Sopenharmony_ci *
11195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
12195972f6Sopenharmony_ci * are permitted provided that the following conditions are met:
13195972f6Sopenharmony_ci *
14195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice,
15195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer.
16195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice,
17195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer in the documentation
18195972f6Sopenharmony_ci *    and/or other materials provided with the distribution.
19195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products
20195972f6Sopenharmony_ci *    derived from this software without specific prior written permission.
21195972f6Sopenharmony_ci *
22195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31195972f6Sopenharmony_ci * OF SUCH DAMAGE.
32195972f6Sopenharmony_ci *
33195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack.
34195972f6Sopenharmony_ci *
35195972f6Sopenharmony_ci * Author: Adam Dunkels <adam@sics.se>
36195972f6Sopenharmony_ci *
37195972f6Sopenharmony_ci */
38195972f6Sopenharmony_ci
39195972f6Sopenharmony_ci#include "lwip/opt.h"
40195972f6Sopenharmony_ci
41195972f6Sopenharmony_ci#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
42195972f6Sopenharmony_ci
43195972f6Sopenharmony_ci#include "lwip/priv/tcpip_priv.h"
44195972f6Sopenharmony_ci#include "lwip/sys.h"
45195972f6Sopenharmony_ci#include "lwip/memp.h"
46195972f6Sopenharmony_ci#include "lwip/mem.h"
47195972f6Sopenharmony_ci#include "lwip/init.h"
48195972f6Sopenharmony_ci#include "lwip/ip.h"
49195972f6Sopenharmony_ci#include "lwip/pbuf.h"
50195972f6Sopenharmony_ci#include "lwip/etharp.h"
51195972f6Sopenharmony_ci#include "netif/ethernet.h"
52195972f6Sopenharmony_ci#if LWIP_LOWPOWER
53195972f6Sopenharmony_ci#include "lwip/lowpower.h"
54195972f6Sopenharmony_ci#endif
55195972f6Sopenharmony_ci
56195972f6Sopenharmony_ci#define TCPIP_MSG_VAR_REF(name)     API_VAR_REF(name)
57195972f6Sopenharmony_ci#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
58195972f6Sopenharmony_ci#define TCPIP_MSG_VAR_ALLOC(name)   API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
59195972f6Sopenharmony_ci#define TCPIP_MSG_VAR_FREE(name)    API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
60195972f6Sopenharmony_ci
61195972f6Sopenharmony_ci/* global variables */
62195972f6Sopenharmony_cistatic tcpip_init_done_fn tcpip_init_done;
63195972f6Sopenharmony_cistatic void *tcpip_init_done_arg;
64195972f6Sopenharmony_cistatic sys_mbox_t tcpip_mbox;
65195972f6Sopenharmony_ci
66195972f6Sopenharmony_ci#if LWIP_TCPIP_CORE_LOCKING
67195972f6Sopenharmony_ci/** The global semaphore to lock the stack. */
68195972f6Sopenharmony_cisys_mutex_t lock_tcpip_core;
69195972f6Sopenharmony_ci#endif /* LWIP_TCPIP_CORE_LOCKING */
70195972f6Sopenharmony_ci
71195972f6Sopenharmony_cistatic void tcpip_thread_handle_msg(struct tcpip_msg *msg);
72195972f6Sopenharmony_ci
73195972f6Sopenharmony_ci#if !LWIP_TIMERS
74195972f6Sopenharmony_ci/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
75195972f6Sopenharmony_ci#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
76195972f6Sopenharmony_ci#else /* !LWIP_TIMERS */
77195972f6Sopenharmony_ci/* wait for a message, timeouts are processed while waiting */
78195972f6Sopenharmony_ci#define TCPIP_MBOX_FETCH(mbox, msg) tcpip_timeouts_mbox_fetch(mbox, msg)
79195972f6Sopenharmony_ci#if !LWIP_LOWPOWER
80195972f6Sopenharmony_ci/**
81195972f6Sopenharmony_ci * Wait (forever) for a message to arrive in an mbox.
82195972f6Sopenharmony_ci * While waiting, timeouts are processed.
83195972f6Sopenharmony_ci *
84195972f6Sopenharmony_ci * @param mbox the mbox to fetch the message from
85195972f6Sopenharmony_ci * @param msg the place to store the message
86195972f6Sopenharmony_ci */
87195972f6Sopenharmony_cistatic void
88195972f6Sopenharmony_citcpip_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
89195972f6Sopenharmony_ci{
90195972f6Sopenharmony_ci  u32_t sleeptime, res;
91195972f6Sopenharmony_ci
92195972f6Sopenharmony_ciagain:
93195972f6Sopenharmony_ci  LWIP_ASSERT_CORE_LOCKED();
94195972f6Sopenharmony_ci
95195972f6Sopenharmony_ci  sleeptime = sys_timeouts_sleeptime();
96195972f6Sopenharmony_ci  if (sleeptime == SYS_TIMEOUTS_SLEEPTIME_INFINITE) {
97195972f6Sopenharmony_ci    UNLOCK_TCPIP_CORE();
98195972f6Sopenharmony_ci    sys_arch_mbox_fetch(mbox, msg, 0);
99195972f6Sopenharmony_ci    LOCK_TCPIP_CORE();
100195972f6Sopenharmony_ci    return;
101195972f6Sopenharmony_ci  } else if (sleeptime == 0) {
102195972f6Sopenharmony_ci    sys_check_timeouts();
103195972f6Sopenharmony_ci    /* We try again to fetch a message from the mbox. */
104195972f6Sopenharmony_ci    goto again;
105195972f6Sopenharmony_ci  }
106195972f6Sopenharmony_ci
107195972f6Sopenharmony_ci  UNLOCK_TCPIP_CORE();
108195972f6Sopenharmony_ci  res = sys_arch_mbox_fetch(mbox, msg, sleeptime);
109195972f6Sopenharmony_ci  LOCK_TCPIP_CORE();
110195972f6Sopenharmony_ci  if (res == SYS_ARCH_TIMEOUT) {
111195972f6Sopenharmony_ci    /* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred
112195972f6Sopenharmony_ci       before a message could be fetched. */
113195972f6Sopenharmony_ci    sys_check_timeouts();
114195972f6Sopenharmony_ci    /* We try again to fetch a message from the mbox. */
115195972f6Sopenharmony_ci    goto again;
116195972f6Sopenharmony_ci  }
117195972f6Sopenharmony_ci}
118195972f6Sopenharmony_ci#endif /* !LWIP_LOWPOWER */
119195972f6Sopenharmony_ci#endif /* !LWIP_TIMERS */
120195972f6Sopenharmony_ci
121195972f6Sopenharmony_ci/**
122195972f6Sopenharmony_ci * The main lwIP thread. This thread has exclusive access to lwIP core functions
123195972f6Sopenharmony_ci * (unless access to them is not locked). Other threads communicate with this
124195972f6Sopenharmony_ci * thread using message boxes.
125195972f6Sopenharmony_ci *
126195972f6Sopenharmony_ci * It also starts all the timers to make sure they are running in the right
127195972f6Sopenharmony_ci * thread context.
128195972f6Sopenharmony_ci *
129195972f6Sopenharmony_ci * @param arg unused argument
130195972f6Sopenharmony_ci */
131195972f6Sopenharmony_cistatic void
132195972f6Sopenharmony_citcpip_thread(void *arg)
133195972f6Sopenharmony_ci{
134195972f6Sopenharmony_ci  struct tcpip_msg *msg;
135195972f6Sopenharmony_ci  LWIP_UNUSED_ARG(arg);
136195972f6Sopenharmony_ci
137195972f6Sopenharmony_ci  LWIP_MARK_TCPIP_THREAD();
138195972f6Sopenharmony_ci
139195972f6Sopenharmony_ci  LOCK_TCPIP_CORE();
140195972f6Sopenharmony_ci  if (tcpip_init_done != NULL) {
141195972f6Sopenharmony_ci    tcpip_init_done(tcpip_init_done_arg);
142195972f6Sopenharmony_ci  }
143195972f6Sopenharmony_ci
144195972f6Sopenharmony_ci  while (1) {                          /* MAIN Loop */
145195972f6Sopenharmony_ci    LWIP_TCPIP_THREAD_ALIVE();
146195972f6Sopenharmony_ci    /* wait for a message, timeouts are processed while waiting */
147195972f6Sopenharmony_ci    TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg);
148195972f6Sopenharmony_ci    if (msg == NULL) {
149195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
150195972f6Sopenharmony_ci      LWIP_ASSERT("tcpip_thread: invalid message", 0);
151195972f6Sopenharmony_ci      continue;
152195972f6Sopenharmony_ci    }
153195972f6Sopenharmony_ci    tcpip_thread_handle_msg(msg);
154195972f6Sopenharmony_ci  }
155195972f6Sopenharmony_ci}
156195972f6Sopenharmony_ci
157195972f6Sopenharmony_ci/* Handle a single tcpip_msg
158195972f6Sopenharmony_ci * This is in its own function for access by tests only.
159195972f6Sopenharmony_ci */
160195972f6Sopenharmony_cistatic void
161195972f6Sopenharmony_citcpip_thread_handle_msg(struct tcpip_msg *msg)
162195972f6Sopenharmony_ci{
163195972f6Sopenharmony_ci  switch (msg->type) {
164195972f6Sopenharmony_ci#if !LWIP_TCPIP_CORE_LOCKING
165195972f6Sopenharmony_ci    case TCPIP_MSG_API:
166195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
167195972f6Sopenharmony_ci      msg->msg.api_msg.function(msg->msg.api_msg.msg);
168195972f6Sopenharmony_ci      break;
169195972f6Sopenharmony_ci    case TCPIP_MSG_API_CALL:
170195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
171195972f6Sopenharmony_ci      msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
172195972f6Sopenharmony_ci      sys_sem_signal(msg->msg.api_call.sem);
173195972f6Sopenharmony_ci      break;
174195972f6Sopenharmony_ci#endif /* !LWIP_TCPIP_CORE_LOCKING */
175195972f6Sopenharmony_ci
176195972f6Sopenharmony_ci#if !LWIP_TCPIP_CORE_LOCKING_INPUT
177195972f6Sopenharmony_ci    case TCPIP_MSG_INPKT:
178195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
179195972f6Sopenharmony_ci      if (msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif) != ERR_OK) {
180195972f6Sopenharmony_ci        pbuf_free(msg->msg.inp.p);
181195972f6Sopenharmony_ci      }
182195972f6Sopenharmony_ci      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
183195972f6Sopenharmony_ci      break;
184195972f6Sopenharmony_ci#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
185195972f6Sopenharmony_ci
186195972f6Sopenharmony_ci#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
187195972f6Sopenharmony_ci    case TCPIP_MSG_TIMEOUT:
188195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
189195972f6Sopenharmony_ci      sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
190195972f6Sopenharmony_ci      memp_free(MEMP_TCPIP_MSG_API, msg);
191195972f6Sopenharmony_ci      break;
192195972f6Sopenharmony_ci    case TCPIP_MSG_UNTIMEOUT:
193195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
194195972f6Sopenharmony_ci      sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
195195972f6Sopenharmony_ci      memp_free(MEMP_TCPIP_MSG_API, msg);
196195972f6Sopenharmony_ci      break;
197195972f6Sopenharmony_ci#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
198195972f6Sopenharmony_ci
199195972f6Sopenharmony_ci    case TCPIP_MSG_CALLBACK:
200195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
201195972f6Sopenharmony_ci      msg->msg.cb.function(msg->msg.cb.ctx);
202195972f6Sopenharmony_ci      memp_free(MEMP_TCPIP_MSG_API, msg);
203195972f6Sopenharmony_ci      break;
204195972f6Sopenharmony_ci
205195972f6Sopenharmony_ci    case TCPIP_MSG_CALLBACK_STATIC:
206195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
207195972f6Sopenharmony_ci      msg->msg.cb.function(msg->msg.cb.ctx);
208195972f6Sopenharmony_ci      break;
209195972f6Sopenharmony_ci#if LWIP_LOWPOWER
210195972f6Sopenharmony_ci    /* just wake up thread do nothing */
211195972f6Sopenharmony_ci    case TCPIP_MSG_NA:
212195972f6Sopenharmony_ci      if (msg->msg.lowpower.type == LOW_BLOCK) {
213195972f6Sopenharmony_ci        LOWPOWER_SIGNAL(msg->msg.lowpower.wait_up);
214195972f6Sopenharmony_ci      } else {
215195972f6Sopenharmony_ci        memp_free(MEMP_TCPIP_MSG_LOWPOWER, msg);
216195972f6Sopenharmony_ci      }
217195972f6Sopenharmony_ci      sys_timeout_set_wake_time(LOW_TMR_DELAY);
218195972f6Sopenharmony_ci      break;
219195972f6Sopenharmony_ci#endif
220195972f6Sopenharmony_ci    default:
221195972f6Sopenharmony_ci      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
222195972f6Sopenharmony_ci      LWIP_ASSERT("tcpip_thread: invalid message", 0);
223195972f6Sopenharmony_ci      break;
224195972f6Sopenharmony_ci  }
225195972f6Sopenharmony_ci}
226195972f6Sopenharmony_ci
227195972f6Sopenharmony_ci#if LWIP_LOWPOWER
228195972f6Sopenharmony_ci/* send a na msg to wake up tcpip_thread */
229195972f6Sopenharmony_civoid
230195972f6Sopenharmony_citcpip_send_msg_na(enum lowpower_msg_type type)
231195972f6Sopenharmony_ci{
232195972f6Sopenharmony_ci  struct tcpip_msg *msg = NULL;
233195972f6Sopenharmony_ci  err_t val;
234195972f6Sopenharmony_ci
235195972f6Sopenharmony_ci  /* is not used lowpower mode */
236195972f6Sopenharmony_ci  if ((type != LOW_FORCE_NON_BLOCK) && (get_lowpowper_mod() == LOW_TMR_NORMAL_MOD)) {
237195972f6Sopenharmony_ci    return;
238195972f6Sopenharmony_ci  }
239195972f6Sopenharmony_ci  if (sys_timeout_waiting_long() == 0) {
240195972f6Sopenharmony_ci    return;
241195972f6Sopenharmony_ci  }
242195972f6Sopenharmony_ci
243195972f6Sopenharmony_ci  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_LOWPOWER);
244195972f6Sopenharmony_ci  if (msg == NULL) {
245195972f6Sopenharmony_ci    LWIP_DEBUGF(LOWPOWER_DEBUG, ("tcpip_send_msg_na alloc faild\n"));
246195972f6Sopenharmony_ci    return;
247195972f6Sopenharmony_ci  }
248195972f6Sopenharmony_ci
249195972f6Sopenharmony_ci  /* just wake up thread if nonblock */
250195972f6Sopenharmony_ci  msg->type = TCPIP_MSG_NA;
251195972f6Sopenharmony_ci  msg->msg.lowpower.type = type;
252195972f6Sopenharmony_ci
253195972f6Sopenharmony_ci  if (type == LOW_BLOCK) {
254195972f6Sopenharmony_ci    LOWPOWER_SEM_NEW(msg->msg.lowpower.wait_up, val);
255195972f6Sopenharmony_ci    if (val != ERR_OK) {
256195972f6Sopenharmony_ci      LWIP_DEBUGF(LOWPOWER_DEBUG, ("alloc sem faild\n"));
257195972f6Sopenharmony_ci      memp_free(MEMP_TCPIP_MSG_LOWPOWER, msg);
258195972f6Sopenharmony_ci      return;
259195972f6Sopenharmony_ci    }
260195972f6Sopenharmony_ci  }
261195972f6Sopenharmony_ci
262195972f6Sopenharmony_ci  if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
263195972f6Sopenharmony_ci    if (type == LOW_BLOCK) {
264195972f6Sopenharmony_ci      LOWPOWER_SEM_FREE(msg->msg.lowpower.wait_up);
265195972f6Sopenharmony_ci    }
266195972f6Sopenharmony_ci    memp_free(MEMP_TCPIP_MSG_LOWPOWER, msg);
267195972f6Sopenharmony_ci    LWIP_DEBUGF(LOWPOWER_DEBUG, ("tcpip_send_msg_na post faild\n"));
268195972f6Sopenharmony_ci    return;
269195972f6Sopenharmony_ci  }
270195972f6Sopenharmony_ci
271195972f6Sopenharmony_ci  if (type == LOW_BLOCK) {
272195972f6Sopenharmony_ci    LOWPOWER_SEM_WAIT(msg->msg.lowpower.wait_up);
273195972f6Sopenharmony_ci    LOWPOWER_SEM_FREE(msg->msg.lowpower.wait_up);
274195972f6Sopenharmony_ci    memp_free(MEMP_TCPIP_MSG_LOWPOWER, msg);
275195972f6Sopenharmony_ci  }
276195972f6Sopenharmony_ci}
277195972f6Sopenharmony_ci#endif /* LWIP_LOWPOWER */
278195972f6Sopenharmony_ci
279195972f6Sopenharmony_ci#ifdef TCPIP_THREAD_TEST
280195972f6Sopenharmony_ci/** Work on queued items in single-threaded test mode */
281195972f6Sopenharmony_ciint
282195972f6Sopenharmony_citcpip_thread_poll_one(void)
283195972f6Sopenharmony_ci{
284195972f6Sopenharmony_ci  int ret = 0;
285195972f6Sopenharmony_ci  struct tcpip_msg *msg;
286195972f6Sopenharmony_ci
287195972f6Sopenharmony_ci  if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_MBOX_EMPTY) {
288195972f6Sopenharmony_ci    LOCK_TCPIP_CORE();
289195972f6Sopenharmony_ci    if (msg != NULL) {
290195972f6Sopenharmony_ci      tcpip_thread_handle_msg(msg);
291195972f6Sopenharmony_ci      ret = 1;
292195972f6Sopenharmony_ci    }
293195972f6Sopenharmony_ci    UNLOCK_TCPIP_CORE();
294195972f6Sopenharmony_ci  }
295195972f6Sopenharmony_ci  return ret;
296195972f6Sopenharmony_ci}
297195972f6Sopenharmony_ci#endif
298195972f6Sopenharmony_ci
299195972f6Sopenharmony_ci/**
300195972f6Sopenharmony_ci * Pass a received packet to tcpip_thread for input processing
301195972f6Sopenharmony_ci *
302195972f6Sopenharmony_ci * @param p the received packet
303195972f6Sopenharmony_ci * @param inp the network interface on which the packet was received
304195972f6Sopenharmony_ci * @param input_fn input function to call
305195972f6Sopenharmony_ci */
306195972f6Sopenharmony_cierr_t
307195972f6Sopenharmony_citcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
308195972f6Sopenharmony_ci{
309195972f6Sopenharmony_ci#if LWIP_TCPIP_CORE_LOCKING_INPUT
310195972f6Sopenharmony_ci  err_t ret;
311195972f6Sopenharmony_ci  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
312195972f6Sopenharmony_ci#if LWIP_LOWPOWER
313195972f6Sopenharmony_ci  tcpip_send_msg_na(LOW_BLOCK);
314195972f6Sopenharmony_ci#endif
315195972f6Sopenharmony_ci  LOCK_TCPIP_CORE();
316195972f6Sopenharmony_ci  ret = input_fn(p, inp);
317195972f6Sopenharmony_ci  UNLOCK_TCPIP_CORE();
318195972f6Sopenharmony_ci  return ret;
319195972f6Sopenharmony_ci#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
320195972f6Sopenharmony_ci  struct tcpip_msg *msg;
321195972f6Sopenharmony_ci
322195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
323195972f6Sopenharmony_ci
324195972f6Sopenharmony_ci  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
325195972f6Sopenharmony_ci  if (msg == NULL) {
326195972f6Sopenharmony_ci    return ERR_MEM;
327195972f6Sopenharmony_ci  }
328195972f6Sopenharmony_ci
329195972f6Sopenharmony_ci  msg->type = TCPIP_MSG_INPKT;
330195972f6Sopenharmony_ci  msg->msg.inp.p = p;
331195972f6Sopenharmony_ci  msg->msg.inp.netif = inp;
332195972f6Sopenharmony_ci  msg->msg.inp.input_fn = input_fn;
333195972f6Sopenharmony_ci  if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
334195972f6Sopenharmony_ci    memp_free(MEMP_TCPIP_MSG_INPKT, msg);
335195972f6Sopenharmony_ci    return ERR_MEM;
336195972f6Sopenharmony_ci  }
337195972f6Sopenharmony_ci  return ERR_OK;
338195972f6Sopenharmony_ci#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
339195972f6Sopenharmony_ci}
340195972f6Sopenharmony_ci
341195972f6Sopenharmony_ci/**
342195972f6Sopenharmony_ci * @ingroup lwip_os
343195972f6Sopenharmony_ci * Pass a received packet to tcpip_thread for input processing with
344195972f6Sopenharmony_ci * ethernet_input or ip_input. Don't call directly, pass to netif_add()
345195972f6Sopenharmony_ci * and call netif->input().
346195972f6Sopenharmony_ci *
347195972f6Sopenharmony_ci * @param p the received packet, p->payload pointing to the Ethernet header or
348195972f6Sopenharmony_ci *          to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
349195972f6Sopenharmony_ci *          NETIF_FLAG_ETHERNET flags)
350195972f6Sopenharmony_ci * @param inp the network interface on which the packet was received
351195972f6Sopenharmony_ci */
352195972f6Sopenharmony_cierr_t
353195972f6Sopenharmony_citcpip_input(struct pbuf *p, struct netif *inp)
354195972f6Sopenharmony_ci{
355195972f6Sopenharmony_ci#if LWIP_ETHERNET
356195972f6Sopenharmony_ci  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
357195972f6Sopenharmony_ci    return tcpip_inpkt(p, inp, ethernet_input);
358195972f6Sopenharmony_ci  } else
359195972f6Sopenharmony_ci#endif /* LWIP_ETHERNET */
360195972f6Sopenharmony_ci    return tcpip_inpkt(p, inp, ip_input);
361195972f6Sopenharmony_ci}
362195972f6Sopenharmony_ci
363195972f6Sopenharmony_ci/**
364195972f6Sopenharmony_ci * @ingroup lwip_os
365195972f6Sopenharmony_ci * Call a specific function in the thread context of
366195972f6Sopenharmony_ci * tcpip_thread for easy access synchronization.
367195972f6Sopenharmony_ci * A function called in that way may access lwIP core code
368195972f6Sopenharmony_ci * without fearing concurrent access.
369195972f6Sopenharmony_ci * Blocks until the request is posted.
370195972f6Sopenharmony_ci * Must not be called from interrupt context!
371195972f6Sopenharmony_ci *
372195972f6Sopenharmony_ci * @param function the function to call
373195972f6Sopenharmony_ci * @param ctx parameter passed to f
374195972f6Sopenharmony_ci * @return ERR_OK if the function was called, another err_t if not
375195972f6Sopenharmony_ci *
376195972f6Sopenharmony_ci * @see tcpip_try_callback
377195972f6Sopenharmony_ci */
378195972f6Sopenharmony_cierr_t
379195972f6Sopenharmony_citcpip_callback(tcpip_callback_fn function, void *ctx)
380195972f6Sopenharmony_ci{
381195972f6Sopenharmony_ci  struct tcpip_msg *msg;
382195972f6Sopenharmony_ci
383195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
384195972f6Sopenharmony_ci
385195972f6Sopenharmony_ci  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
386195972f6Sopenharmony_ci  if (msg == NULL) {
387195972f6Sopenharmony_ci    return ERR_MEM;
388195972f6Sopenharmony_ci  }
389195972f6Sopenharmony_ci
390195972f6Sopenharmony_ci  msg->type = TCPIP_MSG_CALLBACK;
391195972f6Sopenharmony_ci  msg->msg.cb.function = function;
392195972f6Sopenharmony_ci  msg->msg.cb.ctx = ctx;
393195972f6Sopenharmony_ci
394195972f6Sopenharmony_ci  sys_mbox_post(&tcpip_mbox, msg);
395195972f6Sopenharmony_ci  return ERR_OK;
396195972f6Sopenharmony_ci}
397195972f6Sopenharmony_ci
398195972f6Sopenharmony_ci/**
399195972f6Sopenharmony_ci * @ingroup lwip_os
400195972f6Sopenharmony_ci * Call a specific function in the thread context of
401195972f6Sopenharmony_ci * tcpip_thread for easy access synchronization.
402195972f6Sopenharmony_ci * A function called in that way may access lwIP core code
403195972f6Sopenharmony_ci * without fearing concurrent access.
404195972f6Sopenharmony_ci * Does NOT block when the request cannot be posted because the
405195972f6Sopenharmony_ci * tcpip_mbox is full, but returns ERR_MEM instead.
406195972f6Sopenharmony_ci * Can be called from interrupt context.
407195972f6Sopenharmony_ci *
408195972f6Sopenharmony_ci * @param function the function to call
409195972f6Sopenharmony_ci * @param ctx parameter passed to f
410195972f6Sopenharmony_ci * @return ERR_OK if the function was called, another err_t if not
411195972f6Sopenharmony_ci *
412195972f6Sopenharmony_ci * @see tcpip_callback
413195972f6Sopenharmony_ci */
414195972f6Sopenharmony_cierr_t
415195972f6Sopenharmony_citcpip_try_callback(tcpip_callback_fn function, void *ctx)
416195972f6Sopenharmony_ci{
417195972f6Sopenharmony_ci  struct tcpip_msg *msg;
418195972f6Sopenharmony_ci
419195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
420195972f6Sopenharmony_ci
421195972f6Sopenharmony_ci  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
422195972f6Sopenharmony_ci  if (msg == NULL) {
423195972f6Sopenharmony_ci    return ERR_MEM;
424195972f6Sopenharmony_ci  }
425195972f6Sopenharmony_ci
426195972f6Sopenharmony_ci  msg->type = TCPIP_MSG_CALLBACK;
427195972f6Sopenharmony_ci  msg->msg.cb.function = function;
428195972f6Sopenharmony_ci  msg->msg.cb.ctx = ctx;
429195972f6Sopenharmony_ci
430195972f6Sopenharmony_ci  if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
431195972f6Sopenharmony_ci    memp_free(MEMP_TCPIP_MSG_API, msg);
432195972f6Sopenharmony_ci    return ERR_MEM;
433195972f6Sopenharmony_ci  }
434195972f6Sopenharmony_ci  return ERR_OK;
435195972f6Sopenharmony_ci}
436195972f6Sopenharmony_ci
437195972f6Sopenharmony_ci#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
438195972f6Sopenharmony_ci/**
439195972f6Sopenharmony_ci * call sys_timeout in tcpip_thread
440195972f6Sopenharmony_ci *
441195972f6Sopenharmony_ci * @param msecs time in milliseconds for timeout
442195972f6Sopenharmony_ci * @param h function to be called on timeout
443195972f6Sopenharmony_ci * @param arg argument to pass to timeout function h
444195972f6Sopenharmony_ci * @return ERR_MEM on memory error, ERR_OK otherwise
445195972f6Sopenharmony_ci */
446195972f6Sopenharmony_cierr_t
447195972f6Sopenharmony_citcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
448195972f6Sopenharmony_ci{
449195972f6Sopenharmony_ci  struct tcpip_msg *msg;
450195972f6Sopenharmony_ci
451195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
452195972f6Sopenharmony_ci
453195972f6Sopenharmony_ci  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
454195972f6Sopenharmony_ci  if (msg == NULL) {
455195972f6Sopenharmony_ci    return ERR_MEM;
456195972f6Sopenharmony_ci  }
457195972f6Sopenharmony_ci
458195972f6Sopenharmony_ci  msg->type = TCPIP_MSG_TIMEOUT;
459195972f6Sopenharmony_ci  msg->msg.tmo.msecs = msecs;
460195972f6Sopenharmony_ci  msg->msg.tmo.h = h;
461195972f6Sopenharmony_ci  msg->msg.tmo.arg = arg;
462195972f6Sopenharmony_ci  sys_mbox_post(&tcpip_mbox, msg);
463195972f6Sopenharmony_ci  return ERR_OK;
464195972f6Sopenharmony_ci}
465195972f6Sopenharmony_ci
466195972f6Sopenharmony_ci/**
467195972f6Sopenharmony_ci * call sys_untimeout in tcpip_thread
468195972f6Sopenharmony_ci *
469195972f6Sopenharmony_ci * @param h function to be called on timeout
470195972f6Sopenharmony_ci * @param arg argument to pass to timeout function h
471195972f6Sopenharmony_ci * @return ERR_MEM on memory error, ERR_OK otherwise
472195972f6Sopenharmony_ci */
473195972f6Sopenharmony_cierr_t
474195972f6Sopenharmony_citcpip_untimeout(sys_timeout_handler h, void *arg)
475195972f6Sopenharmony_ci{
476195972f6Sopenharmony_ci  struct tcpip_msg *msg;
477195972f6Sopenharmony_ci
478195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
479195972f6Sopenharmony_ci
480195972f6Sopenharmony_ci  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
481195972f6Sopenharmony_ci  if (msg == NULL) {
482195972f6Sopenharmony_ci    return ERR_MEM;
483195972f6Sopenharmony_ci  }
484195972f6Sopenharmony_ci
485195972f6Sopenharmony_ci  msg->type = TCPIP_MSG_UNTIMEOUT;
486195972f6Sopenharmony_ci  msg->msg.tmo.h = h;
487195972f6Sopenharmony_ci  msg->msg.tmo.arg = arg;
488195972f6Sopenharmony_ci  sys_mbox_post(&tcpip_mbox, msg);
489195972f6Sopenharmony_ci  return ERR_OK;
490195972f6Sopenharmony_ci}
491195972f6Sopenharmony_ci#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
492195972f6Sopenharmony_ci
493195972f6Sopenharmony_ci
494195972f6Sopenharmony_ci/**
495195972f6Sopenharmony_ci * Sends a message to TCPIP thread to call a function. Caller thread blocks on
496195972f6Sopenharmony_ci * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread,
497195972f6Sopenharmony_ci * this has to be done by the user.
498195972f6Sopenharmony_ci * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way
499195972f6Sopenharmony_ci * with least runtime overhead.
500195972f6Sopenharmony_ci *
501195972f6Sopenharmony_ci * @param fn function to be called from TCPIP thread
502195972f6Sopenharmony_ci * @param apimsg argument to API function
503195972f6Sopenharmony_ci * @param sem semaphore to wait on
504195972f6Sopenharmony_ci * @return ERR_OK if the function was called, another err_t if not
505195972f6Sopenharmony_ci */
506195972f6Sopenharmony_cierr_t
507195972f6Sopenharmony_citcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
508195972f6Sopenharmony_ci{
509195972f6Sopenharmony_ci#if LWIP_TCPIP_CORE_LOCKING
510195972f6Sopenharmony_ci  LWIP_UNUSED_ARG(sem);
511195972f6Sopenharmony_ci#if LWIP_LOWPOWER
512195972f6Sopenharmony_ci  tcpip_send_msg_na(LOW_BLOCK);
513195972f6Sopenharmony_ci#endif
514195972f6Sopenharmony_ci  LOCK_TCPIP_CORE();
515195972f6Sopenharmony_ci  fn(apimsg);
516195972f6Sopenharmony_ci  UNLOCK_TCPIP_CORE();
517195972f6Sopenharmony_ci  return ERR_OK;
518195972f6Sopenharmony_ci#else /* LWIP_TCPIP_CORE_LOCKING */
519195972f6Sopenharmony_ci  TCPIP_MSG_VAR_DECLARE(msg);
520195972f6Sopenharmony_ci
521195972f6Sopenharmony_ci  LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
522195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
523195972f6Sopenharmony_ci
524195972f6Sopenharmony_ci  TCPIP_MSG_VAR_ALLOC(msg);
525195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
526195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
527195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
528195972f6Sopenharmony_ci  sys_mbox_post(&tcpip_mbox, &TCPIP_MSG_VAR_REF(msg));
529195972f6Sopenharmony_ci  sys_arch_sem_wait(sem, 0);
530195972f6Sopenharmony_ci  TCPIP_MSG_VAR_FREE(msg);
531195972f6Sopenharmony_ci  return ERR_OK;
532195972f6Sopenharmony_ci#endif /* LWIP_TCPIP_CORE_LOCKING */
533195972f6Sopenharmony_ci}
534195972f6Sopenharmony_ci
535195972f6Sopenharmony_ci/**
536195972f6Sopenharmony_ci * Synchronously calls function in TCPIP thread and waits for its completion.
537195972f6Sopenharmony_ci * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or
538195972f6Sopenharmony_ci * LWIP_NETCONN_SEM_PER_THREAD.
539195972f6Sopenharmony_ci * If not, a semaphore is created and destroyed on every call which is usually
540195972f6Sopenharmony_ci * an expensive/slow operation.
541195972f6Sopenharmony_ci * @param fn Function to call
542195972f6Sopenharmony_ci * @param call Call parameters
543195972f6Sopenharmony_ci * @return Return value from tcpip_api_call_fn
544195972f6Sopenharmony_ci */
545195972f6Sopenharmony_cierr_t
546195972f6Sopenharmony_citcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
547195972f6Sopenharmony_ci{
548195972f6Sopenharmony_ci#if LWIP_TCPIP_CORE_LOCKING
549195972f6Sopenharmony_ci  err_t err;
550195972f6Sopenharmony_ci#if LWIP_LOWPOWER
551195972f6Sopenharmony_ci  tcpip_send_msg_na(LOW_BLOCK);
552195972f6Sopenharmony_ci#endif
553195972f6Sopenharmony_ci  LOCK_TCPIP_CORE();
554195972f6Sopenharmony_ci  err = fn(call);
555195972f6Sopenharmony_ci  UNLOCK_TCPIP_CORE();
556195972f6Sopenharmony_ci  return err;
557195972f6Sopenharmony_ci#else /* LWIP_TCPIP_CORE_LOCKING */
558195972f6Sopenharmony_ci  TCPIP_MSG_VAR_DECLARE(msg);
559195972f6Sopenharmony_ci
560195972f6Sopenharmony_ci#if !LWIP_NETCONN_SEM_PER_THREAD
561195972f6Sopenharmony_ci  err_t err = sys_sem_new(&call->sem, 0);
562195972f6Sopenharmony_ci  if (err != ERR_OK) {
563195972f6Sopenharmony_ci    return err;
564195972f6Sopenharmony_ci  }
565195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_SEM_PER_THREAD */
566195972f6Sopenharmony_ci
567195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
568195972f6Sopenharmony_ci
569195972f6Sopenharmony_ci  TCPIP_MSG_VAR_ALLOC(msg);
570195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
571195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
572195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
573195972f6Sopenharmony_ci#if LWIP_NETCONN_SEM_PER_THREAD
574195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
575195972f6Sopenharmony_ci#else /* LWIP_NETCONN_SEM_PER_THREAD */
576195972f6Sopenharmony_ci  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
577195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_SEM_PER_THREAD */
578195972f6Sopenharmony_ci  sys_mbox_post(&tcpip_mbox, &TCPIP_MSG_VAR_REF(msg));
579195972f6Sopenharmony_ci  sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
580195972f6Sopenharmony_ci  TCPIP_MSG_VAR_FREE(msg);
581195972f6Sopenharmony_ci
582195972f6Sopenharmony_ci#if !LWIP_NETCONN_SEM_PER_THREAD
583195972f6Sopenharmony_ci  sys_sem_free(&call->sem);
584195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_SEM_PER_THREAD */
585195972f6Sopenharmony_ci
586195972f6Sopenharmony_ci  return call->err;
587195972f6Sopenharmony_ci#endif /* LWIP_TCPIP_CORE_LOCKING */
588195972f6Sopenharmony_ci}
589195972f6Sopenharmony_ci
590195972f6Sopenharmony_ci/**
591195972f6Sopenharmony_ci * @ingroup lwip_os
592195972f6Sopenharmony_ci * Allocate a structure for a static callback message and initialize it.
593195972f6Sopenharmony_ci * The message has a special type such that lwIP never frees it.
594195972f6Sopenharmony_ci * This is intended to be used to send "static" messages from interrupt context,
595195972f6Sopenharmony_ci * e.g. the message is allocated once and posted several times from an IRQ
596195972f6Sopenharmony_ci * using tcpip_callbackmsg_trycallback().
597195972f6Sopenharmony_ci * Example usage: Trigger execution of an ethernet IRQ DPC routine in lwIP thread context.
598195972f6Sopenharmony_ci *
599195972f6Sopenharmony_ci * @param function the function to call
600195972f6Sopenharmony_ci * @param ctx parameter passed to function
601195972f6Sopenharmony_ci * @return a struct pointer to pass to tcpip_callbackmsg_trycallback().
602195972f6Sopenharmony_ci *
603195972f6Sopenharmony_ci * @see tcpip_callbackmsg_trycallback()
604195972f6Sopenharmony_ci * @see tcpip_callbackmsg_delete()
605195972f6Sopenharmony_ci */
606195972f6Sopenharmony_cistruct tcpip_callback_msg *
607195972f6Sopenharmony_citcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
608195972f6Sopenharmony_ci{
609195972f6Sopenharmony_ci  struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
610195972f6Sopenharmony_ci  if (msg == NULL) {
611195972f6Sopenharmony_ci    return NULL;
612195972f6Sopenharmony_ci  }
613195972f6Sopenharmony_ci  msg->type = TCPIP_MSG_CALLBACK_STATIC;
614195972f6Sopenharmony_ci  msg->msg.cb.function = function;
615195972f6Sopenharmony_ci  msg->msg.cb.ctx = ctx;
616195972f6Sopenharmony_ci  return (struct tcpip_callback_msg *)msg;
617195972f6Sopenharmony_ci}
618195972f6Sopenharmony_ci
619195972f6Sopenharmony_ci/**
620195972f6Sopenharmony_ci * @ingroup lwip_os
621195972f6Sopenharmony_ci * Free a callback message allocated by tcpip_callbackmsg_new().
622195972f6Sopenharmony_ci *
623195972f6Sopenharmony_ci * @param msg the message to free
624195972f6Sopenharmony_ci *
625195972f6Sopenharmony_ci * @see tcpip_callbackmsg_new()
626195972f6Sopenharmony_ci */
627195972f6Sopenharmony_civoid
628195972f6Sopenharmony_citcpip_callbackmsg_delete(struct tcpip_callback_msg *msg)
629195972f6Sopenharmony_ci{
630195972f6Sopenharmony_ci  memp_free(MEMP_TCPIP_MSG_API, msg);
631195972f6Sopenharmony_ci}
632195972f6Sopenharmony_ci
633195972f6Sopenharmony_ci/**
634195972f6Sopenharmony_ci * @ingroup lwip_os
635195972f6Sopenharmony_ci * Try to post a callback-message to the tcpip_thread tcpip_mbox.
636195972f6Sopenharmony_ci *
637195972f6Sopenharmony_ci * @param msg pointer to the message to post
638195972f6Sopenharmony_ci * @return sys_mbox_trypost() return code
639195972f6Sopenharmony_ci *
640195972f6Sopenharmony_ci * @see tcpip_callbackmsg_new()
641195972f6Sopenharmony_ci */
642195972f6Sopenharmony_cierr_t
643195972f6Sopenharmony_citcpip_callbackmsg_trycallback(struct tcpip_callback_msg *msg)
644195972f6Sopenharmony_ci{
645195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
646195972f6Sopenharmony_ci  return sys_mbox_trypost(&tcpip_mbox, msg);
647195972f6Sopenharmony_ci}
648195972f6Sopenharmony_ci
649195972f6Sopenharmony_ci/**
650195972f6Sopenharmony_ci * @ingroup lwip_os
651195972f6Sopenharmony_ci * Try to post a callback-message to the tcpip_thread mbox.
652195972f6Sopenharmony_ci * Same as @ref tcpip_callbackmsg_trycallback but calls sys_mbox_trypost_fromisr(),
653195972f6Sopenharmony_ci * mainly to help FreeRTOS, where calls differ between task level and ISR level.
654195972f6Sopenharmony_ci *
655195972f6Sopenharmony_ci * @param msg pointer to the message to post
656195972f6Sopenharmony_ci * @return sys_mbox_trypost_fromisr() return code (without change, so this
657195972f6Sopenharmony_ci *         knowledge can be used to e.g. propagate "bool needs_scheduling")
658195972f6Sopenharmony_ci *
659195972f6Sopenharmony_ci * @see tcpip_callbackmsg_new()
660195972f6Sopenharmony_ci */
661195972f6Sopenharmony_cierr_t
662195972f6Sopenharmony_citcpip_callbackmsg_trycallback_fromisr(struct tcpip_callback_msg *msg)
663195972f6Sopenharmony_ci{
664195972f6Sopenharmony_ci  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
665195972f6Sopenharmony_ci  return sys_mbox_trypost_fromisr(&tcpip_mbox, msg);
666195972f6Sopenharmony_ci}
667195972f6Sopenharmony_ci
668195972f6Sopenharmony_ci/**
669195972f6Sopenharmony_ci * @ingroup lwip_os
670195972f6Sopenharmony_ci * Initialize this module:
671195972f6Sopenharmony_ci * - initialize all sub modules
672195972f6Sopenharmony_ci * - start the tcpip_thread
673195972f6Sopenharmony_ci *
674195972f6Sopenharmony_ci * @param initfunc a function to call when tcpip_thread is running and finished initializing
675195972f6Sopenharmony_ci * @param arg argument to pass to initfunc
676195972f6Sopenharmony_ci */
677195972f6Sopenharmony_civoid
678195972f6Sopenharmony_citcpip_init(tcpip_init_done_fn initfunc, void *arg)
679195972f6Sopenharmony_ci{
680195972f6Sopenharmony_ci  lwip_init();
681195972f6Sopenharmony_ci
682195972f6Sopenharmony_ci  tcpip_init_done = initfunc;
683195972f6Sopenharmony_ci  tcpip_init_done_arg = arg;
684195972f6Sopenharmony_ci  if (sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
685195972f6Sopenharmony_ci    LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
686195972f6Sopenharmony_ci  }
687195972f6Sopenharmony_ci#if LWIP_TCPIP_CORE_LOCKING
688195972f6Sopenharmony_ci  if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
689195972f6Sopenharmony_ci    LWIP_ASSERT("failed to create lock_tcpip_core", 0);
690195972f6Sopenharmony_ci  }
691195972f6Sopenharmony_ci#endif /* LWIP_TCPIP_CORE_LOCKING */
692195972f6Sopenharmony_ci
693195972f6Sopenharmony_ci  sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
694195972f6Sopenharmony_ci}
695195972f6Sopenharmony_ci
696195972f6Sopenharmony_ci/**
697195972f6Sopenharmony_ci * Simple callback function used with tcpip_callback to free a pbuf
698195972f6Sopenharmony_ci * (pbuf_free has a wrong signature for tcpip_callback)
699195972f6Sopenharmony_ci *
700195972f6Sopenharmony_ci * @param p The pbuf (chain) to be dereferenced.
701195972f6Sopenharmony_ci */
702195972f6Sopenharmony_cistatic void
703195972f6Sopenharmony_cipbuf_free_int(void *p)
704195972f6Sopenharmony_ci{
705195972f6Sopenharmony_ci  struct pbuf *q = (struct pbuf *)p;
706195972f6Sopenharmony_ci  pbuf_free(q);
707195972f6Sopenharmony_ci}
708195972f6Sopenharmony_ci
709195972f6Sopenharmony_ci/**
710195972f6Sopenharmony_ci * A simple wrapper function that allows you to free a pbuf from interrupt context.
711195972f6Sopenharmony_ci *
712195972f6Sopenharmony_ci * @param p The pbuf (chain) to be dereferenced.
713195972f6Sopenharmony_ci * @return ERR_OK if callback could be enqueued, an err_t if not
714195972f6Sopenharmony_ci */
715195972f6Sopenharmony_cierr_t
716195972f6Sopenharmony_cipbuf_free_callback(struct pbuf *p)
717195972f6Sopenharmony_ci{
718195972f6Sopenharmony_ci  return tcpip_try_callback(pbuf_free_int, p);
719195972f6Sopenharmony_ci}
720195972f6Sopenharmony_ci
721195972f6Sopenharmony_ci/**
722195972f6Sopenharmony_ci * A simple wrapper function that allows you to free heap memory from
723195972f6Sopenharmony_ci * interrupt context.
724195972f6Sopenharmony_ci *
725195972f6Sopenharmony_ci * @param m the heap memory to free
726195972f6Sopenharmony_ci * @return ERR_OK if callback could be enqueued, an err_t if not
727195972f6Sopenharmony_ci */
728195972f6Sopenharmony_cierr_t
729195972f6Sopenharmony_cimem_free_callback(void *m)
730195972f6Sopenharmony_ci{
731195972f6Sopenharmony_ci  return tcpip_try_callback(mem_free, m);
732195972f6Sopenharmony_ci}
733195972f6Sopenharmony_ci
734195972f6Sopenharmony_ci#endif /* !NO_SYS */
735