From 5e2ae7ac19220c75d23c2c2f8433d0296d41ddad Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 15 Dec 2016 14:37:21 +0800 Subject: [PATCH 1/2] lwip: fix lwip dual core issue Call xSemaphoreGiveFromISR instead xSemaphoreGive when the calling context is in critical section. --- components/lwip/port/freertos/sys_arch.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c index 8d0dd08c5..9efb151e8 100755 --- a/components/lwip/port/freertos/sys_arch.c +++ b/components/lwip/port/freertos/sys_arch.c @@ -42,6 +42,8 @@ /* This is the number of threads that can be started with sys_thread_new() */ #define SYS_THREAD_MAX 4 +static bool g_lwip_in_critical_section = false; + #if !LWIP_COMPAT_MUTEX /** Create a new mutex * @param mutex pointer to the mutex to create @@ -122,7 +124,11 @@ sys_sem_new(sys_sem_t *sem, u8_t count) void sys_sem_signal(sys_sem_t *sem) { - xSemaphoreGive(*sem); + if (g_lwip_in_critical_section){ + xSemaphoreGiveFromISR(*sem, NULL); + } else { + xSemaphoreGive(*sem); + } } /*-----------------------------------------------------------------------------------*/ @@ -453,6 +459,7 @@ sys_prot_t sys_arch_protect(void) { portENTER_CRITICAL(&g_lwip_mux); + g_lwip_in_critical_section = true; return (sys_prot_t) 1; } @@ -467,6 +474,7 @@ void sys_arch_unprotect(sys_prot_t pval) { (void) pval; + g_lwip_in_critical_section = false; portEXIT_CRITICAL(&g_lwip_mux); } From 55726385a44a565b707707a91d12adacc7cbcd61 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 15 Dec 2016 15:06:00 +0800 Subject: [PATCH 2/2] add more comments and call portYIELD when necessary --- components/lwip/port/freertos/sys_arch.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c index 9efb151e8..97ee32d1b 100755 --- a/components/lwip/port/freertos/sys_arch.c +++ b/components/lwip/port/freertos/sys_arch.c @@ -43,6 +43,7 @@ #define SYS_THREAD_MAX 4 static bool g_lwip_in_critical_section = false; +static BaseType_t g_lwip_critical_section_needs_taskswitch; #if !LWIP_COMPAT_MUTEX /** Create a new mutex @@ -125,7 +126,14 @@ void sys_sem_signal(sys_sem_t *sem) { if (g_lwip_in_critical_section){ - xSemaphoreGiveFromISR(*sem, NULL); + /* In function event_callback in sockets.c, lwip signals a semaphore inside a critical + * section. According to the FreeRTOS documentation for FreertosTaskEnterCritical, it's + * not allowed to call any FreeRTOS API function within a critical region. Unfortunately, + * it's not feasible to rework the affected region in LWIP. As a solution, when in a + * critical region, we call xSemaphoreGiveFromISR. This routine is hand-vetted to work + * in a critical region and it will not cause a task switch. + */ + xSemaphoreGiveFromISR(*sem, &g_lwip_critical_section_needs_taskswitch); } else { xSemaphoreGive(*sem); } @@ -476,6 +484,10 @@ sys_arch_unprotect(sys_prot_t pval) (void) pval; g_lwip_in_critical_section = false; portEXIT_CRITICAL(&g_lwip_mux); + if (g_lwip_critical_section_needs_taskswitch){ + g_lwip_critical_section_needs_taskswitch = 0; + portYIELD(); + } } /*-----------------------------------------------------------------------------------*/