lwIP started targeting single-threaded environments.
When adding multi- threading support, instead of making the core thread-safe, another approach was chosen: there is one main thread running the lwIP core (also known as the "tcpip_thread"). When running in a multithreaded environment, raw API functions MUST only be called from the core thread since raw API functions are not protected from concurrent access (aside from pbuf- and memory management functions). Application threads using the sequential- or socket API communicate with this main thread through message passing.
As such, the list of functions that may be called from other threads or an ISR is very limited! Only functions from these API header files are thread-safe:
Additionaly, memory (de-)allocation functions may be called from multiple threads (not ISR!) with NO_SYS=0 since they are protected by SYS_LIGHTWEIGHT_PROT and/or semaphores.
Netconn or Socket API functions are thread safe against the core thread but they are not reentrant at the control block granularity level. That is, a UDP or TCP control block must not be shared among multiple threads without proper locking.
If SYS_LIGHTWEIGHT_PROT is set to 1 and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, pbuf_free() may also be called from another thread or an ISR (since only then, mem_free - for PBUF_RAM - may be called from an ISR: otherwise, the HEAP is only protected by semaphores).
It is strongly recommended to implement the LWIP_ASSERT_CORE_LOCKED() macro in an application that uses multithreading. lwIP code has several places where a check for a correct thread context is implemented which greatly helps the user to get threading done right. See the example sys_arch.c files in unix and Win32 port in the contrib repository.
In short: Copy the functions sys_mark_tcpip_thread() and sys_check_core_locking() to your port and modify them to work with your OS. Then let LWIP_ASSERT_CORE_LOCKED() and LWIP_MARK_TCPIP_THREAD() point to these functions.
If you use LWIP_TCPIP_CORE_LOCKING, you also need to copy and adapt the functions sys_lock_tcpip_core() and sys_unlock_tcpip_core(). Let LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE() point to these functions.