OSDN Git Service

* cygtls.h (struct _local_storage): Add thread storage pointers for
authorcorinna <corinna>
Mon, 6 Jul 2009 15:42:01 +0000 (15:42 +0000)
committercorinna <corinna>
Mon, 6 Jul 2009 15:42:01 +0000 (15:42 +0000)
memory used by socket select functions.  Combine them into a single
struct select.
* cygtls.cc: Accommodate above change throughout.
(_cygtls::init_thread): Drop initalizing of sockevt to
INVALID_HANDLE_VALUE.
(_cygtls::fixup_after_fork): Reset sockevt to NULL.
(_cygtls::remove): Don't use sockevt value to bail out prematurely.
Set sockevt to NULL.  Free malloced select members.
* select.h (struct select_socket_info): Drop max_w4 member.
* select.cc (thread_socket): Use INFINITE timeout value if number of
objects to wait for is <= MAXIMUM_WAIT_OBJECTS.  Use num_w4 member
of select_socket_info struct rather than dropped max_w4.
(init_tls_select_info): New inline function to initialize TLS select
members.
(start_thread_socket): Just call init_tls_select_info to initialize TLS
select members and use them later on.
(socket_cleanup): Don't free select_socket_info pointer members since
they are thread local now.

winsup/cygwin/ChangeLog
winsup/cygwin/cygtls.cc
winsup/cygwin/cygtls.h
winsup/cygwin/select.cc
winsup/cygwin/select.h

index 1f824a3..4a16d36 100644 (file)
@@ -1,3 +1,25 @@
+2009-07-06  Corinna Vinschen  <corinna@vinschen.de>
+
+       * cygtls.h (struct _local_storage): Add thread storage pointers for
+       memory used by socket select functions.  Combine them into a single
+       struct select.
+       * cygtls.cc: Accommodate above change throughout.
+       (_cygtls::init_thread): Drop initalizing of sockevt to
+       INVALID_HANDLE_VALUE.
+       (_cygtls::fixup_after_fork): Reset sockevt to NULL.
+       (_cygtls::remove): Don't use sockevt value to bail out prematurely.
+       Set sockevt to NULL.  Free malloced select members.
+       * select.h (struct select_socket_info): Drop max_w4 member.
+       * select.cc (thread_socket): Use INFINITE timeout value if number of
+       objects to wait for is <= MAXIMUM_WAIT_OBJECTS.  Use num_w4 member
+       of select_socket_info struct rather than dropped max_w4.
+       (init_tls_select_info): New inline function to initialize TLS select
+       members.
+       (start_thread_socket): Just call init_tls_select_info to initialize TLS
+       select members and use them later on.
+       (socket_cleanup): Don't free select_socket_info pointer members since
+       they are thread local now.
+
 2009-07-06  Christopher Faylor  <me+cygwin@cgf.cx>
 
        * dtable.cc (handle_to_fn): Detect failing NtQueryObject.
index 1d8153a..16743af 100644 (file)
@@ -96,7 +96,6 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
 
   thread_id = GetCurrentThreadId ();
   initialized = CYGTLS_INITIALIZED;
-  locals.select_sockevt = INVALID_HANDLE_VALUE;
   errno_addr = &(local_clib._errno);
 
   if ((void *) func == (void *) cygthread::stub
@@ -126,7 +125,7 @@ _cygtls::fixup_after_fork ()
       sig = 0;
     }
   stacklock = spinning = 0;
-  locals.select_sockevt = INVALID_HANDLE_VALUE;
+  locals.select.sockevt = NULL;
   wq.thread_ev = NULL;
 }
 
@@ -141,7 +140,7 @@ void
 _cygtls::remove (DWORD wait)
 {
   initialized = 0;
-  if (!locals.select_sockevt || exit_state >= ES_FINAL)
+  if (exit_state >= ES_FINAL)
     return;
 
   debug_printf ("wait %p", wait);
@@ -149,10 +148,12 @@ _cygtls::remove (DWORD wait)
     {
       /* FIXME: Need some sort of atthreadexit function to allow things like
         select to control this themselves. */
-      if (locals.select_sockevt != INVALID_HANDLE_VALUE)
+      if (!locals.select.sockevt)
        {
-         CloseHandle (locals.select_sockevt);
-         locals.select_sockevt = (HANDLE) NULL;
+         CloseHandle (locals.select.sockevt);
+         locals.select.sockevt = NULL;
+         free_local (select.ser_num);
+         free_local (select.w4);
        }
       free_local (process_ident);
       free_local (ntoa_buf);
index 5b944eb..138d8f2 100644 (file)
@@ -104,7 +104,12 @@ struct _local_storage
   char mnt_dir[CYG_MAX_PATH];
 
   /* select.cc */
-  HANDLE select_sockevt;
+  struct {
+    HANDLE  sockevt;
+    int     max_w4;
+    LONG   *ser_num;                   // note: malloced
+    HANDLE *w4;                                // note: malloced
+  } select;
 
   /* strerror */
   char strerror_buf[sizeof ("Unknown error 4294967295")];
index 07fb30e..6e46c4e 100644 (file)
@@ -16,6 +16,7 @@ details. */
 
 #include "winsup.h"
 #include <stdlib.h>
+#include <sys/param.h>
 #include "ntdll.h"
 
 #include <wingdi.h>
@@ -1315,7 +1316,10 @@ static DWORD WINAPI
 thread_socket (void *arg)
 {
   select_socket_info *si = (select_socket_info *) arg;
-  DWORD timeout = 64 / (si->max_w4 / MAXIMUM_WAIT_OBJECTS);
+  DWORD timeout = (si->num_w4 <= MAXIMUM_WAIT_OBJECTS)
+                 ? INFINITE
+                 : (64 / (roundup2 (si->num_w4, MAXIMUM_WAIT_OBJECTS)
+                          / MAXIMUM_WAIT_OBJECTS));
   bool event = false;
 
   select_printf ("stuff_start %p", si->start);
@@ -1326,18 +1330,19 @@ thread_socket (void *arg)
          if (peek_socket (s, false))
            event = true;
       if (!event)
-       for (int i = 0; i < si->max_w4; i += MAXIMUM_WAIT_OBJECTS)
+       for (int i = 0; i < si->num_w4; i += MAXIMUM_WAIT_OBJECTS)
          switch (WaitForMultipleObjects (min (si->num_w4 - i,
                                               MAXIMUM_WAIT_OBJECTS),
                                          si->w4 + i, FALSE, timeout))
            {
            case WAIT_FAILED:
              goto out;
+           case WAIT_TIMEOUT:
+             continue;
            case WAIT_OBJECT_0:
              if (!i)   /* Socket event set. */
                goto out;
-             break;
-           case WAIT_TIMEOUT:
+             /*FALLTHRU*/
            default:
              break;
            }
@@ -1347,6 +1352,36 @@ out:
   return 0;
 }
 
+static inline bool init_tls_select_info () __attribute__ ((always_inline));
+static inline bool
+init_tls_select_info ()
+{
+  if (!_my_tls.locals.select.sockevt)
+    {
+      _my_tls.locals.select.sockevt = CreateEvent (&sec_none_nih, TRUE, FALSE,
+                                                  NULL);
+      if (!_my_tls.locals.select.sockevt)
+       return false;
+    }
+  if (!_my_tls.locals.select.ser_num)
+    {
+      _my_tls.locals.select.ser_num
+             = (LONG *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (LONG));
+      if (!_my_tls.locals.select.ser_num)
+       return false;
+      _my_tls.locals.select.w4
+             = (HANDLE *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (HANDLE));
+      if (!_my_tls.locals.select.w4)
+       {
+         free (_my_tls.locals.select.ser_num);
+         _my_tls.locals.select.ser_num = NULL;
+         return false;
+       }
+      _my_tls.locals.select.max_w4 = MAXIMUM_WAIT_OBJECTS;
+    }
+  return true;
+}
+
 static int
 start_thread_socket (select_record *me, select_stuff *stuff)
 {
@@ -1359,19 +1394,17 @@ start_thread_socket (select_record *me, select_stuff *stuff)
     }
 
   si = new select_socket_info;
-  si->ser_num = (LONG *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (LONG));
-  si->w4 = (HANDLE *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (HANDLE));
-  if (!si->ser_num || !si->w4)
+
+  if (!init_tls_select_info ())
     return 0;
-  si->max_w4 = MAXIMUM_WAIT_OBJECTS;
-  select_record *s = &stuff->start;
-  if (_my_tls.locals.select_sockevt != INVALID_HANDLE_VALUE)
-    si->w4[0] = _my_tls.locals.select_sockevt;
-  else if (!(si->w4[0] = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL)))
-    return 1;
-  else
-    _my_tls.locals.select_sockevt = si->w4[0];
+
+  si->ser_num = _my_tls.locals.select.ser_num;
+  si->w4 = _my_tls.locals.select.w4;
+
+  si->w4[0] = _my_tls.locals.select.sockevt;
   si->num_w4 = 1;
+
+  select_record *s = &stuff->start;
   while ((s = s->next))
     if (s->startup == start_thread_socket)
       {
@@ -1382,21 +1415,23 @@ start_thread_socket (select_record *me, select_stuff *stuff)
        for (int i = 1; i < si->num_w4; ++i)
          if (si->ser_num[i] == ser_num)
            goto continue_outer_loop;
-       if (si->num_w4 >= si->max_w4)
+       if (si->num_w4 >= _my_tls.locals.select.max_w4)
          {
            LONG *nser = (LONG *) realloc (si->ser_num,
-                                          (si->max_w4 + MAXIMUM_WAIT_OBJECTS)
+                                          (_my_tls.locals.select.max_w4
+                                           + MAXIMUM_WAIT_OBJECTS)
                                           * sizeof (LONG));
            if (!nser)
              return 0;
-           si->ser_num = nser;
+           _my_tls.locals.select.ser_num = si->ser_num = nser;
            HANDLE *nw4 = (HANDLE *) realloc (si->w4,
-                                          (si->max_w4 + MAXIMUM_WAIT_OBJECTS)
+                                          (_my_tls.locals.select.max_w4
+                                           + MAXIMUM_WAIT_OBJECTS)
                                           * sizeof (HANDLE));
            if (!nw4)
              return 0;
-           si->w4 = nw4;
-           si->max_w4 += MAXIMUM_WAIT_OBJECTS;
+           _my_tls.locals.select.w4 = si->w4 = nw4;
+           _my_tls.locals.select.max_w4 += MAXIMUM_WAIT_OBJECTS;
          }
        si->ser_num[si->num_w4] = ser_num;
        si->w4[si->num_w4++] = ((fhandler_socket *) s->fh)->wsock_event ();
@@ -1423,10 +1458,6 @@ socket_cleanup (select_record *, select_stuff *stuff)
       si->thread->detach ();
       ResetEvent (si->w4[0]);
       stuff->device_specific_socket = NULL;
-      if (si->ser_num)
-       free (si->ser_num);
-      if (si->w4)
-       free (si->w4);
       delete si;
     }
   select_printf ("returning");
index 766f8c6..743222e 100644 (file)
@@ -58,7 +58,6 @@ struct select_pipe_info: public select_info
 
 struct select_socket_info: public select_info
 {
-  int max_w4;
   int num_w4;
   LONG *ser_num;
   HANDLE *w4;