From 8656ee07efbd5d47cde561d4ead67174970f989b Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sat, 26 Feb 2000 01:11:54 +0000 Subject: [PATCH] * exceptions.cc (interruptible): Make a little more structured. (call_handler): Allow signals to be sent even if signalled thread is stopped. Change order of signal_arrived arming/waiting threads clearing to eliminate a race. (reset_signal_arrived): New helper function. * malloc.cc (malloc_init): Use mutos so that signal handler can keep track of who owns the lock. (__malloc_lock): Ditto. (__malloc_unlock): Ditto. * sync.h (new_muto): Actually use a muto for the "buffer". * Makefile.in: Fix a dependency. --- winsup/cygwin/ChangeLog | 16 ++++++- winsup/cygwin/Makefile.in | 2 +- winsup/cygwin/debug.cc | 1 + winsup/cygwin/exceptions.cc | 73 +++++++++++++++++++------------ winsup/cygwin/fhandler.cc | 1 + winsup/cygwin/fhandler_console.cc | 1 - winsup/cygwin/malloc_wrapper.cc | 9 ++-- winsup/cygwin/sigproc.cc | 1 + winsup/cygwin/sync.cc | 5 ++- winsup/cygwin/sync.h | 12 ++--- winsup/cygwin/winsup.h | 2 - 11 files changed, 77 insertions(+), 46 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index da5352695..83c70d277 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +Fri Feb 25 19:26:42 2000 Christopher Faylor + + * exceptions.cc (interruptible): Make a little more structured. + (call_handler): Allow signals to be sent even if signalled thread is + stopped. Change order of signal_arrived arming/waiting threads + clearing to eliminate a race. + (reset_signal_arrived): New helper function. + * malloc.cc (malloc_init): Use mutos so that signal handler can keep + track of who owns the lock. + (__malloc_lock): Ditto. + (__malloc_unlock): Ditto. + * sync.h (new_muto): Actually use a muto for the "buffer". + * Makefile.in: Fix a dependency. + 2000-02-25 DJ Delorie * Makefile.in: fix "make check" support and cygrun. @@ -17,7 +31,7 @@ Thu Feb 24 14:45:06 2000 Christopher Faylor Thu Feb 24 00:59:15 2000 Christopher Faylor - Fix final round of gcc warnings relating to unused parameters. + Fix final round of gcc warnings relating to unused parameters. * debug.cc (iscygthread): New function. * debug.h: Declare it. * exceptions.cc (set_process_mask): Flush pending signals. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index dfef07c56..de386a91b 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -302,7 +302,7 @@ ioctl.o: $(WINSUP_H) libccrt0.o: $(WINSUP_H) libcmain.o: $(WINSUP_H) localtime.o: tz_posixrules.h -malloc.o: $(WINSUP_H) +malloc.o: $(WINSUP_H) sync.h mcount.o: gmon.h mmap.o: $(WINSUP_H) net.o: $(WINSUP_H) autoload.h diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc index 6218312fe..e7ddec8af 100644 --- a/winsup/cygwin/debug.cc +++ b/winsup/cygwin/debug.cc @@ -9,6 +9,7 @@ details. */ #define NO_DEBUG_DEFINES #include "winsup.h" #include "exceptions.h" +#include "sync.h" static muto NO_COPY *threadname_lock = NULL; #define lock_threadname() \ diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 3213aa972..1cfe1e701 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -18,6 +18,7 @@ details. */ #define DECLSPEC_IMPORT #include #include "autoload.h" +#include "sync.h" char debugger_command[2 * MAX_PATH + 20]; @@ -557,7 +558,7 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *) bp -= 2; break; } - + in->Ebp = (DWORD) bp; sigsave.cx = in; sig_send (NULL, sig); // Signal myself @@ -621,21 +622,28 @@ interruptible (DWORD pc) return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) || !(pchigh == 0xb0000000 || pchigh == 0x70000000 || pchigh == 0x60000000); #else + int res = 1; if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) - return 1; + res = 0; + else + { + MEMORY_BASIC_INFORMATION m; + memset (&m, 0, sizeof m); + if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m)) + sigproc_printf ("couldn't get memory info, %E"); - MEMORY_BASIC_INFORMATION m; - memset (&m, 0, sizeof m); - if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m)) - sigproc_printf ("couldn't get memory info, %E"); + char *checkdir = (char *) alloca (windows_system_directory_length); +# define h ((HMODULE) m.AllocationBase) + if (h == cygwin_hmodule) + res = 0; + else if (!GetModuleFileName (h, checkdir, windows_system_directory_length)) + res = 0; + else + res = !strncasematch (windows_system_directory, checkdir, + windows_system_directory_length); + } -# define h ((HMODULE) m.AllocationBase) - if (h == cygwin_hmodule) - return 0; - char *checkdir = (char *) alloca (windows_system_directory_length); - if (!GetModuleFileName (h, checkdir, windows_system_directory_length)) - return 0; - return !strncasematch (windows_system_directory, checkdir, windows_system_directory_length); + return res; # undef h #endif } @@ -727,7 +735,6 @@ call_handler (int sig, struct sigaction& siga, void *handler) we have to do that since sometimes they don't return - and if this thread doesn't return, you won't ever get another exception. */ - sigproc_printf ("Suspending %p (mainthread)", myself->getthread2signal()); HANDLE hth = myself->getthread2signal (); /* Suspend the thread which will receive the signal. But first ensure that this thread doesn't have the sync_proc_subproc and mask_sync mutos, since @@ -736,11 +743,9 @@ call_handler (int sig, struct sigaction& siga, void *handler) already suspended (which should never occur) then just queue the signal. */ for (;;) { + sigproc_printf ("suspending mainthread"); res = SuspendThread (hth); - if (res) - goto set_pending; - /* FIXME: Make multi-thread aware */ for (muto *m = muto_start.next; m != NULL; m = m->next) if (m->unstable () || m->owner () == maintid) @@ -749,10 +754,14 @@ call_handler (int sig, struct sigaction& siga, void *handler) break; keep_looping: + sigproc_printf ("suspended thread owns a muto"); + if (res) + goto set_pending; + ResumeThread (hth); Sleep (0); } - + sigproc_printf ("suspend said %d, %E", res); if (sigsave.cx) @@ -783,12 +792,6 @@ call_handler (int sig, struct sigaction& siga, void *handler) interrupted = 0; } - if (interrupted) - { - /* Clear any waiting threads prior to dispatching to handler function */ - proc_subproc(PROC_CLEARWAIT, 1); - } - (void) ResumeThread (hth); if (interrupted) @@ -796,6 +799,8 @@ call_handler (int sig, struct sigaction& siga, void *handler) /* Apparently we have to set signal_arrived after resuming the thread or it is possible that the event will be ignored. */ (void) SetEvent (signal_arrived); // For an EINTR case + /* Clear any waiting threads prior to dispatching to handler function */ + proc_subproc(PROC_CLEARWAIT, 1); } sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res); @@ -1068,6 +1073,15 @@ events_terminate (void) #define pid_offset (unsigned)(((pinfo *)NULL)->pid) extern "C" { +static void __stdcall +reset_signal_arrived () __attribute__ ((unused)); +static void __stdcall +reset_signal_arrived () +{ + (void) ResetEvent (signal_arrived); + sigproc_printf ("reset signal_arrived"); +} + void unused_sig_wrapper() { /* Signal cleanup stuff. Cleans up stack (too bad that we didn't @@ -1076,7 +1090,6 @@ void unused_sig_wrapper() and returns to orignal caller. */ __asm__ volatile (" .text -___sigfirst: .globl __raise __raise: pushl %%ebp @@ -1120,19 +1133,21 @@ _sigdelayed: pushl %3 # oldmask pushl %4 # signal argument pushl $_sigreturn - movl $0,%0 - pushl _signal_arrived # Everybody waiting for this should - call _ResetEvent@4 # have woken up by now. + call _reset_signal_arrived@0 +# pushl _signal_arrived # Everybody waiting for this should +# call _ResetEvent@4 # have woken up by now. + movl $0,%0 cmpl $0,_pending_signals je 2f +___sigfirst: pushl $0 call _sig_dispatch_pending@4 +___siglast: 2: jmp *%5 -___siglast: " : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno), "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig), "g" (sigsave.func), "o" (pid_offset), "g" (sigsave.saved_errno) diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index f4335a249..3d0195822 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -13,6 +13,7 @@ details. */ #include #include #include "winsup.h" +#include "sync.h" static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 67732ba1c..e95cc0a9a 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -178,7 +178,6 @@ fhandler_console::read (void *pv, size_t buflen) kill_pgrp (tc->getpgid (), SIGWINCH); continue; } -debug_printf ("ich %d, keydown %d, type %d", ich, input_rec.Event.KeyEvent.bKeyDown, input_rec.EventType); if (input_rec.EventType != KEY_EVENT || !input_rec.Event.KeyEvent.bKeyDown) continue; diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc index 3442c14d4..3fa5e064f 100644 --- a/winsup/cygwin/malloc_wrapper.cc +++ b/winsup/cygwin/malloc_wrapper.cc @@ -13,6 +13,7 @@ details. */ #include "winsup.h" #include +#include "sync.h" /* we provide these stubs to call into a user's provided malloc if there is one - otherwise @@ -200,12 +201,12 @@ _strdup_r (struct _reent *, const char *s) newlib will call __malloc_lock and __malloc_unlock at appropriate times. */ -static NO_COPY CRITICAL_SECTION malloc_critical_section; +static NO_COPY muto *mprotect = NULL; void malloc_init () { - InitializeCriticalSection (&malloc_critical_section); + mprotect = new_muto (FALSE, NULL); /* Check if mallock is provided by application. If so, redirect all calls to export_malloc/free/realloc to application provided. This may happen if some other dll calls cygwin's malloc, but main code provides @@ -226,12 +227,12 @@ extern "C" void __malloc_lock (struct _reent *) { - SetResourceLock(LOCK_MEMORY_LIST,WRITE_LOCK|READ_LOCK," __malloc_lock"); + mprotect->acquire (); } extern "C" void __malloc_unlock (struct _reent *) { - ReleaseResourceLock(LOCK_MEMORY_LIST,WRITE_LOCK|READ_LOCK," __malloc_unlock"); + mprotect->release (); } diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 9698a2362..991d91ffb 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -16,6 +16,7 @@ details. */ #include #include #include "winsup.h" +#include "sync.h" extern BOOL allow_ntsec; diff --git a/winsup/cygwin/sync.cc b/winsup/cygwin/sync.cc index 744eb8dc7..aa3978fe0 100644 --- a/winsup/cygwin/sync.cc +++ b/winsup/cygwin/sync.cc @@ -20,11 +20,12 @@ details. */ #include #include #include "winsup.h" +#include "sync.h" -muto muto_start (0, 0); +muto NO_COPY muto_start; /* Constructor */ -muto::muto(int inh, const char *name) : sync (0), visits(0), waiters(-1), tid (0), next (0) +muto::muto(int inh, const char *name) : sync (0), visits(0), waiters(-1), tid (0), next (NULL) { /* Create event which is used in the fallback case when blocking is necessary */ if (!(bruteforce = CreateEvent (inh ? &sec_all_nih : &sec_none_nih, FALSE, FALSE, name))) diff --git a/winsup/cygwin/sync.h b/winsup/cygwin/sync.h index 7215c2bd7..c7ada834a 100644 --- a/winsup/cygwin/sync.h +++ b/winsup/cygwin/sync.h @@ -28,7 +28,7 @@ public: /* This simple constructor is used for cases where no bruteforce event handling is required. */ - muto(): sync(0), visits(0), waiters(-1), bruteforce(0), tid(0), next (0) {;} + muto(): sync(0), visits(0), waiters(-1), bruteforce(0), tid(0), next (NULL) {;} /* A more complicated constructor. */ muto(int inh, const char *name); ~muto (); @@ -46,9 +46,9 @@ extern muto muto_start; /* Use a statically allocated buffer as the storage for a muto */ #define new_muto(__inh, __name) \ ({ \ - static NO_COPY char __mbuf[sizeof(class muto) + 100] = {0}; \ - muto *m = muto_start.next; \ - muto_start.next = new (__mbuf) muto ((__inh), (__name)); \ - muto_start.next->next = m; \ - muto_start.next; \ + static NO_COPY muto __mbuf; \ + (void) new ((char *) &__mbuf) muto (__inh, __name); \ + __mbuf.next = muto_start.next; \ + muto_start.next = &__mbuf; \ + &__mbuf; \ }) diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 4bbf789f2..3e07fb1e9 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -82,8 +82,6 @@ extern int dynamically_loaded; extern HANDLE hMainThread; extern HANDLE hMainProc; -#include "sync.h" - /* Now that pinfo has been defined, include... */ #include "debug.h" #include "sigproc.h"