72#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
73#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
74#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
75#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
79static void *tcpip_init_done_arg;
81static sys_thread_t tcpip_thread_handle;
82static struct tcpip_msg tcpip_shutdown_msg;
83enum tcpip_lifecycle_state {
84 TCPIP_STATE_RUNNING = 0,
85 TCPIP_STATE_STOPPING = 1,
86 TCPIP_STATE_STOPPED = 2,
87 TCPIP_STATE_FAILED = 3,
88 TCPIP_STATE_INITIALIZING = 4
90static u8_t tcpip_shutdown_state = TCPIP_STATE_STOPPED;
91static u32_t tcpip_active_producers;
94tcpip_producer_enter(
void)
96 if (__atomic_load_n(&tcpip_shutdown_state, __ATOMIC_ACQUIRE) !=
97 TCPIP_STATE_RUNNING) {
101 __atomic_add_fetch(&tcpip_active_producers, 1, __ATOMIC_ACQ_REL);
102 if (__atomic_load_n(&tcpip_shutdown_state, __ATOMIC_ACQUIRE) !=
103 TCPIP_STATE_RUNNING) {
104 __atomic_sub_fetch(&tcpip_active_producers, 1, __ATOMIC_RELEASE);
111tcpip_producer_leave(
void)
113 LWIP_ASSERT(
"tcpip producer admission underflow",
114 __atomic_load_n(&tcpip_active_producers, __ATOMIC_RELAXED) != 0);
115 __atomic_sub_fetch(&tcpip_active_producers, 1, __ATOMIC_RELEASE);
118#if LWIP_TCPIP_CORE_LOCKING
120sys_mutex_t lock_tcpip_core;
125#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg)
128#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
142tcpip_thread(
void *arg)
147 while (__atomic_load_n(&tcpip_shutdown_state, __ATOMIC_ACQUIRE) ==
148 TCPIP_STATE_INITIALIZING) {
151 LWIP_ASSERT(
"tcpip_thread started outside running state",
152 __atomic_load_n(&tcpip_shutdown_state, __ATOMIC_ACQUIRE) ==
153 TCPIP_STATE_RUNNING);
155 if (tcpip_init_done != NULL) {
156 tcpip_init_done(tcpip_init_done_arg);
164 TCPIP_MBOX_FETCH(&mbox, (
void **)&msg);
168 LWIP_ASSERT(
"tcpip_thread: invalid message", 0);
172#if !LWIP_TCPIP_CORE_LOCKING
175 msg->msg.api_msg.function(msg->msg.api_msg.msg);
177 case TCPIP_MSG_API_CALL:
179 msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
184#if !LWIP_TCPIP_CORE_LOCKING_INPUT
185 case TCPIP_MSG_INPKT:
187 msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
192#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
193 case TCPIP_MSG_TIMEOUT:
195 sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
198 case TCPIP_MSG_UNTIMEOUT:
200 sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
205 case TCPIP_MSG_CALLBACK:
207 msg->msg.cb.function(msg->msg.cb.ctx);
211 case TCPIP_MSG_CALLBACK_STATIC:
213 msg->msg.cb.function(msg->msg.cb.ctx);
216 case TCPIP_MSG_SHUTDOWN:
222 LWIP_ASSERT(
"tcpip_thread: invalid message", 0);
238 if (!tcpip_producer_enter()) {
241#if LWIP_TCPIP_CORE_LOCKING_INPUT
245 ret = input_fn(p, inp);
247 tcpip_producer_leave();
256 tcpip_producer_leave();
260 msg->type = TCPIP_MSG_INPKT;
262 msg->msg.inp.netif = inp;
263 msg->msg.inp.input_fn = input_fn;
266 tcpip_producer_leave();
269 tcpip_producer_leave();
308tcpip_callback_with_block_admitted(
tcpip_callback_fn function,
void *ctx, u8_t block)
319 msg->type = TCPIP_MSG_CALLBACK;
320 msg->msg.cb.function = function;
321 msg->msg.cb.ctx = ctx;
338 if (!tcpip_producer_enter()) {
341 err = tcpip_callback_with_block_admitted(function, ctx, block);
342 tcpip_producer_leave();
349 sys_sem_t completion;
354tcpip_callback_wait_shim(
void *arg)
358 context->function(context->ctx);
361 __atomic_store_n(&context->retired, 1, __ATOMIC_RELEASE);
370 if (function == NULL) {
373 if (!tcpip_producer_enter()) {
377 __atomic_load_n(&tcpip_thread_handle, __ATOMIC_ACQUIRE))) {
379 tcpip_producer_leave();
382 context.function = function;
387 tcpip_producer_leave();
391 err = tcpip_callback_with_block_admitted(tcpip_callback_wait_shim, &context, 1);
394 while (!__atomic_load_n(&context.retired, __ATOMIC_ACQUIRE)) {
398 tcpip_producer_leave();
402#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
412tcpip_timeout(u32_t msecs, sys_timeout_handler h,
void *arg)
416 if (!tcpip_producer_enter()) {
423 tcpip_producer_leave();
427 msg->type = TCPIP_MSG_TIMEOUT;
428 msg->msg.tmo.msecs = msecs;
430 msg->msg.tmo.arg = arg;
432 tcpip_producer_leave();
444tcpip_untimeout(sys_timeout_handler h,
void *arg)
448 if (!tcpip_producer_enter()) {
455 tcpip_producer_leave();
459 msg->type = TCPIP_MSG_UNTIMEOUT;
461 msg->msg.tmo.arg = arg;
463 tcpip_producer_leave();
484 if (!tcpip_producer_enter()) {
487#if LWIP_TCPIP_CORE_LOCKING
492 tcpip_producer_leave();
495 TCPIP_MSG_VAR_DECLARE(msg);
497 LWIP_ASSERT(
"semaphore not initialized",
sys_sem_valid(sem));
500#if LWIP_MPU_COMPATIBLE
503 tcpip_producer_leave();
507 TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
508 TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
509 TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
512 TCPIP_MSG_VAR_FREE(msg);
513 tcpip_producer_leave();
531 if (!tcpip_producer_enter()) {
534#if LWIP_TCPIP_CORE_LOCKING
539 tcpip_producer_leave();
542 TCPIP_MSG_VAR_DECLARE(msg);
544#if !LWIP_NETCONN_SEM_PER_THREAD
547 tcpip_producer_leave();
554#if LWIP_MPU_COMPATIBLE
557#if !LWIP_NETCONN_SEM_PER_THREAD
560 tcpip_producer_leave();
564 TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
565 TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
566 TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
567#if LWIP_NETCONN_SEM_PER_THREAD
568 TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
570 TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
574 TCPIP_MSG_VAR_FREE(msg);
576#if !LWIP_NETCONN_SEM_PER_THREAD
580 tcpip_producer_leave();
593struct tcpip_callback_msg*
600 msg->type = TCPIP_MSG_CALLBACK_STATIC;
601 msg->msg.cb.function = function;
602 msg->msg.cb.ctx = ctx;
603 return (
struct tcpip_callback_msg*)msg;
629 if (!tcpip_producer_enter()) {
634 tcpip_producer_leave();
650 u8_t state = TCPIP_STATE_STOPPED;
651 if (!__atomic_compare_exchange_n(
652 &tcpip_shutdown_state, &state, TCPIP_STATE_INITIALIZING, 0,
653 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
654 LWIP_ASSERT(
"tcpip_init called outside stopped state", 0);
657 LWIP_ASSERT(
"tcpip_init with active producers",
658 __atomic_load_n(&tcpip_active_producers, __ATOMIC_ACQUIRE) == 0);
661 tcpip_init_done = initfunc;
662 tcpip_init_done_arg = arg;
664 LWIP_ASSERT(
"failed to create tcpip_thread mbox", 0);
666#if LWIP_TCPIP_CORE_LOCKING
668 LWIP_ASSERT(
"failed to create lock_tcpip_core", 0);
674 LWIP_ASSERT(
"failed to create tcpip_thread", thread != NULL);
675 __atomic_store_n(&tcpip_thread_handle, thread, __ATOMIC_RELEASE);
676 __atomic_store_n(&tcpip_shutdown_state, TCPIP_STATE_RUNNING, __ATOMIC_RELEASE);
682 u8_t state = __atomic_load_n(&tcpip_shutdown_state, __ATOMIC_ACQUIRE);
684 if (state == TCPIP_STATE_STOPPED) {
687 if (state == TCPIP_STATE_FAILED) {
690 if (state == TCPIP_STATE_STOPPING || state == TCPIP_STATE_INITIALIZING) {
694 if (!tcpip_producer_enter()) {
695 state = __atomic_load_n(&tcpip_shutdown_state, __ATOMIC_ACQUIRE);
696 return state == TCPIP_STATE_STOPPED
701 sys_thread_t thread =
702 __atomic_load_n(&tcpip_thread_handle, __ATOMIC_ACQUIRE);
704 tcpip_producer_leave();
709 state = __atomic_load_n(&tcpip_shutdown_state, __ATOMIC_ACQUIRE);
710 if (state != TCPIP_STATE_RUNNING) {
711 return state == TCPIP_STATE_STOPPED
716 state = TCPIP_STATE_RUNNING;
717 if (!__atomic_compare_exchange_n(
718 &tcpip_shutdown_state, &state, TCPIP_STATE_STOPPING, 0,
719 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
720 return state == TCPIP_STATE_STOPPED
725 while (__atomic_load_n(&tcpip_active_producers, __ATOMIC_ACQUIRE) != 0) {
729 tcpip_shutdown_msg.type = TCPIP_MSG_SHUTDOWN;
731 __atomic_store_n(&tcpip_shutdown_state, TCPIP_STATE_FAILED, __ATOMIC_RELEASE);
734 thread = __atomic_load_n(&tcpip_thread_handle, __ATOMIC_ACQUIRE);
736 __atomic_store_n(&tcpip_shutdown_state, TCPIP_STATE_FAILED, __ATOMIC_RELEASE);
739 __atomic_store_n(&tcpip_thread_handle, NULL, __ATOMIC_RELEASE);
741#if LWIP_TCPIP_CORE_LOCKING
751 tcpip_init_done = NULL;
752 tcpip_init_done_arg = NULL;
753 __atomic_store_n(&tcpip_shutdown_state, TCPIP_STATE_STOPPED, __ATOMIC_RELEASE);
764pbuf_free_int(
void *p)
779 return tcpip_callback_with_block(pbuf_free_int, p, 0);
792 return tcpip_callback_with_block(
mem_free, m, 0);
#define LWIP_DEBUGF(debug, message)
#define LWIP_UNUSED_ARG(x)
#define TCPIP_THREAD_NAME
#define TCPIP_THREAD_PRIO
#define LWIP_TCPIP_THREAD_ALIVE()
#define TCPIP_THREAD_STACKSIZE
#define NETIF_FLAG_ETHERNET
#define NETIF_FLAG_ETHARP
u8_t pbuf_free(struct pbuf *p)
void sys_mbox_post(sys_mbox_t *mbox, void *msg)
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
void sys_mbox_free(sys_mbox_t *mbox)
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
void sys_msleep(u32_t ms)
void sys_mutex_free(sys_mutex_t *mutex)
err_t sys_mutex_new(sys_mutex_t *mutex)
void sys_mutex_set_invalid(sys_mutex_t *mutex)
int sys_mutex_valid(sys_mutex_t *mutex)
int sys_sem_valid(sys_sem_t *sem)
void sys_sem_free(sys_sem_t *sem)
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
void sys_sem_signal(sys_sem_t *sem)
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
void mem_free(void *rmem)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
err_t(* netif_input_fn)(struct pbuf *p, struct netif *inp)
int sys_thread_is_current(sys_thread_t thread)
int sys_thread_join(sys_thread_t thread)
#define sys_mbox_valid_val(mbox)
#define sys_mbox_set_invalid_val(mbox)
err_t sys_mbox_post_and_close(sys_mbox_t *mbox, void *msg)
struct tcpip_callback_msg * tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
void tcpip_init(tcpip_init_done_fn initfunc, void *arg)
err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
err_t mem_free_callback(void *m)
err_t pbuf_free_callback(struct pbuf *p)
err_t tcpip_callback_wait(tcpip_callback_fn function, void *ctx)
err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
err_t tcpip_shutdown(void)
void tcpip_callbackmsg_delete(struct tcpip_callback_msg *msg)
err_t tcpip_trycallback(struct tcpip_callback_msg *msg)
err_t tcpip_input(struct pbuf *p, struct netif *inp)
void(* tcpip_callback_fn)(void *ctx)
void(* tcpip_init_done_fn)(void *arg)