aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/cygthread.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2002-12-11 04:00:04 +0000
committerChristopher Faylor <me@cgf.cx>2002-12-11 04:00:04 +0000
commit1d380f593ae54513419a7e7f31817fc23a5e69b9 (patch)
tree6997ee23c02f85f89c36ab4e7d971cd174c68869 /winsup/cygwin/cygthread.cc
parentea01c7f5d25779a88d6476da8b7f780379bc0c05 (diff)
downloadnewlib-1d380f593ae54513419a7e7f31817fc23a5e69b9.zip
newlib-1d380f593ae54513419a7e7f31817fc23a5e69b9.tar.gz
newlib-1d380f593ae54513419a7e7f31817fc23a5e69b9.tar.bz2
* cygthread.h (cygthread::stack_ptr): New element.
(cygthread::detach): Accept a "wait_for_signal" argument. (cygthread::terminate_thread): New function. * cygthread.cc (cygthread::stub): Set stack pointer argument. (cygthread::terminate_thread): New function. Forcibly terminate thread. (cygthread::detach): Optionally wait for signals and kill thread when signal arrives. * exceptions.cc (signal_exit): Set signal_arrived prior to exiting to wake up anything blocking on signals. * fhandler.h (fhandler_base::set_r_no_interrupt): Change to accept bool argument. (fhandler_pipe::ready_for_read): Declare. * pipe.cc (pipeargs): New structure. (read_pipe): New thread stub wrapper for normal pipe read. (fhandler_pipe::read): Modify to call reader in a cygthread, terminating on signal, as appropriate. * select.cc (fhandler_pipe::ready_for_read): Define new function.
Diffstat (limited to 'winsup/cygwin/cygthread.cc')
-rw-r--r--winsup/cygwin/cygthread.cc66
1 files changed, 60 insertions, 6 deletions
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc
index 27e7f94..0c591d0 100644
--- a/winsup/cygwin/cygthread.cc
+++ b/winsup/cygwin/cygthread.cc
@@ -9,14 +9,17 @@ details. */
#include "winsup.h"
#include <windows.h>
#include <stdlib.h>
+#include <errno.h>
#include "exceptions.h"
#include "security.h"
#include "cygthread.h"
#include "sync.h"
+#include "cygerrno.h"
+#include "sigproc.h"
#undef CloseHandle
-static cygthread NO_COPY threads[9];
+static cygthread NO_COPY threads[18];
#define NTHREADS (sizeof (threads) / sizeof (threads[0]))
DWORD NO_COPY cygthread::main_thread_id;
@@ -37,11 +40,12 @@ cygthread::stub (VOID *arg)
cygthread *info = (cygthread *) arg;
if (info->arg == cygself)
- info->ev = info->thread_sync = NULL;
+ info->ev = info->thread_sync = info->stack_ptr = NULL;
else
{
info->ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
info->thread_sync = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
+ info->stack_ptr = &arg;
}
while (1)
{
@@ -231,22 +235,72 @@ cygthread::exit_thread ()
ExitThread (0);
}
+/* Forcibly terminate a thread. */
+void
+cygthread::terminate_thread ()
+{
+ if (!is_freerange)
+ SetEvent (*this);
+ (void) TerminateThread (h, 0);
+ (void) WaitForSingleObject (h, INFINITE);
+
+ MEMORY_BASIC_INFORMATION m;
+ memset (&m, 0, sizeof (m));
+ (void) VirtualQuery (stack_ptr, &m, sizeof m);
+
+ if (m.RegionSize)
+ (void) VirtualFree (m.AllocationBase, m.RegionSize, MEM_DECOMMIT);
+
+ if (is_freerange)
+ is_freerange = false;
+ else
+ {
+ CloseHandle (ev);
+ CloseHandle (thread_sync);
+ }
+ CloseHandle (h);
+ thread_sync = ev = h = NULL;
+ __name = NULL;
+ id = 0;
+}
+
/* Detach the cygthread from the current thread. Note that the
theory is that cygthreads are only associated with one thread.
So, there should be no problems with multiple threads doing waits
on the one cygthread. */
void
-cygthread::detach ()
+cygthread::detach (bool wait_for_sig)
{
if (avail)
system_printf ("called detach on available thread %d?", avail);
else
{
DWORD avail = id;
- DWORD res = WaitForSingleObject (*this, INFINITE);
- thread_printf ("WFSO returns %d, id %p", res, id);
+ DWORD res;
+
+ if (!wait_for_sig)
+ res = WaitForSingleObject (*this, INFINITE);
+ else
+ {
+ HANDLE w4[2];
+ w4[0] = signal_arrived;
+ w4[1] = *this;
+ res = WaitForMultipleObjects (2, w4, FALSE, INFINITE);
+ if (res == WAIT_OBJECT_0)
+ {
+ terminate_thread ();
+ set_errno (EINTR); /* caller should be dealing with return
+ values. */
+ avail = 0;
+ }
+ }
+
+ thread_printf ("%s returns %d, id %p", wait_for_sig ? "WFMO" : "WFSO",
+ res, id);
- if (is_freerange)
+ if (!avail)
+ /* already handled */;
+ else if (is_freerange)
{
CloseHandle (h);
free (this);