diff options
author | Christopher Faylor <me@cgf.cx> | 2002-12-11 04:00:04 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2002-12-11 04:00:04 +0000 |
commit | 1d380f593ae54513419a7e7f31817fc23a5e69b9 (patch) | |
tree | 6997ee23c02f85f89c36ab4e7d971cd174c68869 /winsup/cygwin/cygthread.cc | |
parent | ea01c7f5d25779a88d6476da8b7f780379bc0c05 (diff) | |
download | newlib-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.cc | 66 |
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); |