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:
Christopher Faylor 2012-06-17 20:50:24 +00:00
parent d66ef282c2
commit 4ae6378382
18 changed files with 269 additions and 176 deletions

View File

@ -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

View File

@ -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

View File

@ -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 \

108
winsup/cygwin/cygwait.cc Normal file
View File

@ -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;
}

47
winsup/cygwin/cygwait.h Normal file
View File

@ -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);
}

View File

@ -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;

View File

@ -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:

View File

@ -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*/

View File

@ -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:

View File

@ -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 ();

View File

@ -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*/

View File

@ -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*/

View File

@ -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*/

View File

@ -22,6 +22,7 @@ details. */
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include "cygwait.h"
#define _SA_NORESTART 0x8000

View File

@ -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)));

View File

@ -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--;

View File

@ -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 ()

View File

@ -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);