From 1d380f593ae54513419a7e7f31817fc23a5e69b9 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Wed, 11 Dec 2002 04:00:04 +0000 Subject: * 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. --- winsup/cygwin/cygthread.cc | 66 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) (limited to 'winsup/cygwin/cygthread.cc') diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index 27e7f9442..0c591d01f 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -9,14 +9,17 @@ details. */ #include "winsup.h" #include #include +#include #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); -- cgit v1.2.3