diff --git a/src/api/tcpip.c b/src/api/tcpip.c index f2c65349..6763a5cb 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -91,6 +91,8 @@ tcpip_thread(void *arg) struct tcpip_msg *msg; LWIP_UNUSED_ARG(arg); + LWIP_MARK_TCPIP_THREAD(); + if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); } diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c index 441b34c9..47394305 100644 --- a/src/core/ipv4/ip4.c +++ b/src/core/ipv4/ip4.c @@ -422,6 +422,8 @@ ip4_input(struct pbuf *p, struct netif *inp) int check_ip_src = 1; #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */ + LWIP_ASSERT_CORE_LOCKED(); + IP_STATS_INC(ip.recv); MIB2_STATS_INC(mib2.ipinreceives); diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c index bab6d738..647c44e0 100644 --- a/src/core/ipv6/ip6.c +++ b/src/core/ipv6/ip6.c @@ -515,6 +515,8 @@ ip6_input(struct pbuf *p, struct netif *inp) int check_ip_src=1; #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + LWIP_ASSERT_CORE_LOCKED(); + IP6_STATS_INC(ip6.recv); /* identify the IP header */ diff --git a/src/core/netif.c b/src/core/netif.c index 5050e812..16fa9511 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -210,6 +210,8 @@ netif_init(void) err_t netif_input(struct pbuf *p, struct netif *inp) { + LWIP_ASSERT_CORE_LOCKED(); + #if LWIP_ETHERNET if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { return ethernet_input(p, inp); @@ -272,6 +274,8 @@ netif_add(struct netif *netif, s8_t i; #endif + LWIP_ASSERT_CORE_LOCKED(); + #if LWIP_SINGLE_NETIF if (netif_default != NULL) { LWIP_ASSERT("single netif already set", 0); @@ -441,6 +445,8 @@ netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t * } #endif + LWIP_ASSERT_CORE_LOCKED(); + if (ip4_addr_isany(ipaddr)) { /* when removing an address, we have to remove it *before* changing netmask/gw to ensure that tcp RST segment can be sent correctly */ @@ -475,6 +481,8 @@ netif_remove(struct netif *netif) int i; #endif + LWIP_ASSERT_CORE_LOCKED(); + if (netif == NULL) { return; } @@ -575,6 +583,9 @@ void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) { ip_addr_t new_addr; + + LWIP_ASSERT_CORE_LOCKED(); + *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); @@ -642,6 +653,8 @@ netif_set_gw(struct netif *netif, const ip4_addr_t *gw) args.ipv4_gw_changed.old_address = &old_addr; #endif + LWIP_ASSERT_CORE_LOCKED(); + /* address is actually being changed? */ if (ip4_addr_cmp(safe_gw, netif_ip4_gw(netif)) == 0) { ip4_addr_set(ip_2_ip4(&netif->gw), gw); @@ -678,6 +691,8 @@ netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) args.ipv4_nm_changed.old_address = &old_addr; #endif + LWIP_ASSERT_CORE_LOCKED(); + /* address is actually being changed? */ if (ip4_addr_cmp(safe_netmask, netif_ip4_netmask(netif)) == 0) { mib2_remove_route_ip4(0, netif); @@ -707,6 +722,8 @@ netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) void netif_set_default(struct netif *netif) { + LWIP_ASSERT_CORE_LOCKED(); + if (netif == NULL) { /* remove default route */ mib2_remove_route_ip4(1, netif); @@ -727,6 +744,8 @@ netif_set_default(struct netif *netif) void netif_set_up(struct netif *netif) { + LWIP_ASSERT_CORE_LOCKED(); + if (!(netif->flags & NETIF_FLAG_UP)) { netif_set_flags(netif, NETIF_FLAG_UP); @@ -751,6 +770,8 @@ netif_set_up(struct netif *netif) static void netif_issue_reports(struct netif *netif, u8_t report_type) { + LWIP_ASSERT_CORE_LOCKED(); + /* Only send reports when both link and admin states are up */ if (!(netif->flags & NETIF_FLAG_LINK_UP) || !(netif->flags & NETIF_FLAG_UP)) { @@ -797,6 +818,8 @@ netif_issue_reports(struct netif *netif, u8_t report_type) void netif_set_down(struct netif *netif) { + LWIP_ASSERT_CORE_LOCKED(); + if (netif->flags & NETIF_FLAG_UP) { #if LWIP_NETIF_EXT_STATUS_CALLBACK { @@ -831,6 +854,8 @@ netif_set_down(struct netif *netif) void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) { + LWIP_ASSERT_CORE_LOCKED(); + if (netif) { netif->status_callback = status_callback; } @@ -858,6 +883,8 @@ netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_c void netif_set_link_up(struct netif *netif) { + LWIP_ASSERT_CORE_LOCKED(); + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { netif_set_flags(netif, NETIF_FLAG_LINK_UP); @@ -889,6 +916,8 @@ netif_set_link_up(struct netif *netif) void netif_set_link_down(struct netif *netif ) { + LWIP_ASSERT_CORE_LOCKED(); + if (netif->flags & NETIF_FLAG_LINK_UP) { netif_clear_flags(netif, NETIF_FLAG_LINK_UP); NETIF_LINK_CALLBACK(netif); @@ -910,6 +939,8 @@ netif_set_link_down(struct netif *netif ) void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) { + LWIP_ASSERT_CORE_LOCKED(); + if (netif) { netif->link_callback = link_callback; } @@ -1133,6 +1164,8 @@ netif_alloc_client_data_id(void) u8_t result = netif_client_id; netif_client_id++; + LWIP_ASSERT_CORE_LOCKED(); + #if LWIP_NUM_NETIF_CLIENT_DATA > 256 #error LWIP_NUM_NETIF_CLIENT_DATA must be <= 256 #endif @@ -1156,6 +1189,9 @@ void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) { LWIP_ASSERT("addr6 != NULL", addr6 != NULL); + + LWIP_ASSERT_CORE_LOCKED(); + netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], addr6->addr[2], addr6->addr[3]); } @@ -1175,6 +1211,7 @@ netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, { ip_addr_t old_addr; ip_addr_t new_ipaddr; + LWIP_ASSERT_CORE_LOCKED(); LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); @@ -1238,6 +1275,7 @@ void netif_ip6_addr_set_state(struct netif *netif, s8_t addr_idx, u8_t state) { u8_t old_state; + LWIP_ASSERT_CORE_LOCKED(); LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); @@ -1317,6 +1355,8 @@ netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) { s8_t i; + LWIP_ASSERT_CORE_LOCKED(); + #if LWIP_IPV6_SCOPES if (ip6_addr_has_zone(ip6addr) && !ip6_addr_test_zone(ip6addr, netif)) { return -1; /* wrong zone, no match */ @@ -1345,6 +1385,8 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) { u8_t i, addr_index; + LWIP_ASSERT_CORE_LOCKED(); + /* Link-local prefix. */ ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; @@ -1409,6 +1451,8 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos { s8_t i; + LWIP_ASSERT_CORE_LOCKED(); + i = netif_get_ip6_addr_match(netif, ip6addr); if (i >= 0) { /* Address already added */ @@ -1501,6 +1545,8 @@ netif_get_by_index(u8_t idx) { struct netif *netif; + LWIP_ASSERT_CORE_LOCKED(); + if (idx != NETIF_NO_INDEX) { NETIF_FOREACH(netif) { if (idx == netif_get_index(netif)) { @@ -1525,6 +1571,8 @@ netif_find(const char *name) struct netif *netif; u8_t num; + LWIP_ASSERT_CORE_LOCKED(); + if (name == NULL) { return NULL; } @@ -1552,6 +1600,7 @@ netif_find(const char *name) */ void netif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn) { + LWIP_ASSERT_CORE_LOCKED(); LWIP_ASSERT("callback must be != NULL", callback != NULL); LWIP_ASSERT("fn must be != NULL", fn != NULL); diff --git a/src/core/timeouts.c b/src/core/timeouts.c index 1290661d..01e0d0ec 100644 --- a/src/core/timeouts.c +++ b/src/core/timeouts.c @@ -208,6 +208,8 @@ sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) struct sys_timeo *timeout, *t; u32_t now, diff; + LWIP_ASSERT_CORE_LOCKED(); + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); if (timeout == NULL) { LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); @@ -275,6 +277,8 @@ sys_untimeout(sys_timeout_handler handler, void *arg) { struct sys_timeo *prev_t, *t; + LWIP_ASSERT_CORE_LOCKED(); + if (next_timeout == NULL) { return; } @@ -313,6 +317,8 @@ static void sys_check_timeouts(void) { + LWIP_ASSERT_CORE_LOCKED(); + if (next_timeout) { struct sys_timeo *tmptimeout; u32_t diff; @@ -369,6 +375,8 @@ sys_check_timeouts(void) void sys_restart_timeouts(void) { + LWIP_ASSERT_CORE_LOCKED(); + timeouts_last_time = sys_now(); } @@ -382,6 +390,9 @@ u32_t sys_timeouts_sleeptime(void) { u32_t diff; + + LWIP_ASSERT_CORE_LOCKED(); + if (next_timeout == NULL) { return 0xffffffff; } diff --git a/src/core/udp.c b/src/core/udp.c index 9804a57c..82b27c07 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -198,6 +198,7 @@ udp_input(struct pbuf *p, struct netif *inp) u8_t for_us = 0; LWIP_UNUSED_ARG(inp); + LWIP_ASSERT_CORE_LOCKED(); PERF_START; @@ -680,6 +681,8 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d u8_t ip_proto; u8_t ttl; + LWIP_ASSERT_CORE_LOCKED(); + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { return ERR_VAL; @@ -893,6 +896,8 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) ip_addr_t zoned_ipaddr; #endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */ + LWIP_ASSERT_CORE_LOCKED(); + #if LWIP_IPV4 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ if (ipaddr == NULL) { @@ -995,6 +1000,8 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) void udp_bind_netif(struct udp_pcb *pcb, const struct netif *netif) { + LWIP_ASSERT_CORE_LOCKED(); + if (netif != NULL) { pcb->netif_idx = netif_get_index(netif); } else { @@ -1024,6 +1031,8 @@ udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) { struct udp_pcb *ipcb; + LWIP_ASSERT_CORE_LOCKED(); + if ((pcb == NULL) || (ipaddr == NULL)) { return ERR_VAL; } @@ -1076,6 +1085,8 @@ udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) void udp_disconnect(struct udp_pcb *pcb) { + LWIP_ASSERT_CORE_LOCKED(); + /* reset remote address association */ #if LWIP_IPV4 && LWIP_IPV6 if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { @@ -1104,6 +1115,8 @@ udp_disconnect(struct udp_pcb *pcb) void udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) { + LWIP_ASSERT_CORE_LOCKED(); + /* remember recv() callback and user data */ pcb->recv = recv; pcb->recv_arg = recv_arg; @@ -1123,6 +1136,8 @@ udp_remove(struct udp_pcb *pcb) { struct udp_pcb *pcb2; + LWIP_ASSERT_CORE_LOCKED(); + mib2_udp_unbind(pcb); /* pcb to be removed is first in list? */ if (udp_pcbs == pcb) { @@ -1157,6 +1172,9 @@ struct udp_pcb * udp_new(void) { struct udp_pcb *pcb; + + LWIP_ASSERT_CORE_LOCKED(); + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); /* could allocate UDP PCB? */ if (pcb != NULL) { @@ -1191,6 +1209,9 @@ struct udp_pcb * udp_new_ip_type(u8_t type) { struct udp_pcb *pcb; + + LWIP_ASSERT_CORE_LOCKED(); + pcb = udp_new(); #if LWIP_IPV4 && LWIP_IPV6 if (pcb != NULL) { diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 54bc01e4..be5fa983 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -212,6 +212,27 @@ #if !defined SYS_LIGHTWEIGHT_PROT || defined __DOXYGEN__ #define SYS_LIGHTWEIGHT_PROT 1 #endif + +/** + * LWIP_ASSERT_CORE_LOCKED: Macro to check whether lwIP's threading/locking + * requirements are satisfied during current function call. + * This macro usually calls a function that is implemented in the OS-dependent + * sys layer and performs the following checks: + * - Not in ISR + * - If LWIP_TCPIP_CORE_LOCKING=1: TCPIP core lock is held + * - If LWIP_TCPIP_CORE_LOCKING=0: function is called from TCPIP thread + */ +#if !defined LWIP_ASSERT_CORE_LOCKED || defined __DOXYGEN__ +#define LWIP_ASSERT_CORE_LOCKED() +#endif + +/** + * Called as first thing in the lwIP TCPIP thread. Can be used in conjunction + * with LWIP_ASSERT_CORE_LOCKED to check core locking. + */ +#if !defined LWIP_MARK_TCPIP_THREAD || defined __DOXYGEN__ +#define LWIP_MARK_TCPIP_THREAD() +#endif /** * @} */