From f9d653bd6329c4ee5d2839abe2a858a50cd49be7 Mon Sep 17 00:00:00 2001
From: David Lockyer <david.lockyer@chronos.co.uk>
Date: Tue, 12 Sep 2017 10:06:06 +0100
Subject: [PATCH 1/4] Ported lwip_select() mpu fixes from STABLE-2_0_0 branch.

---
 src/api/sockets.c                    | 57 +++++++++++++++++++++---------------
 src/include/lwip/opt.h               |  8 +++++
 src/include/lwip/priv/memp_std.h     |  4 +++
 src/include/lwip/priv/sockets_priv.h | 27 +++++++++++++++++
 4 files changed, 73 insertions(+), 23 deletions(-)

diff --git a/src/api/sockets.c b/src/api/sockets.c
index a23c797..4b3925b 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -84,6 +84,12 @@
 #define LWIP_NETCONN 0
 #endif
 
+#define API_SELECT_CB_VAR_REF(name)               API_VAR_REF(name)
+#define API_SELECT_CB_VAR_DECLARE(name)           API_VAR_DECLARE(struct lwip_select_cb, name)
+#define API_SELECT_CB_VAR_ALLOC(name)             API_VAR_ALLOC(struct lwip_select_cb, MEMP_SELECT_CB, name, ERR_MEM)
+#define API_SELECT_CB_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct lwip_select_cb, MEMP_SELECT_CB, name, NULL)
+#define API_SELECT_CB_VAR_FREE(name)              API_VAR_FREE(MEMP_SELECT_CB, name)
+
 #if LWIP_IPV4
 #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
       (sin)->sin_len = sizeof(struct sockaddr_in); \
@@ -1851,7 +1857,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
   int nready;
   fd_set lreadset, lwriteset, lexceptset;
   u32_t msectimeout;
-  struct lwip_select_cb select_cb;
+  API_SELECT_CB_VAR_DECLARE(select_cb);
   int i;
   int maxfdp2;
 #if LWIP_NETCONN_SEM_PER_THREAD
@@ -1863,6 +1869,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
   SYS_ARCH_DECL_PROTECT(lev);
   LWIP_SOCKET_SELECT_DECL_PROTECT(lev2);
 
+  API_SELECT_CB_VAR_ALLOC(select_cb);
+
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
                   maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
                   timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
@@ -1899,19 +1907,20 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
        list is only valid while we are in this function, so it's ok
        to use local variables. */
 
-    select_cb.next = NULL;
-    select_cb.prev = NULL;
-    select_cb.readset = readset;
-    select_cb.writeset = writeset;
-    select_cb.exceptset = exceptset;
-    select_cb.sem_signalled = 0;
+    API_SELECT_CB_VAR_REF(select_cb).next = NULL;
+    API_SELECT_CB_VAR_REF(select_cb).prev = NULL;
+    API_SELECT_CB_VAR_REF(select_cb).readset = readset;
+    API_SELECT_CB_VAR_REF(select_cb).writeset = writeset;
+    API_SELECT_CB_VAR_REF(select_cb).exceptset = exceptset;
+    API_SELECT_CB_VAR_REF(select_cb).sem_signalled = 0;
 #if LWIP_NETCONN_SEM_PER_THREAD
-    select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET();
+    API_SELECT_CB_VAR_REF(select_cb).sem = LWIP_NETCONN_THREAD_SEM_GET();
 #else /* LWIP_NETCONN_SEM_PER_THREAD */
-    if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) {
+    if (sys_sem_new(&API_SELECT_CB_VAR_REF(select_cb).sem, 0) != ERR_OK) {
       /* failed to create semaphore */
       set_errno(ENOMEM);
       lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
+      API_SELECT_CB_VAR_FREE(select_cb);
       return -1;
     }
 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
@@ -1920,11 +1929,11 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
     LWIP_SOCKET_SELECT_PROTECT(lev2);
 
     /* Put this select_cb on top of list */
-    select_cb.next = select_cb_list;
+    API_SELECT_CB_VAR_REF(select_cb).next = select_cb_list;
     if (select_cb_list != NULL) {
-      select_cb_list->prev = &select_cb;
+      select_cb_list->prev = &API_SELECT_CB_VAR_REF(select_cb);
     }
-    select_cb_list = &select_cb;
+    select_cb_list = &API_SELECT_CB_VAR_REF(select_cb);
 #if !LWIP_TCPIP_CORE_LOCKING
     /* Increasing this counter tells select_check_waiters that the list has changed. */
     select_cb_ctr++;
@@ -1986,7 +1995,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
           }
         }
 
-        waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout);
+        waitres = sys_arch_sem_wait(SELECT_SEM_PTR(API_SELECT_CB_VAR_REF(select_cb).sem), msectimeout);
 #if LWIP_NETCONN_SEM_PER_THREAD
         waited = 1;
 #endif
@@ -2018,15 +2027,15 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
     }
     /* Take us off the list */
     LWIP_SOCKET_SELECT_PROTECT(lev2);
-    if (select_cb.next != NULL) {
-      select_cb.next->prev = select_cb.prev;
+    if (API_SELECT_CB_VAR_REF(select_cb).next != NULL) {
+      API_SELECT_CB_VAR_REF(select_cb).next->prev = API_SELECT_CB_VAR_REF(select_cb).prev;
     }
-    if (select_cb_list == &select_cb) {
-      LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
-      select_cb_list = select_cb.next;
+    if (select_cb_list == &API_SELECT_CB_VAR_REF(select_cb)) {
+      LWIP_ASSERT("select_cb.prev == NULL", API_SELECT_CB_VAR_REF(select_cb).prev == NULL);
+      select_cb_list = API_SELECT_CB_VAR_REF(select_cb).next;
     } else {
-      LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
-      select_cb.prev->next = select_cb.next;
+      LWIP_ASSERT("select_cb.prev != NULL", API_SELECT_CB_VAR_REF(select_cb).prev != NULL);
+      API_SELECT_CB_VAR_REF(select_cb).prev->next = API_SELECT_CB_VAR_REF(select_cb).next;
     }
 #if !LWIP_TCPIP_CORE_LOCKING
     /* Increasing this counter tells select_check_waiters that the list has changed. */
@@ -2035,17 +2044,18 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
     LWIP_SOCKET_SELECT_UNPROTECT(lev2);
 
 #if LWIP_NETCONN_SEM_PER_THREAD
-    if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) {
+    if (API_SELECT_CB_VAR_REF(select_cb).sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) {
       /* don't leave the thread-local semaphore signalled */
-      sys_arch_sem_wait(select_cb.sem, 1);
+      sys_arch_sem_wait(API_SELECT_CB_VAR_REF(select_cb).sem, 1);
     }
 #else /* LWIP_NETCONN_SEM_PER_THREAD */
-    sys_sem_free(&select_cb.sem);
+    sys_sem_free(&API_SELECT_CB_VAR_REF(select_cb).sem);
 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
 
     if (nready < 0) {
       /* This happens when a socket got closed while waiting */
       lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
+      API_SELECT_CB_VAR_FREE(select_cb);
       return -1;
     }
 
@@ -2074,6 +2084,7 @@ return_copy_fdsets:
   if (exceptset) {
     *exceptset = lexceptset;
   }
+  API_SELECT_CB_VAR_FREE(select_cb);
   return nready;
 }
 
diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h
index 6813faa..5bb4b35 100644
--- a/src/include/lwip/opt.h
+++ b/src/include/lwip/opt.h
@@ -489,6 +489,14 @@
 #endif
 
 /**
+ * MEMP_NUM_SELECT_CB: the number of struct lwip_select_cb.
+ * (only needed if you use the sockets API)
+ */
+#if !defined MEMP_NUM_SELECT_CB || defined __DOXYGEN__
+#define MEMP_NUM_SELECT_CB              4
+#endif
+
+/**
  * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
  * for callback/timeout API communication.
  * (only needed if you use tcpip.c)
diff --git a/src/include/lwip/priv/memp_std.h b/src/include/lwip/priv/memp_std.h
index e2e5fbb..e00e5cb 100644
--- a/src/include/lwip/priv/memp_std.h
+++ b/src/include/lwip/priv/memp_std.h
@@ -68,6 +68,10 @@ LWIP_MEMPOOL(NETBUF,         MEMP_NUM_NETBUF,          sizeof(struct netbuf),
 LWIP_MEMPOOL(NETCONN,        MEMP_NUM_NETCONN,         sizeof(struct netconn),        "NETCONN")
 #endif /* LWIP_NETCONN || LWIP_SOCKET */
 
+#if LWIP_SOCKET && LWIP_SOCKET_SELECT
+LWIP_MEMPOOL(SELECT_CB,      MEMP_NUM_SELECT_CB,       sizeof(struct lwip_select_cb), "SELECT_CB")
+#endif /* LWIP_SOCKET */
+
 #if NO_SYS==0
 LWIP_MEMPOOL(TCPIP_MSG_API,  MEMP_NUM_TCPIP_MSG_API,   sizeof(struct tcpip_msg),      "TCPIP_MSG_API")
 #if LWIP_MPU_COMPATIBLE
diff --git a/src/include/lwip/priv/sockets_priv.h b/src/include/lwip/priv/sockets_priv.h
index d2ec917..9918aa2 100644
--- a/src/include/lwip/priv/sockets_priv.h
+++ b/src/include/lwip/priv/sockets_priv.h
@@ -43,6 +43,7 @@
 
 #include "lwip/err.h"
 #include "lwip/sockets.h"
+#include "lwip/sys.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -132,6 +133,32 @@ struct lwip_setgetsockopt_data {
 
 struct lwip_sock* lwip_socket_dbg_get_socket(int fd);
 
+#if LWIP_NETCONN_SEM_PER_THREAD
+#define SELECT_SEM_T        sys_sem_t*
+#define SELECT_SEM_PTR(sem) (sem)
+#else /* LWIP_NETCONN_SEM_PER_THREAD */
+#define SELECT_SEM_T        sys_sem_t
+#define SELECT_SEM_PTR(sem) (&(sem))
+#endif /* LWIP_NETCONN_SEM_PER_THREAD */
+
+/** Description for a task waiting in select */
+struct lwip_select_cb {
+  /** Pointer to the next waiting task */
+  struct lwip_select_cb *next;
+  /** Pointer to the previous waiting task */
+  struct lwip_select_cb *prev;
+  /** readset passed to select */
+  fd_set *readset;
+  /** writeset passed to select */
+  fd_set *writeset;
+  /** unimplemented: exceptset passed to select */
+  fd_set *exceptset;
+  /** don't signal the same semaphore twice: set to 1 when signalled */
+  int sem_signalled;
+  /** semaphore to wake up a task waiting for select */
+  SELECT_SEM_T sem;
+};
+
 #endif /* LWIP_SOCKET */
 
 #endif /* LWIP_HDR_SOCKETS_PRIV_H */
-- 
2.7.4


From 37e8245068373281fee276583dd269a2c13ea94d Mon Sep 17 00:00:00 2001
From: David Lockyer <david.lockyer@chronos.co.uk>
Date: Tue, 12 Sep 2017 10:24:49 +0100
Subject: [PATCH 2/4] Remove double-keep of #include lwip/sys.h from sockets.c.

---
 src/api/sockets.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/api/sockets.c b/src/api/sockets.c
index 4b3925b..d654807 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -51,7 +51,6 @@
 #include "lwip/sockets.h"
 #include "lwip/priv/sockets_priv.h"
 #include "lwip/api.h"
-#include "lwip/sys.h"
 #include "lwip/igmp.h"
 #include "lwip/inet.h"
 #include "lwip/tcp.h"
-- 
2.7.4


From 2259ba709fb339e894cc9320c8ce52019ae7a50c Mon Sep 17 00:00:00 2001
From: David Lockyer <david.lockyer@chronos.co.uk>
Date: Tue, 12 Sep 2017 10:27:56 +0100
Subject: [PATCH 3/4] Correct comment in memp_std.h.

---
 src/include/lwip/priv/memp_std.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/include/lwip/priv/memp_std.h b/src/include/lwip/priv/memp_std.h
index e00e5cb..c5e3c01 100644
--- a/src/include/lwip/priv/memp_std.h
+++ b/src/include/lwip/priv/memp_std.h
@@ -70,7 +70,7 @@ LWIP_MEMPOOL(NETCONN,        MEMP_NUM_NETCONN,         sizeof(struct netconn),
 
 #if LWIP_SOCKET && LWIP_SOCKET_SELECT
 LWIP_MEMPOOL(SELECT_CB,      MEMP_NUM_SELECT_CB,       sizeof(struct lwip_select_cb), "SELECT_CB")
-#endif /* LWIP_SOCKET */
+#endif /* LWIP_SOCKET && LWIP_SOCKET_SELECT */
 
 #if NO_SYS==0
 LWIP_MEMPOOL(TCPIP_MSG_API,  MEMP_NUM_TCPIP_MSG_API,   sizeof(struct tcpip_msg),      "TCPIP_MSG_API")
-- 
2.7.4


From 229335a2b9debeebe386343d473be2247f16ef9a Mon Sep 17 00:00:00 2001
From: David Lockyer <david.lockyer@chronos.co.uk>
Date: Tue, 12 Sep 2017 16:20:36 +0100
Subject: [PATCH 4/4] Updates to socket.c based on code review.

---
 src/api/sockets.c | 30 ++----------------------------
 1 file changed, 2 insertions(+), 28 deletions(-)

diff --git a/src/api/sockets.c b/src/api/sockets.c
index d654807..e074422 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -204,34 +204,6 @@ static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t*
 #endif
 
 
-#if LWIP_NETCONN_SEM_PER_THREAD
-#define SELECT_SEM_T        sys_sem_t*
-#define SELECT_SEM_PTR(sem) (sem)
-#else /* LWIP_NETCONN_SEM_PER_THREAD */
-#define SELECT_SEM_T        sys_sem_t
-#define SELECT_SEM_PTR(sem) (&(sem))
-#endif /* LWIP_NETCONN_SEM_PER_THREAD */
-
-#if LWIP_SOCKET_SELECT
-/** Description for a task waiting in select */
-struct lwip_select_cb {
-  /** Pointer to the next waiting task */
-  struct lwip_select_cb *next;
-  /** Pointer to the previous waiting task */
-  struct lwip_select_cb *prev;
-  /** readset passed to select */
-  fd_set *readset;
-  /** writeset passed to select */
-  fd_set *writeset;
-  /** exceptset passed to select */
-  fd_set *exceptset;
-  /** don't signal the same semaphore twice: set to 1 when signalled */
-  int sem_signalled;
-  /** semaphore to wake up a task waiting for select */
-  SELECT_SEM_T sem;
-};
-#endif /* LWIP_SOCKET_SELECT */
-
 /** A struct sockaddr replacement that has the same alignment as sockaddr_in/
  *  sockaddr_in6 if instantiated.
  */
@@ -1877,6 +1849,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
 
   if ((maxfdp1 < 0) || (maxfdp1 > (FD_SETSIZE + LWIP_SOCKET_OFFSET))) {
     set_errno(EINVAL);
+    API_SELECT_CB_VAR_FREE(select_cb);
     return -1;
   }
 
@@ -1889,6 +1862,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
   if (nready < 0) {
     set_errno(EBADF);
     lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
+    API_SELECT_CB_VAR_FREE(select_cb);
     return -1;
   }
 
-- 
2.7.4

