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