* 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.
This commit is contained in:
Christopher Faylor
2002-12-11 04:00:04 +00:00
parent ea01c7f5d2
commit 1d380f593a
7 changed files with 146 additions and 33 deletions

View File

@@ -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 (is_freerange)
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 (!avail)
/* already handled */;
else if (is_freerange)
{
CloseHandle (h);
free (this);