From f69b5f7e405caf7000974f11a7fbf8dc0dfc1b9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joan=20Lled=C3=B3?= <jlledom@member.fsf.org>
Date: Sun, 14 Jul 2019 12:30:40 +0200
Subject: [PATCH] Unix port: improve support for the Hurd

---
 contrib/ports/unix/check/CMakeLists.txt         | 10 +++++----
 contrib/ports/unix/port/include/arch/sys_arch.h |  3 +++
 contrib/ports/unix/port/sys_arch.c              | 29 ++++++++++++++++++++-----
 3 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/contrib/ports/unix/check/CMakeLists.txt b/contrib/ports/unix/check/CMakeLists.txt
index 68833163..9cf8d05a 100644
--- a/contrib/ports/unix/check/CMakeLists.txt
+++ b/contrib/ports/unix/check/CMakeLists.txt
@@ -4,12 +4,14 @@ set (CMAKE_CONFIGURATION_TYPES "Debug;Release")
 
 project(lwipunittests C)
 
-if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
-    message(FATAL_ERROR "Unit test are currently only working on Linux or Darwin")
+if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_SYSTEM_NAME STREQUAL "GNU")
+    message(FATAL_ERROR "Unit test are currently only working on Linux, Darwin or Hurd")
 endif()
 
 set(LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
-set(LWIP_USE_SANITIZERS true)
+if (NOT CMAKE_SYSTEM_NAME STREQUAL "GNU")
+    set(LWIP_USE_SANITIZERS true)
+endif()
 include(${LWIP_DIR}/contrib/ports/CMakeCommon.cmake)
 
 if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
@@ -45,7 +47,7 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
     target_link_libraries(lwip_unittests ${LIBSUBUNIT})
 endif()
 
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "GNU")
     find_library(LIBUTIL util)
     find_library(LIBPTHREAD pthread)
     find_library(LIBRT rt)
diff --git a/contrib/ports/unix/port/include/arch/sys_arch.h b/contrib/ports/unix/port/include/arch/sys_arch.h
index 416b716c..46c559dc 100644
--- a/contrib/ports/unix/port/include/arch/sys_arch.h
+++ b/contrib/ports/unix/port/include/arch/sys_arch.h
@@ -35,6 +35,9 @@
 #define SYS_MBOX_NULL NULL
 #define SYS_SEM_NULL  NULL
 
+/* Return code for an interrupted timed wait */
+#define SYS_ARCH_INTR 0xfffffffeUL
+
 /*typedef u32_t sys_prot_t;*/
 
 struct sys_sem;
diff --git a/contrib/ports/unix/port/sys_arch.c b/contrib/ports/unix/port/sys_arch.c
index a56d7de1..a2884cfc 100644
--- a/contrib/ports/unix/port/sys_arch.c
+++ b/contrib/ports/unix/port/sys_arch.c
@@ -489,14 +489,20 @@ cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout)
   struct timespec rtime1, rtime2, ts;
   int ret;
 
-#ifdef __GNU__
+#ifdef LWIP_UNIX_HURD
   #define pthread_cond_wait pthread_hurd_cond_wait_np
   #define pthread_cond_timedwait pthread_hurd_cond_timedwait_np
 #endif
 
   if (timeout == 0) {
-    pthread_cond_wait(cond, mutex);
-    return 0;
+    ret = pthread_cond_wait(cond, mutex);
+    return
+#ifdef LWIP_UNIX_HURD
+    /* On the Hurd, ret == 1 means the RPC has been cancelled.
+     * The thread is awakened (not terminated) and execution must continue */
+    ret == 1 ? SYS_ARCH_INTR :
+#endif
+    (u32_t)ret;
   }
 
   /* Get a timestamp and add the timeout value. */
@@ -517,6 +523,12 @@ cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout)
 #endif
   if (ret == ETIMEDOUT) {
     return SYS_ARCH_TIMEOUT;
+#ifdef LWIP_UNIX_HURD
+    /* On the Hurd, ret == 1 means the RPC has been cancelled.
+     * The thread is awakened (not terminated) and execution must continue */
+  } else if (ret == EINTR) {
+    return SYS_ARCH_INTR;
+#endif
   }
 
   /* Calculate for how long we waited for the cond. */
@@ -546,11 +558,18 @@ sys_arch_sem_wait(struct sys_sem **s, u32_t timeout)
       if (time_needed == SYS_ARCH_TIMEOUT) {
         pthread_mutex_unlock(&(sem->mutex));
         return SYS_ARCH_TIMEOUT;
+#ifdef LWIP_UNIX_HURD
+      } else if(time_needed == SYS_ARCH_INTR) {
+        pthread_mutex_unlock(&(sem->mutex));
+        return 0;
+#endif
       }
       /*      pthread_mutex_unlock(&(sem->mutex));
               return time_needed; */
-    } else {
-      cond_wait(&(sem->cond), &(sem->mutex), 0);
+    } else if(cond_wait(&(sem->cond), &(sem->mutex), 0)) {
+      /* Some error happened or the thread has been awakened but not by lwip */
+      pthread_mutex_unlock(&(sem->mutex));
+      return 0;
     }
   }
   sem->c--;
-- 
2.11.0

