Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog32
-rw-r--r--winsup/cygwin/DevNotes22
-rw-r--r--winsup/cygwin/Makefile.in16
-rw-r--r--winsup/cygwin/cygwait.cc108
-rw-r--r--winsup/cygwin/cygwait.h47
-rw-r--r--winsup/cygwin/exceptions.cc4
-rw-r--r--winsup/cygwin/fhandler.cc3
-rw-r--r--winsup/cygwin/fhandler_console.cc5
-rw-r--r--winsup/cygwin/fhandler_dsp.cc9
-rw-r--r--winsup/cygwin/fhandler_fifo.cc17
-rw-r--r--winsup/cygwin/fhandler_serial.cc9
-rw-r--r--winsup/cygwin/fhandler_tty.cc11
-rw-r--r--winsup/cygwin/select.cc5
-rw-r--r--winsup/cygwin/signal.cc1
-rw-r--r--winsup/cygwin/sigproc.h27
-rw-r--r--winsup/cygwin/thread.cc102
-rw-r--r--winsup/cygwin/thread.h22
-rw-r--r--winsup/cygwin/wait.cc5
18 files changed, 269 insertions, 176 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 6bfb7ef67..ef885e083 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/DevNotes b/winsup/cygwin/DevNotes
index a311256e2..7bec42017 100644
--- a/winsup/cygwin/DevNotes
+++ b/winsup/cygwin/DevNotes
@@ -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
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index e65b44031..2aedb1c7b 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -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 \
diff --git a/winsup/cygwin/cygwait.cc b/winsup/cygwin/cygwait.cc
new file mode 100644
index 000000000..6e0610da0
--- /dev/null
+++ b/winsup/cygwin/cygwait.cc
@@ -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;
+}
diff --git a/winsup/cygwin/cygwait.h b/winsup/cygwin/cygwait.h
new file mode 100644
index 000000000..c2b7f5801
--- /dev/null
+++ b/winsup/cygwin/cygwait.h
@@ -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);
+}
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index f78e8f7b6..3c22e35c3 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -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;
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index a22fe2496..55a73b66e 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -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:
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index e54f11f2a..0208a4863 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -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*/
diff --git a/winsup/cygwin/fhandler_dsp.cc b/winsup/cygwin/fhandler_dsp.cc
index 1cb3b465e..b16606615 100644
--- a/winsup/cygwin/fhandler_dsp.cc
+++ b/winsup/cygwin/fhandler_dsp.cc
@@ -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:
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index 0e2d2bde4..d2b236d5c 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -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 ();
diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc
index 033498742..c9a18c3d9 100644
--- a/winsup/cygwin/fhandler_serial.cc
+++ b/winsup/cygwin/fhandler_serial.cc
@@ -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*/
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 38a0571cb..fe7e283a9 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -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*/
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 2d00e7c96..0186af733 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -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*/
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index 649cda694..a62c038cd 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -22,6 +22,7 @@ details. */
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
+#include "cygwait.h"
#define _SA_NORESTART 0x8000
diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h
index a86c6bc42..d980f1a6e 100644
--- a/winsup/cygwin/sigproc.h
+++ b/winsup/cygwin/sigproc.h
@@ -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)));
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index b66bd4835..f3ff336f4 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -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--;
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index ec3ca7ebf..0dd9b893b 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -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 ()
diff --git a/winsup/cygwin/wait.cc b/winsup/cygwin/wait.cc
index 91a76239a..829c123bd 100644
--- a/winsup/cygwin/wait.cc
+++ b/winsup/cygwin/wait.cc
@@ -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);