Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2009-07-06 19:42:01 +0400
committerCorinna Vinschen <corinna@vinschen.de>2009-07-06 19:42:01 +0400
commit023c25829cef04ee4869063160bdad12fc231d34 (patch)
treee9cab2d22a73a24fc62240fe1fbcfe0bfbd3ddbd /winsup/cygwin
parent1183d7fb13e9ad0fcd02b8c96c8d413b448b0ae1 (diff)
* 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.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/cygtls.cc13
-rw-r--r--winsup/cygwin/cygtls.h7
-rw-r--r--winsup/cygwin/select.cc81
-rw-r--r--winsup/cygwin/select.h1
5 files changed, 91 insertions, 33 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 1f824a391..4a16d36ab 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index 1d8153a32..16743af46 100644
--- a/winsup/cygwin/cygtls.cc
+++ b/winsup/cygwin/cygtls.cc
@@ -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);
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index 5b944eb91..138d8f2bb 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -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")];
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 07fb30e09..6e46c4ed1 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -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");
diff --git a/winsup/cygwin/select.h b/winsup/cygwin/select.h
index 766f8c679..743222ebd 100644
--- a/winsup/cygwin/select.h
+++ b/winsup/cygwin/select.h
@@ -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;