Gisle Vanem wrote:
> AFAICS, you could use the stuff in
> <Gnulib-root>/lib/glthread/*.c

Thanks a lot I was looking for something like this.

Please let me know if I am missing anything else.

Regards,
Akash Rawal
>From 40fc0f1cbc5184fca75fb955313caa8de430a2b2 Mon Sep 17 00:00:00 2001
From: Akash Rawal <[email protected]>
Date: Wed, 24 May 2017 09:08:34 +0530
Subject: [PATCH] * lib/select.c: Make select() multi-thread safe in windows

---
 lib/select.c   | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 modules/select |  1 +
 2 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/lib/select.c b/lib/select.c
index ac86c499d..ad704e11f 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -35,6 +35,7 @@
 #include <stdio.h>
 #include <conio.h>
 #include <time.h>
+#include <glthread/lock.h>
 
 /* Get the overridden 'struct timeval'.  */
 #include <sys/time.h>
@@ -105,6 +106,15 @@ IsSocketHandle (HANDLE h)
 
 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
    H).  */
+gl_once_define(static, windows_poll_handle_once)
+static PNtQueryInformationFile NtQueryInformationFile;
+void 
+static windows_poll_handle_init()
+{
+  NtQueryInformationFile = (PNtQueryInformationFile)
+    GetProcAddress (GetModuleHandle ("ntdll.dll"),
+                      "NtQueryInformationFile");
+}
 
 static int
 windows_poll_handle (HANDLE h, int fd,
@@ -119,8 +129,6 @@ windows_poll_handle (HANDLE h, int fd,
   BOOL bRet;
   IO_STATUS_BLOCK iosb;
   FILE_PIPE_LOCAL_INFORMATION fpli;
-  static PNtQueryInformationFile NtQueryInformationFile;
-  static BOOL once_only;
 
   read = write = except = FALSE;
   switch (GetFileType (h))
@@ -131,13 +139,7 @@ windows_poll_handle (HANDLE h, int fd,
       break;
 
     case FILE_TYPE_PIPE:
-      if (!once_only)
-        {
-          NtQueryInformationFile = (PNtQueryInformationFile)
-            GetProcAddress (GetModuleHandle ("ntdll.dll"),
-                            "NtQueryInformationFile");
-          once_only = TRUE;
-        }
+      glthread_once(&windows_poll_handle_once, windows_poll_handle_init);
 
       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
         {
@@ -240,13 +242,77 @@ windows_poll_handle (HANDLE h, int fd,
   return ret;
 }
 
+static struct
+{
+  HANDLE *data;
+  size_t len;
+  size_t alloc_len;
+} event_pool = {NULL, 0, 8};
+gl_lock_define_initialized(static, event_pool_lock)
+
+static HANDLE
+get_hevent()
+{
+  HANDLE res;
+  
+  glthread_lock_lock(&event_pool_lock);
+
+  if (event_pool.len)
+    {
+      event_pool.len--;
+      res = event_pool.data[event_pool.len];
+    }
+  else
+    {
+      res = CreateEvent (NULL, FALSE, FALSE, NULL);
+    }
+
+  glthread_lock_unlock(&event_pool_lock);
+
+  return res;
+}
+
+static void
+return_hevent(HANDLE v)
+{
+  glthread_lock_lock(&event_pool_lock);
+
+  event_pool.len++;
+
+  if (! event_pool.data)
+    {
+      event_pool.data = malloc(sizeof(HANDLE) * event_pool.alloc_len);
+      if (! event_pool.data)
+        {
+          fprintf(stderr, "Failed to allocate memory\n");
+          abort();
+        }
+    }
+    
+  if (event_pool.len > event_pool.alloc_len)
+    {
+      event_pool.alloc_len *= 2;
+      event_pool.data = realloc(event_pool.data, 
+                                sizeof(HANDLE) * event_pool.alloc_len);
+      if (! event_pool.data)
+        {
+          fprintf(stderr, "Failed to allocate memory\n");
+          abort();
+        }
+    }
+
+  event_pool.data[event_pool.len - 1] = v; 
+
+  glthread_lock_unlock(&event_pool_lock);
+}
+
 int
 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
             struct timeval *timeout)
 #undef timeval
 {
   static struct timeval tv0;
-  static HANDLE hEvent;
+  HANDLE hEvent;
   HANDLE h, handle_array[FD_SETSIZE + 2];
   fd_set handle_rfds, handle_wfds, handle_xfds;
   struct bitset rbits, wbits, xbits;
@@ -273,8 +339,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
         }
     }
 
-  if (!hEvent)
-    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+  hEvent = get_hevent();
 
   handle_array[0] = hEvent;
   nhandles = 1;
@@ -346,6 +411,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
       if (!h)
         {
           errno = EBADF;
+          return_hevent(hEvent);
           return -1;
         }
 
@@ -528,6 +594,8 @@ restart:
         }
     }
 
+  return_hevent(hEvent);
+
   return rc;
 }
 
diff --git a/modules/select b/modules/select
index 28c89ee9c..ced86a162 100644
--- a/modules/select
+++ b/modules/select
@@ -12,6 +12,7 @@ dup2            [test $REPLACE_SELECT = 1]
 sockets         [test $REPLACE_SELECT = 1]
 sys_time        [test $REPLACE_SELECT = 1]
 msvc-nothrow    [test $REPLACE_SELECT = 1]
+lock            [test $REPLACE_SELECT = 1]
 
 configure.ac:
 gl_FUNC_SELECT
-- 
2.13.0

Reply via email to