* 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.
This commit is contained in:
Corinna Vinschen 2009-07-06 15:42:01 +00:00
parent 1183d7fb13
commit 023c25829c
5 changed files with 91 additions and 33 deletions

View 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> 2009-07-06 Christopher Faylor <me+cygwin@cgf.cx>
* dtable.cc (handle_to_fn): Detect failing NtQueryObject. * dtable.cc (handle_to_fn): Detect failing NtQueryObject.

View File

@ -96,7 +96,6 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
thread_id = GetCurrentThreadId (); thread_id = GetCurrentThreadId ();
initialized = CYGTLS_INITIALIZED; initialized = CYGTLS_INITIALIZED;
locals.select_sockevt = INVALID_HANDLE_VALUE;
errno_addr = &(local_clib._errno); errno_addr = &(local_clib._errno);
if ((void *) func == (void *) cygthread::stub if ((void *) func == (void *) cygthread::stub
@ -126,7 +125,7 @@ _cygtls::fixup_after_fork ()
sig = 0; sig = 0;
} }
stacklock = spinning = 0; stacklock = spinning = 0;
locals.select_sockevt = INVALID_HANDLE_VALUE; locals.select.sockevt = NULL;
wq.thread_ev = NULL; wq.thread_ev = NULL;
} }
@ -141,7 +140,7 @@ void
_cygtls::remove (DWORD wait) _cygtls::remove (DWORD wait)
{ {
initialized = 0; initialized = 0;
if (!locals.select_sockevt || exit_state >= ES_FINAL) if (exit_state >= ES_FINAL)
return; return;
debug_printf ("wait %p", wait); debug_printf ("wait %p", wait);
@ -149,10 +148,12 @@ _cygtls::remove (DWORD wait)
{ {
/* FIXME: Need some sort of atthreadexit function to allow things like /* FIXME: Need some sort of atthreadexit function to allow things like
select to control this themselves. */ select to control this themselves. */
if (locals.select_sockevt != INVALID_HANDLE_VALUE) if (!locals.select.sockevt)
{ {
CloseHandle (locals.select_sockevt); CloseHandle (locals.select.sockevt);
locals.select_sockevt = (HANDLE) NULL; locals.select.sockevt = NULL;
free_local (select.ser_num);
free_local (select.w4);
} }
free_local (process_ident); free_local (process_ident);
free_local (ntoa_buf); free_local (ntoa_buf);

View File

@ -104,7 +104,12 @@ struct _local_storage
char mnt_dir[CYG_MAX_PATH]; char mnt_dir[CYG_MAX_PATH];
/* select.cc */ /* select.cc */
HANDLE select_sockevt; struct {
HANDLE sockevt;
int max_w4;
LONG *ser_num; // note: malloced
HANDLE *w4; // note: malloced
} select;
/* strerror */ /* strerror */
char strerror_buf[sizeof ("Unknown error 4294967295")]; char strerror_buf[sizeof ("Unknown error 4294967295")];

View File

@ -16,6 +16,7 @@ details. */
#include "winsup.h" #include "winsup.h"
#include <stdlib.h> #include <stdlib.h>
#include <sys/param.h>
#include "ntdll.h" #include "ntdll.h"
#include <wingdi.h> #include <wingdi.h>
@ -1315,7 +1316,10 @@ static DWORD WINAPI
thread_socket (void *arg) thread_socket (void *arg)
{ {
select_socket_info *si = (select_socket_info *) 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; bool event = false;
select_printf ("stuff_start %p", si->start); select_printf ("stuff_start %p", si->start);
@ -1326,18 +1330,19 @@ thread_socket (void *arg)
if (peek_socket (s, false)) if (peek_socket (s, false))
event = true; event = true;
if (!event) 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, switch (WaitForMultipleObjects (min (si->num_w4 - i,
MAXIMUM_WAIT_OBJECTS), MAXIMUM_WAIT_OBJECTS),
si->w4 + i, FALSE, timeout)) si->w4 + i, FALSE, timeout))
{ {
case WAIT_FAILED: case WAIT_FAILED:
goto out; goto out;
case WAIT_TIMEOUT:
continue;
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
if (!i) /* Socket event set. */ if (!i) /* Socket event set. */
goto out; goto out;
break; /*FALLTHRU*/
case WAIT_TIMEOUT:
default: default:
break; break;
} }
@ -1347,6 +1352,36 @@ out:
return 0; 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 static int
start_thread_socket (select_record *me, select_stuff *stuff) 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 = new select_socket_info;
si->ser_num = (LONG *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (LONG));
si->w4 = (HANDLE *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (HANDLE)); if (!init_tls_select_info ())
if (!si->ser_num || !si->w4)
return 0; return 0;
si->max_w4 = MAXIMUM_WAIT_OBJECTS;
select_record *s = &stuff->start; si->ser_num = _my_tls.locals.select.ser_num;
if (_my_tls.locals.select_sockevt != INVALID_HANDLE_VALUE) si->w4 = _my_tls.locals.select.w4;
si->w4[0] = _my_tls.locals.select_sockevt;
else if (!(si->w4[0] = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL))) si->w4[0] = _my_tls.locals.select.sockevt;
return 1;
else
_my_tls.locals.select_sockevt = si->w4[0];
si->num_w4 = 1; si->num_w4 = 1;
select_record *s = &stuff->start;
while ((s = s->next)) while ((s = s->next))
if (s->startup == start_thread_socket) 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) for (int i = 1; i < si->num_w4; ++i)
if (si->ser_num[i] == ser_num) if (si->ser_num[i] == ser_num)
goto continue_outer_loop; 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, LONG *nser = (LONG *) realloc (si->ser_num,
(si->max_w4 + MAXIMUM_WAIT_OBJECTS) (_my_tls.locals.select.max_w4
+ MAXIMUM_WAIT_OBJECTS)
* sizeof (LONG)); * sizeof (LONG));
if (!nser) if (!nser)
return 0; return 0;
si->ser_num = nser; _my_tls.locals.select.ser_num = si->ser_num = nser;
HANDLE *nw4 = (HANDLE *) realloc (si->w4, HANDLE *nw4 = (HANDLE *) realloc (si->w4,
(si->max_w4 + MAXIMUM_WAIT_OBJECTS) (_my_tls.locals.select.max_w4
+ MAXIMUM_WAIT_OBJECTS)
* sizeof (HANDLE)); * sizeof (HANDLE));
if (!nw4) if (!nw4)
return 0; return 0;
si->w4 = nw4; _my_tls.locals.select.w4 = si->w4 = nw4;
si->max_w4 += MAXIMUM_WAIT_OBJECTS; _my_tls.locals.select.max_w4 += MAXIMUM_WAIT_OBJECTS;
} }
si->ser_num[si->num_w4] = ser_num; si->ser_num[si->num_w4] = ser_num;
si->w4[si->num_w4++] = ((fhandler_socket *) s->fh)->wsock_event (); 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 (); si->thread->detach ();
ResetEvent (si->w4[0]); ResetEvent (si->w4[0]);
stuff->device_specific_socket = NULL; stuff->device_specific_socket = NULL;
if (si->ser_num)
free (si->ser_num);
if (si->w4)
free (si->w4);
delete si; delete si;
} }
select_printf ("returning"); select_printf ("returning");

View File

@ -58,7 +58,6 @@ struct select_pipe_info: public select_info
struct select_socket_info: public select_info struct select_socket_info: public select_info
{ {
int max_w4;
int num_w4; int num_w4;
LONG *ser_num; LONG *ser_num;
HANDLE *w4; HANDLE *w4;