* 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.
This commit is contained in:
Christopher Faylor 2000-02-26 01:11:54 +00:00
parent 52aaab48f4
commit 8656ee07ef
11 changed files with 77 additions and 46 deletions

View File

@ -1,3 +1,17 @@
Fri Feb 25 19:26:42 2000 Christopher Faylor <cgf@cygnus.com>
* 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 <dj@cygnus.com> 2000-02-25 DJ Delorie <dj@cygnus.com>
* Makefile.in: fix "make check" support and cygrun. * Makefile.in: fix "make check" support and cygrun.

View File

@ -302,7 +302,7 @@ ioctl.o: $(WINSUP_H)
libccrt0.o: $(WINSUP_H) libccrt0.o: $(WINSUP_H)
libcmain.o: $(WINSUP_H) libcmain.o: $(WINSUP_H)
localtime.o: tz_posixrules.h localtime.o: tz_posixrules.h
malloc.o: $(WINSUP_H) malloc.o: $(WINSUP_H) sync.h
mcount.o: gmon.h mcount.o: gmon.h
mmap.o: $(WINSUP_H) mmap.o: $(WINSUP_H)
net.o: $(WINSUP_H) autoload.h net.o: $(WINSUP_H) autoload.h

View File

@ -9,6 +9,7 @@ details. */
#define NO_DEBUG_DEFINES #define NO_DEBUG_DEFINES
#include "winsup.h" #include "winsup.h"
#include "exceptions.h" #include "exceptions.h"
#include "sync.h"
static muto NO_COPY *threadname_lock = NULL; static muto NO_COPY *threadname_lock = NULL;
#define lock_threadname() \ #define lock_threadname() \

View File

@ -18,6 +18,7 @@ details. */
#define DECLSPEC_IMPORT #define DECLSPEC_IMPORT
#include <imagehlp.h> #include <imagehlp.h>
#include "autoload.h" #include "autoload.h"
#include "sync.h"
char debugger_command[2 * MAX_PATH + 20]; char debugger_command[2 * MAX_PATH + 20];
@ -621,21 +622,28 @@ interruptible (DWORD pc)
return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) || return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) ||
!(pchigh == 0xb0000000 || pchigh == 0x70000000 || pchigh == 0x60000000); !(pchigh == 0xb0000000 || pchigh == 0x70000000 || pchigh == 0x60000000);
#else #else
int res = 1;
if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
return 1; res = 0;
else
{
MEMORY_BASIC_INFORMATION m; MEMORY_BASIC_INFORMATION m;
memset (&m, 0, sizeof m); memset (&m, 0, sizeof m);
if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m)) if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
sigproc_printf ("couldn't get memory info, %E"); sigproc_printf ("couldn't get memory info, %E");
char *checkdir = (char *) alloca (windows_system_directory_length);
# define h ((HMODULE) m.AllocationBase) # define h ((HMODULE) m.AllocationBase)
if (h == cygwin_hmodule) if (h == cygwin_hmodule)
return 0; res = 0;
char *checkdir = (char *) alloca (windows_system_directory_length); else if (!GetModuleFileName (h, checkdir, windows_system_directory_length))
if (!GetModuleFileName (h, checkdir, windows_system_directory_length)) res = 0;
return 0; else
return !strncasematch (windows_system_directory, checkdir, windows_system_directory_length); res = !strncasematch (windows_system_directory, checkdir,
windows_system_directory_length);
}
return res;
# undef h # undef h
#endif #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 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. */ this thread doesn't return, you won't ever get another exception. */
sigproc_printf ("Suspending %p (mainthread)", myself->getthread2signal());
HANDLE hth = myself->getthread2signal (); HANDLE hth = myself->getthread2signal ();
/* Suspend the thread which will receive the signal. But first ensure that /* 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 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. */ already suspended (which should never occur) then just queue the signal. */
for (;;) for (;;)
{ {
sigproc_printf ("suspending mainthread");
res = SuspendThread (hth); res = SuspendThread (hth);
if (res)
goto set_pending;
/* FIXME: Make multi-thread aware */ /* FIXME: Make multi-thread aware */
for (muto *m = muto_start.next; m != NULL; m = m->next) for (muto *m = muto_start.next; m != NULL; m = m->next)
if (m->unstable () || m->owner () == maintid) if (m->unstable () || m->owner () == maintid)
@ -749,6 +754,10 @@ call_handler (int sig, struct sigaction& siga, void *handler)
break; break;
keep_looping: keep_looping:
sigproc_printf ("suspended thread owns a muto");
if (res)
goto set_pending;
ResumeThread (hth); ResumeThread (hth);
Sleep (0); Sleep (0);
} }
@ -783,12 +792,6 @@ call_handler (int sig, struct sigaction& siga, void *handler)
interrupted = 0; interrupted = 0;
} }
if (interrupted)
{
/* Clear any waiting threads prior to dispatching to handler function */
proc_subproc(PROC_CLEARWAIT, 1);
}
(void) ResumeThread (hth); (void) ResumeThread (hth);
if (interrupted) 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 /* Apparently we have to set signal_arrived after resuming the thread or it
is possible that the event will be ignored. */ is possible that the event will be ignored. */
(void) SetEvent (signal_arrived); // For an EINTR case (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); 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) #define pid_offset (unsigned)(((pinfo *)NULL)->pid)
extern "C" { 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() void unused_sig_wrapper()
{ {
/* Signal cleanup stuff. Cleans up stack (too bad that we didn't /* 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. */ and returns to orignal caller. */
__asm__ volatile (" __asm__ volatile ("
.text .text
___sigfirst:
.globl __raise .globl __raise
__raise: __raise:
pushl %%ebp pushl %%ebp
@ -1120,19 +1133,21 @@ _sigdelayed:
pushl %3 # oldmask pushl %3 # oldmask
pushl %4 # signal argument pushl %4 # signal argument
pushl $_sigreturn pushl $_sigreturn
movl $0,%0
pushl _signal_arrived # Everybody waiting for this should call _reset_signal_arrived@0
call _ResetEvent@4 # have woken up by now. # pushl _signal_arrived # Everybody waiting for this should
# call _ResetEvent@4 # have woken up by now.
movl $0,%0
cmpl $0,_pending_signals cmpl $0,_pending_signals
je 2f je 2f
___sigfirst:
pushl $0 pushl $0
call _sig_dispatch_pending@4 call _sig_dispatch_pending@4
___siglast:
2: jmp *%5 2: jmp *%5
___siglast:
" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno), " : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
"g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig), "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig),
"g" (sigsave.func), "o" (pid_offset), "g" (sigsave.saved_errno) "g" (sigsave.func), "o" (pid_offset), "g" (sigsave.saved_errno)

View File

@ -13,6 +13,7 @@ details. */
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include "winsup.h" #include "winsup.h"
#include "sync.h"
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */

View File

@ -178,7 +178,6 @@ fhandler_console::read (void *pv, size_t buflen)
kill_pgrp (tc->getpgid (), SIGWINCH); kill_pgrp (tc->getpgid (), SIGWINCH);
continue; continue;
} }
debug_printf ("ich %d, keydown %d, type %d", ich, input_rec.Event.KeyEvent.bKeyDown, input_rec.EventType);
if (input_rec.EventType != KEY_EVENT || if (input_rec.EventType != KEY_EVENT ||
!input_rec.Event.KeyEvent.bKeyDown) !input_rec.Event.KeyEvent.bKeyDown)
continue; continue;

View File

@ -13,6 +13,7 @@ details. */
#include "winsup.h" #include "winsup.h"
#include <stdlib.h> #include <stdlib.h>
#include "sync.h"
/* we provide these stubs to call into a user's /* we provide these stubs to call into a user's
provided malloc if there is one - otherwise 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 newlib will call __malloc_lock and __malloc_unlock at appropriate
times. */ times. */
static NO_COPY CRITICAL_SECTION malloc_critical_section; static NO_COPY muto *mprotect = NULL;
void void
malloc_init () malloc_init ()
{ {
InitializeCriticalSection (&malloc_critical_section); mprotect = new_muto (FALSE, NULL);
/* Check if mallock is provided by application. If so, redirect all /* Check if mallock is provided by application. If so, redirect all
calls to export_malloc/free/realloc to application provided. This may calls to export_malloc/free/realloc to application provided. This may
happen if some other dll calls cygwin's malloc, but main code provides happen if some other dll calls cygwin's malloc, but main code provides
@ -226,12 +227,12 @@ extern "C"
void void
__malloc_lock (struct _reent *) __malloc_lock (struct _reent *)
{ {
SetResourceLock(LOCK_MEMORY_LIST,WRITE_LOCK|READ_LOCK," __malloc_lock"); mprotect->acquire ();
} }
extern "C" extern "C"
void void
__malloc_unlock (struct _reent *) __malloc_unlock (struct _reent *)
{ {
ReleaseResourceLock(LOCK_MEMORY_LIST,WRITE_LOCK|READ_LOCK," __malloc_unlock"); mprotect->release ();
} }

View File

@ -16,6 +16,7 @@ details. */
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include "winsup.h" #include "winsup.h"
#include "sync.h"
extern BOOL allow_ntsec; extern BOOL allow_ntsec;

View File

@ -20,11 +20,12 @@ details. */
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include "winsup.h" #include "winsup.h"
#include "sync.h"
muto muto_start (0, 0); muto NO_COPY muto_start;
/* Constructor */ /* 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 */ /* 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))) if (!(bruteforce = CreateEvent (inh ? &sec_all_nih : &sec_none_nih, FALSE, FALSE, name)))

View File

@ -28,7 +28,7 @@ public:
/* This simple constructor is used for cases where no bruteforce /* This simple constructor is used for cases where no bruteforce
event handling is required. */ 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. */ /* A more complicated constructor. */
muto(int inh, const char *name); muto(int inh, const char *name);
~muto (); ~muto ();
@ -46,9 +46,9 @@ extern muto muto_start;
/* Use a statically allocated buffer as the storage for a muto */ /* Use a statically allocated buffer as the storage for a muto */
#define new_muto(__inh, __name) \ #define new_muto(__inh, __name) \
({ \ ({ \
static NO_COPY char __mbuf[sizeof(class muto) + 100] = {0}; \ static NO_COPY muto __mbuf; \
muto *m = muto_start.next; \ (void) new ((char *) &__mbuf) muto (__inh, __name); \
muto_start.next = new (__mbuf) muto ((__inh), (__name)); \ __mbuf.next = muto_start.next; \
muto_start.next->next = m; \ muto_start.next = &__mbuf; \
muto_start.next; \ &__mbuf; \
}) })

View File

@ -82,8 +82,6 @@ extern int dynamically_loaded;
extern HANDLE hMainThread; extern HANDLE hMainThread;
extern HANDLE hMainProc; extern HANDLE hMainProc;
#include "sync.h"
/* Now that pinfo has been defined, include... */ /* Now that pinfo has been defined, include... */
#include "debug.h" #include "debug.h"
#include "sigproc.h" #include "sigproc.h"