Add '#include "cygwait.h"' throughout, where appropriate.
* DevNotes: Add entry cgf-000012. * Makefile.in (DLL_OFILES): Add cygwait.o. * sigproc.h: Remove cygwait definitions. * cygwait.h: New file. Define/declare Cygwin waitfor functions. * cygwait.cc: Ditto. * exceptions.cc: Include cygwait.h. (handle_sigsuspend): Accommodate change in cancelable_wait arguments. (sigpacket::process): Display thread tls in debugging output. * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Use symbolic names for signal and cancel return. * fhandler_console.cc (fhandler_console::read): Ditto. (fhandler_dev_dsp::Audio_out::waitforspace): Ditto. fhandler_dev_dsp::Audio_in::waitfordata): Ditto. * fhandler_fifo.cc (fhandler_fifo::wait): Ditto. * fhandler_serial.cc (fhandler_serial::raw_read): Ditto. * fhandler_tty.cc (fhandler_pty_slave::read): Ditto. * select.cc (cygwin_select): Ditto. * wait.cc (wait4): Ditto. * thread.cc (cancelable_wait): Move definition to cygwait.h. (pthread_cond::wait): Accommodate change in cancelable_wait arguments. (pthread_mutex::lock): Ditto. (pthread_spinlock::lock): Ditto. (pthread::join): Ditto. (pthread::thread_init_wrapper): Display tls in debugging output. (semaphore::_timedwait): Ditto. * thread.h (cw_sig_wait): Move to cygwait.h. (cw_cancel_action): Delete. (cancelable_wait): Move declaration to cygwait.h.
This commit is contained in:
parent
d66ef282c2
commit
4ae6378382
|
@ -1,3 +1,35 @@
|
|||
2012-06-17 Christopher Faylor <me.cygwin2012@cgf.cx>
|
||||
|
||||
Add '#include "cygwait.h"' throughout, where appropriate.
|
||||
* DevNotes: Add entry cgf-000012.
|
||||
* Makefile.in (DLL_OFILES): Add cygwait.o.
|
||||
* sigproc.h: Remove cygwait definitions.
|
||||
* cygwait.h: New file. Define/declare Cygwin waitfor functions.
|
||||
* cygwait.cc: Ditto.
|
||||
* exceptions.cc: Include cygwait.h.
|
||||
(handle_sigsuspend): Accommodate change in cancelable_wait arguments.
|
||||
(sigpacket::process): Display thread tls in debugging output.
|
||||
* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Use symbolic
|
||||
names for signal and cancel return.
|
||||
* fhandler_console.cc (fhandler_console::read): Ditto.
|
||||
(fhandler_dev_dsp::Audio_out::waitforspace): Ditto.
|
||||
fhandler_dev_dsp::Audio_in::waitfordata): Ditto.
|
||||
* fhandler_fifo.cc (fhandler_fifo::wait): Ditto.
|
||||
* fhandler_serial.cc (fhandler_serial::raw_read): Ditto.
|
||||
* fhandler_tty.cc (fhandler_pty_slave::read): Ditto.
|
||||
* select.cc (cygwin_select): Ditto.
|
||||
* wait.cc (wait4): Ditto.
|
||||
* thread.cc (cancelable_wait): Move definition to cygwait.h.
|
||||
(pthread_cond::wait): Accommodate change in cancelable_wait arguments.
|
||||
(pthread_mutex::lock): Ditto.
|
||||
(pthread_spinlock::lock): Ditto.
|
||||
(pthread::join): Ditto.
|
||||
(pthread::thread_init_wrapper): Display tls in debugging output.
|
||||
(semaphore::_timedwait): Ditto.
|
||||
* thread.h (cw_sig_wait): Move to cygwait.h.
|
||||
(cw_cancel_action): Delete.
|
||||
(cancelable_wait): Move declaration to cygwait.h.
|
||||
|
||||
2012-06-11 Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
|
||||
|
||||
* regex/regcomp.c (p_ere): Allow vertical-line following
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
2012-06-12 cgf-000012
|
||||
|
||||
These changes are the preliminary for redoing the way threads wait for
|
||||
signals. The problems are shown by the test case mentioned here:
|
||||
|
||||
http://cygwin.com/ml/cygwin/2012-05/msg00434.html
|
||||
|
||||
I've known that the signal handling in threads wasn't quite right for
|
||||
some time. I lost all of my thread signal tests in the great "rm -r"
|
||||
debacle of a few years ago and have been less than enthusiastic about
|
||||
redoing everything (I had PCTS tests and everyting). But it really is
|
||||
time to redo this signal handling to make it more like it is supposed to
|
||||
be.
|
||||
|
||||
This change should not introduce any new behavior. Things should
|
||||
continue to behave as before. The major differences are a change in the
|
||||
arguments to cancelable_wait and cygwait now uses cancelable_wait and,
|
||||
so, the returns from cygwait now mirror cancelable_wait.
|
||||
|
||||
The next change will consolidate cygwait and cancelable_wait into one
|
||||
cygwait function.
|
||||
|
||||
2012-06-02 cgf-000011
|
||||
|
||||
The refcnt handling was tricky to get right but I had convinced myself
|
||||
|
|
|
@ -133,16 +133,16 @@ MALLOC_OFILES:=@MALLOC_OFILES@
|
|||
DLL_IMPORTS:=$(w32api_lib)/libkernel32.a $(w32api_lib)/libntdll.a
|
||||
|
||||
MT_SAFE_OBJECTS:=
|
||||
# Please maintain this list in sorted order, with maximum files per 86 col line
|
||||
#
|
||||
DLL_OFILES:=advapi32.o assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o \
|
||||
cygthread.o cygtls.o cygxdr.o dcrt0.o debug.o devices.o dir.o dlfcn.o \
|
||||
dll_init.o dtable.o environ.o errno.o exceptions.o exec.o external.o \
|
||||
fcntl.o fenv.o fhandler.o fhandler_clipboard.o fhandler_console.o \
|
||||
fhandler_dev.o fhandler_disk_file.o fhandler_dsp.o fhandler_fifo.o \
|
||||
fhandler_floppy.o fhandler_mailslot.o fhandler_mem.o fhandler_netdrive.o \
|
||||
fhandler_nodevice.o fhandler_proc.o fhandler_process.o fhandler_procnet.o \
|
||||
fhandler_procsys.o fhandler_procsysvipc.o fhandler_random.o fhandler_raw.o \
|
||||
cygthread.o cygtls.o cygwait.o cygxdr.o dcrt0.o debug.o devices.o \
|
||||
dir.o dlfcn.o dll_init.o dtable.o environ.o errno.o exceptions.o \
|
||||
exec.o external.o fcntl.o fenv.o fhandler.o fhandler_clipboard.o \
|
||||
fhandler_console.o fhandler_dev.o fhandler_disk_file.o fhandler_dsp.o \
|
||||
fhandler_fifo.o fhandler_floppy.o fhandler_mailslot.o fhandler_mem.o \
|
||||
fhandler_netdrive.o fhandler_nodevice.o fhandler_proc.o \
|
||||
fhandler_process.o fhandler_procnet.o fhandler_procsys.o \
|
||||
fhandler_procsysvipc.o fhandler_random.o fhandler_raw.o \
|
||||
fhandler_registry.o fhandler_serial.o fhandler_socket.o fhandler_tape.o \
|
||||
fhandler_termios.o fhandler_tty.o fhandler_virtual.o fhandler_windows.o \
|
||||
fhandler_zero.o flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o \
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/* cygwait.h
|
||||
|
||||
Copyright 2011, 2012 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include "sigproc.h"
|
||||
#include "cygwait.h"
|
||||
#include "ntdll.h"
|
||||
|
||||
#define is_cw_cancel (mask & cw_cancel)
|
||||
#define is_cw_cancel_self (mask & cw_cancel_self)
|
||||
#define is_cw_sig (mask & cw_sig)
|
||||
#define is_cw_sig_eintr (mask & cw_sig_eintr)
|
||||
#define is_cw_sig_return (mask & cw_sig_return)
|
||||
|
||||
#define is_cw_sig_handle (mask & (is_cw_sig | is_cw_sig_eintr))
|
||||
|
||||
DWORD
|
||||
cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
|
||||
{
|
||||
DWORD res;
|
||||
DWORD num = 0;
|
||||
HANDLE wait_objects[4];
|
||||
pthread_t thread = pthread::self ();
|
||||
|
||||
/* Do not change the wait order.
|
||||
The object must have higher priority than the cancel event,
|
||||
because WaitForMultipleObjects will return the smallest index
|
||||
if both objects are signaled. */
|
||||
if (object)
|
||||
wait_objects[num++] = object;
|
||||
|
||||
DWORD sig_n;
|
||||
if (!is_cw_sig_handle)
|
||||
sig_n = WAIT_TIMEOUT + 1;
|
||||
else
|
||||
{
|
||||
sig_n = WAIT_OBJECT_0 + num++;
|
||||
wait_objects[sig_n] = signal_arrived;
|
||||
}
|
||||
|
||||
DWORD cancel_n;
|
||||
if (!is_cw_cancel || !pthread::is_good_object (&thread) ||
|
||||
thread->cancelstate == PTHREAD_CANCEL_DISABLE)
|
||||
cancel_n = WAIT_TIMEOUT + 1;
|
||||
else
|
||||
{
|
||||
cancel_n = WAIT_OBJECT_0 + num++;
|
||||
wait_objects[cancel_n] = thread->cancel_event;
|
||||
}
|
||||
|
||||
DWORD timeout_n;
|
||||
if (!timeout)
|
||||
timeout_n = WAIT_TIMEOUT + 1;
|
||||
else
|
||||
{
|
||||
timeout_n = WAIT_OBJECT_0 + num++;
|
||||
if (!_my_tls.locals.cw_timer)
|
||||
NtCreateTimer (&_my_tls.locals.cw_timer, TIMER_ALL_ACCESS, NULL,
|
||||
NotificationTimer);
|
||||
NtSetTimer (_my_tls.locals.cw_timer, timeout, NULL, NULL, FALSE, 0, NULL);
|
||||
wait_objects[timeout_n] = _my_tls.locals.cw_timer;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = WaitForMultipleObjects (num, wait_objects, FALSE, INFINITE);
|
||||
if (res == cancel_n)
|
||||
{
|
||||
if (is_cw_cancel_self)
|
||||
pthread::static_cancel_self ();
|
||||
res = WAIT_CANCELED;
|
||||
}
|
||||
else if (res == timeout_n)
|
||||
res = WAIT_TIMEOUT;
|
||||
else if (res != sig_n)
|
||||
/* all set */;
|
||||
else if (is_cw_sig_eintr)
|
||||
res = WAIT_SIGNALED;
|
||||
else
|
||||
{
|
||||
_my_tls.call_signal_handler ();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
TIMER_BASIC_INFORMATION tbi;
|
||||
|
||||
NtQueryTimer (_my_tls.locals.cw_timer, TimerBasicInformation, &tbi,
|
||||
sizeof tbi, NULL);
|
||||
/* if timer expired, TimeRemaining is negative and represents the
|
||||
system uptime when signalled */
|
||||
if (timeout->QuadPart < 0LL)
|
||||
timeout->QuadPart = tbi.SignalState ? 0LL : tbi.TimeRemaining.QuadPart;
|
||||
NtCancelTimer (_my_tls.locals.cw_timer, NULL);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* cygwait.h
|
||||
|
||||
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
||||
Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#pragma once
|
||||
|
||||
enum cw_wait_mask
|
||||
{
|
||||
cw_cancel = 0x0001,
|
||||
cw_cancel_self = 0x0002,
|
||||
cw_sig = 0x0004,
|
||||
cw_sig_eintr = 0x0008
|
||||
};
|
||||
|
||||
const unsigned cw_std_mask = cw_cancel | cw_cancel_self | cw_sig;
|
||||
|
||||
DWORD cancelable_wait (HANDLE, PLARGE_INTEGER timeout = NULL,
|
||||
unsigned = cw_std_mask)
|
||||
__attribute__ ((regparm (3)));
|
||||
|
||||
static inline DWORD __attribute__ ((always_inline))
|
||||
cygwait (HANDLE h, DWORD howlong = INFINITE)
|
||||
{
|
||||
PLARGE_INTEGER pli_howlong;
|
||||
LARGE_INTEGER li_howlong;
|
||||
if (howlong == INFINITE)
|
||||
pli_howlong = NULL;
|
||||
else
|
||||
{
|
||||
li_howlong.QuadPart = 10000ULL * howlong;
|
||||
pli_howlong = &li_howlong;
|
||||
}
|
||||
return cancelable_wait (h, pli_howlong, cw_cancel | cw_sig_eintr);
|
||||
}
|
||||
|
||||
static inline DWORD __attribute__ ((always_inline))
|
||||
cygwait (DWORD howlong)
|
||||
{
|
||||
return cygwait ((HANDLE) NULL, howlong);
|
||||
}
|
|
@ -31,6 +31,7 @@ details. */
|
|||
#include "child_info.h"
|
||||
#include "ntdll.h"
|
||||
#include "exception.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
#define CALL_HANDLER_RETRY_OUTER 10
|
||||
#define CALL_HANDLER_RETRY_INNER 10
|
||||
|
@ -714,7 +715,7 @@ handle_sigsuspend (sigset_t tempmask)
|
|||
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
|
||||
|
||||
pthread_testcancel ();
|
||||
cancelable_wait (signal_arrived);
|
||||
cancelable_wait (signal_arrived, NULL, cw_cancel | cw_cancel_self);
|
||||
|
||||
set_sig_errno (EINTR); // Per POSIX
|
||||
|
||||
|
@ -1194,6 +1195,7 @@ sigpacket::process ()
|
|||
handler = NULL;
|
||||
|
||||
_cygtls *use_tls = tls ?: _main_tls;
|
||||
sigproc_printf ("tls %p, use_tls %p", tls, use_tls);
|
||||
|
||||
if (si.si_signo == SIGKILL)
|
||||
goto exit_sig;
|
||||
|
|
|
@ -31,6 +31,7 @@ details. */
|
|||
#include "sigproc.h"
|
||||
#include "shared_info.h"
|
||||
#include <asm/socket.h>
|
||||
#include "cygwait.h"
|
||||
|
||||
#define MAX_OVERLAPPED_WRITE_LEN (64 * 1024 * 1024)
|
||||
#define MIN_OVERLAPPED_WRITE_LEN (1 * 1024 * 1024)
|
||||
|
@ -1939,7 +1940,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
|||
case WAIT_OBJECT_0:
|
||||
err = ERROR_INVALID_HANDLE;
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_SIGNALED:
|
||||
err = ERROR_INVALID_AT_INTERRUPT_TIME;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -36,6 +36,7 @@ details. */
|
|||
#include <asm/socket.h>
|
||||
#include "sync.h"
|
||||
#include "child_info.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
/* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer
|
||||
is allocated using tmp_pathbuf!!! */
|
||||
|
@ -355,9 +356,9 @@ fhandler_console::read (void *pv, size_t& buflen)
|
|||
{
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_SIGNALED:
|
||||
goto sig_exit;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
case WAIT_CANCELED:
|
||||
process_state.pop ();
|
||||
pthread::static_cancel_self ();
|
||||
/*NOTREACHED*/
|
||||
|
|
|
@ -21,6 +21,7 @@ details. */
|
|||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "sigproc.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Simple encapsulation of the win32 audio device.
|
||||
|
@ -544,14 +545,14 @@ fhandler_dev_dsp::Audio_out::waitforspace ()
|
|||
debug_printf ("100ms");
|
||||
switch (cygwait (100))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_SIGNALED:
|
||||
if (!_my_tls.call_signal_handler ())
|
||||
{
|
||||
set_errno (EINTR);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_CANCELED:
|
||||
pthread::static_cancel_self ();
|
||||
/*NOTREACHED*/
|
||||
default:
|
||||
|
@ -922,14 +923,14 @@ fhandler_dev_dsp::Audio_in::waitfordata ()
|
|||
debug_printf ("100ms");
|
||||
switch (cygwait (100))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_SIGNALED:
|
||||
if (!_my_tls.call_signal_handler ())
|
||||
{
|
||||
set_errno (EINTR);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_CANCELED:
|
||||
pthread::static_cancel_self ();
|
||||
/*NOTREACHED*/
|
||||
default:
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "cygtls.h"
|
||||
#include "shared_info.h"
|
||||
#include "ntdll.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
fhandler_fifo::fhandler_fifo ():
|
||||
fhandler_base_overlapped (),
|
||||
|
@ -242,6 +243,14 @@ fhandler_fifo::wait (HANDLE h)
|
|||
case WAIT_OBJECT_0:
|
||||
debug_only_printf ("successfully waited for %s", what);
|
||||
return true;
|
||||
case WAIT_SIGNALED:
|
||||
debug_only_printf ("interrupted by signal while waiting for %s", what);
|
||||
set_errno (EINTR);
|
||||
return false;
|
||||
case WAIT_CANCELED:
|
||||
debug_only_printf ("cancellable interruption while waiting for %s", what);
|
||||
pthread::static_cancel_self (); /* never returns */
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
if (h == write_ready)
|
||||
{
|
||||
|
@ -254,14 +263,6 @@ fhandler_fifo::wait (HANDLE h)
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
debug_only_printf ("interrupted by signal while waiting for %s", what);
|
||||
set_errno (EINTR);
|
||||
return false;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
debug_only_printf ("cancellable interruption while waiting for %s", what);
|
||||
pthread::static_cancel_self (); /* never returns */
|
||||
break;
|
||||
default:
|
||||
debug_only_printf ("unknown error while waiting for %s", what);
|
||||
__seterrno ();
|
||||
|
|
|
@ -20,6 +20,7 @@ details. */
|
|||
#include "pinfo.h"
|
||||
#include <asm/socket.h>
|
||||
#include <ddk/ntddser.h>
|
||||
#include "cygwait.h"
|
||||
|
||||
/**********************************************************************/
|
||||
/* fhandler_serial */
|
||||
|
@ -94,13 +95,13 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen)
|
|||
goto err;
|
||||
debug_printf ("n %d, ev %x", n, ev);
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_SIGNALED:
|
||||
tot = -1;
|
||||
PurgeComm (get_handle (), PURGE_RXABORT);
|
||||
overlapped_armed = 0;
|
||||
set_sig_errno (EINTR);
|
||||
goto out;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
case WAIT_CANCELED:
|
||||
PurgeComm (get_handle (), PURGE_RXABORT);
|
||||
overlapped_armed = 0;
|
||||
pthread::static_cancel_self ();
|
||||
|
@ -201,12 +202,12 @@ fhandler_serial::raw_write (const void *ptr, size_t len)
|
|||
{
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_SIGNALED:
|
||||
PurgeComm (get_handle (), PURGE_TXABORT);
|
||||
set_sig_errno (EINTR);
|
||||
ForceCloseHandle (write_status.hEvent);
|
||||
return -1;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
case WAIT_CANCELED:
|
||||
PurgeComm (get_handle (), PURGE_TXABORT);
|
||||
pthread::static_cancel_self ();
|
||||
/*NOTREACHED*/
|
||||
|
|
|
@ -26,6 +26,7 @@ details. */
|
|||
#include "cygthread.h"
|
||||
#include "child_info.h"
|
||||
#include <asm/socket.h>
|
||||
#include "cygwait.h"
|
||||
|
||||
#define close_maybe(h) \
|
||||
do { \
|
||||
|
@ -737,14 +738,14 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
|
|||
goto out;
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_SIGNALED:
|
||||
if (totalread > 0)
|
||||
goto out;
|
||||
termios_printf ("wait catched signal");
|
||||
set_sig_errno (EINTR);
|
||||
totalread = -1;
|
||||
goto out;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
case WAIT_CANCELED:
|
||||
process_state.pop ();
|
||||
pthread::static_cancel_self ();
|
||||
/*NOTREACHED*/
|
||||
|
@ -772,14 +773,14 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
|
|||
case WAIT_OBJECT_0:
|
||||
case WAIT_ABANDONED_0:
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_SIGNALED:
|
||||
if (totalread > 0)
|
||||
goto out;
|
||||
termios_printf ("wait for mutex catched signal");
|
||||
termios_printf ("wait for mutex caught signal");
|
||||
set_sig_errno (EINTR);
|
||||
totalread = -1;
|
||||
goto out;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
case WAIT_CANCELED:
|
||||
process_state.pop ();
|
||||
pthread::static_cancel_self ();
|
||||
/*NOTREACHED*/
|
||||
|
|
|
@ -34,6 +34,7 @@ details. */
|
|||
#include "pinfo.h"
|
||||
#include "sigproc.h"
|
||||
#include "cygtls.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
/*
|
||||
* All these defines below should be in sys/types.h
|
||||
|
@ -143,7 +144,7 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
if (sel.start.next == NULL)
|
||||
switch (cygwait (ms))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_SIGNALED:
|
||||
select_printf ("signal received");
|
||||
_my_tls.call_signal_handler ();
|
||||
if (!sel.return_on_signal)
|
||||
|
@ -154,7 +155,7 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
res = select_stuff::select_error;
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
case WAIT_CANCELED:
|
||||
sel.destroy ();
|
||||
pthread::static_cancel_self ();
|
||||
/*NOTREACHED*/
|
||||
|
|
|
@ -22,6 +22,7 @@ details. */
|
|||
#include "fhandler.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
#define _SA_NORESTART 0x8000
|
||||
|
||||
|
|
|
@ -80,33 +80,6 @@ void __stdcall proc_terminate ();
|
|||
void __stdcall sigproc_init ();
|
||||
#ifdef __INSIDE_CYGWIN__
|
||||
void __stdcall sigproc_terminate (enum exit_states);
|
||||
|
||||
static inline DWORD __attribute__ ((always_inline))
|
||||
cygwait (HANDLE h, DWORD howlong = INFINITE)
|
||||
{
|
||||
HANDLE w4[3];
|
||||
DWORD n = 0;
|
||||
DWORD wait_signal;
|
||||
if ((w4[n] = h) != NULL)
|
||||
wait_signal = WAIT_OBJECT_0 + ++n;
|
||||
else
|
||||
wait_signal = WAIT_OBJECT_0 + 15; /* Arbitrary. Don't call signal
|
||||
handler if only waiting for signal */
|
||||
w4[n++] = signal_arrived;
|
||||
if ((w4[n] = pthread::get_cancel_event ()) != NULL)
|
||||
n++;
|
||||
DWORD res;
|
||||
while ((res = WaitForMultipleObjects (n, w4, FALSE, howlong)) == wait_signal
|
||||
&& (_my_tls.call_signal_handler () || &_my_tls != _main_tls))
|
||||
continue;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline DWORD __attribute__ ((always_inline))
|
||||
cygwait (DWORD wait)
|
||||
{
|
||||
return cygwait ((HANDLE) NULL, wait);
|
||||
}
|
||||
#endif
|
||||
bool __stdcall pid_exists (pid_t) __attribute__ ((regparm(1)));
|
||||
int __stdcall sig_send (_pinfo *, siginfo_t&, class _cygtls *tls = NULL) __attribute__ ((regparm (3)));
|
||||
|
|
|
@ -32,6 +32,7 @@ details. */
|
|||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "ntdll.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
extern "C" void __fp_lock_all ();
|
||||
extern "C" void __fp_unlock_all ();
|
||||
|
@ -937,92 +938,6 @@ pthread::static_cancel_self ()
|
|||
pthread::self ()->cancel_self ();
|
||||
}
|
||||
|
||||
DWORD
|
||||
cancelable_wait (HANDLE object, PLARGE_INTEGER timeout,
|
||||
const cw_cancel_action cancel_action,
|
||||
const enum cw_sig_wait sig_wait)
|
||||
{
|
||||
DWORD res;
|
||||
DWORD num = 0;
|
||||
HANDLE wait_objects[4];
|
||||
pthread_t thread = pthread::self ();
|
||||
|
||||
/* Do not change the wait order.
|
||||
The object must have higher priority than the cancel event,
|
||||
because WaitForMultipleObjects will return the smallest index
|
||||
if both objects are signaled. */
|
||||
wait_objects[num++] = object;
|
||||
DWORD cancel_n;
|
||||
if (cancel_action == cw_no_cancel || !pthread::is_good_object (&thread) ||
|
||||
thread->cancelstate == PTHREAD_CANCEL_DISABLE)
|
||||
cancel_n = WAIT_TIMEOUT + 1;
|
||||
else
|
||||
{
|
||||
cancel_n = WAIT_OBJECT_0 + num++;
|
||||
wait_objects[cancel_n] = thread->cancel_event;
|
||||
}
|
||||
|
||||
DWORD sig_n;
|
||||
if (sig_wait == cw_sig_nosig)
|
||||
sig_n = WAIT_TIMEOUT + 1;
|
||||
else
|
||||
{
|
||||
sig_n = WAIT_OBJECT_0 + num++;
|
||||
wait_objects[sig_n] = signal_arrived;
|
||||
}
|
||||
|
||||
DWORD timeout_n;
|
||||
if (!timeout)
|
||||
timeout_n = WAIT_TIMEOUT + 1;
|
||||
else
|
||||
{
|
||||
timeout_n = WAIT_OBJECT_0 + num++;
|
||||
if (!_my_tls.locals.cw_timer)
|
||||
NtCreateTimer (&_my_tls.locals.cw_timer, TIMER_ALL_ACCESS, NULL,
|
||||
NotificationTimer);
|
||||
NtSetTimer (_my_tls.locals.cw_timer, timeout, NULL, NULL, FALSE, 0, NULL);
|
||||
wait_objects[timeout_n] = _my_tls.locals.cw_timer;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = WaitForMultipleObjects (num, wait_objects, FALSE, INFINITE);
|
||||
if (res == cancel_n)
|
||||
{
|
||||
if (cancel_action == cw_cancel_self)
|
||||
pthread::static_cancel_self ();
|
||||
res = WAIT_CANCELED;
|
||||
}
|
||||
else if (res == timeout_n)
|
||||
res = WAIT_TIMEOUT;
|
||||
else if (res != sig_n)
|
||||
/* all set */;
|
||||
else if (sig_wait == cw_sig_eintr)
|
||||
res = WAIT_SIGNALED;
|
||||
else
|
||||
{
|
||||
_my_tls.call_signal_handler ();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
TIMER_BASIC_INFORMATION tbi;
|
||||
|
||||
NtQueryTimer (_my_tls.locals.cw_timer, TimerBasicInformation, &tbi,
|
||||
sizeof tbi, NULL);
|
||||
/* if timer expired, TimeRemaining is negative and represents the
|
||||
system uptime when signalled */
|
||||
if (timeout->QuadPart < 0LL)
|
||||
timeout->QuadPart = tbi.SignalState ? 0LL : tbi.TimeRemaining.QuadPart;
|
||||
NtCancelTimer (_my_tls.locals.cw_timer, NULL);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
pthread::setcancelstate (int state, int *oldstate)
|
||||
{
|
||||
|
@ -1313,7 +1228,7 @@ pthread_cond::wait (pthread_mutex_t mutex, PLARGE_INTEGER timeout)
|
|||
++mutex->condwaits;
|
||||
mutex->unlock ();
|
||||
|
||||
rv = cancelable_wait (sem_wait, timeout, cw_no_cancel_self, cw_sig_eintr);
|
||||
rv = cancelable_wait (sem_wait, timeout, cw_cancel | cw_sig_eintr);
|
||||
|
||||
mtx_out.lock ();
|
||||
|
||||
|
@ -1828,7 +1743,8 @@ pthread_mutex::lock ()
|
|||
else if (type == PTHREAD_MUTEX_NORMAL /* potentially causes deadlock */
|
||||
|| !pthread::equal (owner, self))
|
||||
{
|
||||
cancelable_wait (win32_obj_id, NULL, cw_no_cancel, cw_sig_resume);
|
||||
/* FIXME: no cancel? */
|
||||
cancelable_wait (win32_obj_id, NULL, cw_sig);
|
||||
set_owner (self);
|
||||
}
|
||||
else
|
||||
|
@ -1968,7 +1884,8 @@ pthread_spinlock::lock ()
|
|||
/* Minimal timeout to minimize CPU usage while still spinning. */
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = -10000LL;
|
||||
cancelable_wait (win32_obj_id, &timeout, cw_no_cancel, cw_sig_resume);
|
||||
/* FIXME: no cancel? */
|
||||
cancelable_wait (win32_obj_id, &timeout, cw_sig);
|
||||
}
|
||||
}
|
||||
while (result == -1);
|
||||
|
@ -2013,6 +1930,7 @@ pthread::thread_init_wrapper (void *arg)
|
|||
_my_tls.sigmask = thread->parent_sigmask;
|
||||
thread->mutex.unlock ();
|
||||
|
||||
debug_printf ("tid %p", &_my_tls);
|
||||
thread_printf ("started thread %p %p %p %p %p %p", arg, &_my_tls.local_clib,
|
||||
_impure_ptr, thread, thread->function, thread->arg);
|
||||
|
||||
|
@ -2446,7 +2364,7 @@ pthread::join (pthread_t *thread, void **return_val)
|
|||
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
|
||||
(*thread)->mutex.unlock ();
|
||||
|
||||
switch (cancelable_wait ((*thread)->win32_obj_id, NULL, cw_no_cancel_self, cw_sig_resume))
|
||||
switch (cancelable_wait ((*thread)->win32_obj_id, NULL, cw_sig | cw_cancel))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
if (return_val)
|
||||
|
@ -3561,7 +3479,7 @@ semaphore::_timedwait (const struct timespec *abstime)
|
|||
timeout.QuadPart = abstime->tv_sec * NSPERSEC
|
||||
+ (abstime->tv_nsec + 99) / 100 + FACTOR;
|
||||
|
||||
switch (cancelable_wait (win32_obj_id, &timeout, cw_cancel_self, cw_sig_eintr))
|
||||
switch (cancelable_wait (win32_obj_id, &timeout, cw_cancel | cw_cancel_self | cw_sig_eintr))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
currentvalue--;
|
||||
|
@ -3583,7 +3501,7 @@ semaphore::_timedwait (const struct timespec *abstime)
|
|||
int
|
||||
semaphore::_wait ()
|
||||
{
|
||||
switch (cancelable_wait (win32_obj_id, NULL, cw_cancel_self, cw_sig_eintr))
|
||||
switch (cancelable_wait (win32_obj_id, NULL, cw_cancel | cw_cancel_self | cw_sig_eintr))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
currentvalue--;
|
||||
|
|
|
@ -29,25 +29,7 @@ details. */
|
|||
#include "security.h"
|
||||
#include <errno.h>
|
||||
#include "cygerrno.h"
|
||||
|
||||
enum cw_sig_wait
|
||||
{
|
||||
cw_sig_nosig,
|
||||
cw_sig_eintr,
|
||||
cw_sig_resume
|
||||
};
|
||||
|
||||
enum cw_cancel_action
|
||||
{
|
||||
cw_cancel_self,
|
||||
cw_no_cancel_self,
|
||||
cw_no_cancel
|
||||
};
|
||||
|
||||
DWORD cancelable_wait (HANDLE, PLARGE_INTEGER timeout = NULL,
|
||||
const cw_cancel_action = cw_cancel_self,
|
||||
const enum cw_sig_wait = cw_sig_nosig)
|
||||
__attribute__ ((regparm (3)));
|
||||
#include "cygwait.h"
|
||||
|
||||
class fast_mutex
|
||||
{
|
||||
|
@ -78,7 +60,7 @@ public:
|
|||
void lock ()
|
||||
{
|
||||
if (InterlockedIncrement ((long *) &lock_counter) != 1)
|
||||
cancelable_wait (win32_obj_id, NULL, cw_no_cancel, cw_sig_resume);
|
||||
cancelable_wait (win32_obj_id, NULL, cw_sig);
|
||||
}
|
||||
|
||||
void unlock ()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* wait.cc: Posix wait routines.
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
2005, 2009, 2011 Red Hat, Inc.
|
||||
2005, 2009, 2011, 2012 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
@ -14,6 +14,7 @@ details. */
|
|||
#include "sigproc.h"
|
||||
#include "thread.h"
|
||||
#include "cygtls.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
/* This is called _wait and not wait because the real wait is defined
|
||||
in libc/syscalls/syswait.c. It calls us. */
|
||||
|
@ -79,7 +80,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
|
|||
if ((waitfor = w->ev) == NULL)
|
||||
goto nochildren;
|
||||
|
||||
res = cancelable_wait (waitfor);
|
||||
res = cancelable_wait (waitfor, NULL, cw_cancel | cw_cancel_self);
|
||||
|
||||
sigproc_printf ("%d = cancelable_wait (...)", res);
|
||||
|
||||
|
|
Loading…
Reference in New Issue