From 5e2ae7ac19220c75d23c2c2f8433d0296d41ddad Mon Sep 17 00:00:00 2001
From: Liu Zhi Fu <liuzhifu@espressif.com>
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 8d0dd08c58..9efb151e8e 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 <liuzhifu@espressif.com>
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 9efb151e8e..97ee32d1bd 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();
+  }
 }
 
 /*-----------------------------------------------------------------------------------*/