summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-03-22 01:22:28 +0000
committerMark Mitchell <mark@codesourcery.com>2006-03-22 01:22:28 +0000
commitc749c8e7df6f7a3e5f3575ffc62ea2619ce5bb2a (patch)
treebf478960faf9e485252bfebd570e92d30caf52f0
parent43122d14a4b677927a540bd8d904961637caa9a2 (diff)
downloadgdb-c749c8e7df6f7a3e5f3575ffc62ea2619ce5bb2a.tar.gz
* gdb/ser-mingw.c (net_windows_state): Add mutex.
(net_windows_select_thread): Grab lock around access to read_event. (net_windows_wait_handle): Do not reset the read_event. (net_windows_open): Create a mutex. (net_windows_read_prim): New function. (_initialize_ser_windows): Use it.
-rw-r--r--ChangeLog.csl10
-rw-r--r--gdb/ser-mingw.c32
2 files changed, 39 insertions, 3 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 95a2ea8a1ee..77f90d9f713 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,3 +1,13 @@
+2006-03-21 Mark Mitchell <mark@codesourcery.com>
+
+ * gdb/ser-mingw.c (net_windows_state): Add mutex.
+ (net_windows_select_thread): Grab lock around access to
+ read_event.
+ (net_windows_wait_handle): Do not reset the read_event.
+ (net_windows_open): Create a mutex.
+ (net_windows_read_prim): New function.
+ (_initialize_ser_windows): Use it.
+
2006-03-20 Mark Mitchell <mark@codesourcery.com>
* libiberty/pex-common.c (pex_run): Close the write end of the
diff --git a/gdb/ser-mingw.c b/gdb/ser-mingw.c
index b5cd16eb26c..d170cec53d9 100644
--- a/gdb/ser-mingw.c
+++ b/gdb/ser-mingw.c
@@ -784,6 +784,8 @@ pipe_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
struct net_windows_state
{
+ /* Every access to read_event is guarded by this mutex. */
+ HANDLE mutex;
HANDLE read_event;
HANDLE except_event;
@@ -841,10 +843,11 @@ net_windows_select_thread (void *arg)
/* Enumerate the internal network events, and reset the object that
signalled us to catch the next event. */
+ WaitForSingleObject (state->mutex, INFINITE);
WSAEnumNetworkEvents (fd, state->sock_event, &events);
-
if (events.lNetworkEvents & FD_READ)
SetEvent (state->read_event);
+ ReleaseMutex (state->mutex);
if (events.lNetworkEvents & FD_CLOSE)
SetEvent (state->except_event);
@@ -856,7 +859,6 @@ net_windows_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
{
struct net_windows_state *state = scb->state;
- ResetEvent (state->read_event);
ResetEvent (state->except_event);
SetEvent (state->start_select);
@@ -892,6 +894,9 @@ net_windows_open (struct serial *scb, const char *name)
state->read_event = CreateEvent (0, FALSE, FALSE, 0);
state->except_event = CreateEvent (0, FALSE, FALSE, 0);
+ /* Guard access to the read_event. */
+ state->mutex = CreateMutex (NULL, FALSE, NULL);
+
/* And finally start the select thread. */
CreateThread (NULL, 0, net_windows_select_thread, scb, 0, &threadId);
@@ -916,6 +921,27 @@ net_windows_close (struct serial *scb)
net_close (scb);
}
+static int
+net_windows_read_prim (struct serial *scb, size_t count)
+{
+ struct net_windows_state *state = scb->state;
+ int ret;
+
+ /* We're about to call recv. If any bytes appear after this point,
+ we need to be told about them. So, we must reset the read event.
+ However, if we reset the event, then read, we could read all the
+ bytes -- and leave the event signaled if the thread notices new
+ bytes arriving between the reset and the read. Similarly, if we
+ read, then reset, we could miss new bytes arriving between the
+ read and the reset. So, we must make the read and reset atomic. */
+ WaitForSingleObject (state->mutex, INFINITE);
+ ResetEvent (state->read_event);
+ ret = net_read_prim (scb, count);
+ ReleaseMutex (state->mutex);
+
+ return ret;
+}
+
void
_initialize_ser_windows (void)
{
@@ -1028,7 +1054,7 @@ _initialize_ser_windows (void)
ops->setstopbits = ser_base_setstopbits;
ops->drain_output = ser_base_drain_output;
ops->async = ser_base_async;
- ops->read_prim = net_read_prim;
+ ops->read_prim = net_windows_read_prim;
ops->write_prim = net_write_prim;
ops->wait_handle = net_windows_wait_handle;
serial_add_interface (ops);