[m-dev.] for review: use Win32 exceptions in the runtime

Peter Ross petdr at cs.mu.OZ.AU
Wed Jun 28 23:20:11 AEST 2000


On Wed, Jun 28, 2000 at 07:44:00AM +1000, Fergus Henderson wrote:
> On 27-Jun-2000, Peter Ross <petdr at cs.mu.OZ.AU> wrote:
> > On Tue, Jun 27, 2000 at 10:56:20AM +1000, Fergus Henderson wrote:
> > > Where does MR_WIN32 get defined?
> > > 
> > It is defined in mercury_conf.h, which is generate by configure.
> 
> Ah, I see.  Thanks.
> 
> I think the documentation of MR_WIN32 is not clear.
> 
> For example, if MS port MSVC++ to Linux, should MR_WIN32
> be defined when using the Linux version of MSVC++?
> 
Good point, a search of MSDN documentation found _WIN32 which is defined
if we are in Win32 land.


> > > > +#ifdef MR_PROTECTPAGE
> > > > +
> > > > +  #ifdef MR_WIN32
> > > > +    #define PROT_NONE  0x0000
> > > > +    #define PROT_READ  0x0001
> > > > +    #define PROT_WRITE 0x0002
> > > > +  #endif
> > > 
> > > That could cause problems on systems that offer both Win32 and Unix APIs,
> > > and thus define MR_WIN32 but also include a definition of PROT_NONE in
> > > the system header files.  I suggest using MR_PROT_NONE etc.
> > > and defining MR_PROT_NONE as PROT_NONE on systems for which MR_WIN32
> > > is not defined.
> > 
> > If PROT_* are not defined, I define them as above, this is all that
> > needs to be done.
> 
> But the above definitions are not protected by `#ifndef'.
> So you define PROT_* regardless of whether or not they are already defined.
> This might cause problems on systems that define both MR_WIN32 and PROT_NONE.
> I suppose you could change them to
> 
> 	#ifdef MR_PROTECTPAGE
> 	
> 	  #ifdef MR_WIN32
> 	    #ifndef PROT_NONE
> 	      #define PROT_NONE  0x0000
> 	    #endif
> 	    #ifndef PROT_READ
> 	      #define PROT_READ  0x0001
> 	    #endif
> 	    #ifndef PROT_WRITE
> 	      #define PROT_WRITE 0x0002
> 	    #endif
> 	  #endif
> 
> and that would be a bit safer.  Oh, wait, I see from the diff that is
> exactly what you did.  Still, even then, there might be problems if
> those macros were not defined at this point because the appropriate
> system header file has not been included, but that system header file
> was then included later on in the compilation unit.  If that were to
> happen, you might get errors in the system header file because
> PROT_NONE etc. were already defined.
> 
I can live with this solution at the moment.


> > +++ runtime/mercury_memory_handlers.c	Tue Jun 27 14:08:08 2000
> > @@ -554,7 +553,7 @@
> >  
> >  #endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
> >  
> > -#ifdef MR_WIN32
> > +#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
> >  #include <tchar.h>
> 
> Hmm, here you're assuming that MR_WIN32_STRUCTURED_EXCEPTIONS
> implies that we have <tchar.h>.  Is that necessary?
> What are you using <tchar.h> for?  Is it just the `_T' macro?
> What exactly does that do, and why do you need it?
> 
It is something to do with Unicode strings (I believe), which we don't
need so I have removed.

> If you really do need <tchar.h>, it would be a good idea to document
> it in the documentation for MR_WIN32_STRUCTURED_EXCEPTIONS.
> 
No I don't need it.

 > Index: mercury_memory_zones.c
> > ===================================================================
> > RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
> > retrieving revision 1.10
> > diff -u -r1.10 mercury_memory_zones.c
> > --- mercury_memory_zones.c	2000/06/08 07:59:05	1.10
> > +++ mercury_memory_zones.c	2000/06/27 12:16:25
> > @@ -51,9 +51,84 @@
> >    #include "mercury_thread.h"
> >  #endif
> >  
> > +#ifdef MR_WIN32
> > +  #include <windows.h>
> > +#endif
> 
> Shouldn't that be `#ifdef MR_WIN32_VIRTUAL_ALLOC'?
> 
Yes.


And now here is a relative diff and full diff.




Estimated hours taken: 48

Use Win32 exceptions to report problems when Win32 structured exceptions
are available.

configure.in:
runtime/mercury_conf.h.in:
    No longer define MR_WIN32, just because we are using a Microsoft
    compiler, instead we use _WIN32 to detect the presence of the Win32
    API.

runtime/mercury_conf_param.h:
    Define the following symbolic constants:
        MR_WIN32 which is true if the Win32 API is available.
        MR_WIN32_GETSYSTEMINFO which is true if GetSystemInfo() is
        availabe.
        MR_WIN32_VIRTUALALLOC which is true if VirtualAlloc() is
        availabe.
        MR_MSVC_STRUCTURED_EXCEPTIONS if we can use Microsoft Visual C
        structured exceptions.
        MR_PROTECTPAGE if can provide mprotect like functionality.
    All of the above are assumed true if the Win32 API is available.
    MR_CHECK_OVERFLOW_VIA_MPROTECT is also true if MR_WIN32, because the
    Win32 API provides mprotect like functionality.
    
runtime/mercury_memory_zones.c:
    Define a function MR_protect_pages() which has the same interface as
    mprotect.  It just calls mprotect when it exists or equivalent code
    to emulate it under Win32.
    Use MR_PROTECTPAGE in place of HAVE_MPROTECT, and replace all calls
    to mprotect() with MR_protect_pages().
    Define a Win32 version of memalign.

runtime/mercury_memory_handlers.c:
    Use MR_protect_pages() instead of mprotect().
    Don't use signal handlers when in a Win32 structured exceptions are
    available.
    Code to explain Win32 exceptions on stderr.

runtime/mercury_memory_handlers.h:
    Export MR_filter_win32_exception for use in mercury_wrapper.c

runtime/mercury_memory_zones.h:
    Use MR_PROTECTPAGE in place of HAVE_MPROTECT.
    Define PROT_{NONE,READ,WRITE} if we the Win32 API is available and
    they are not already defined.
    Export the definition of MR_protect_pages().

runtime/mercury_wrapper.c:
    Wrap the call to main in a __try __except block if we are using
    Win32 structured exceptions, so that any exceptions generated are
    caught and debugging info about them printed to stderr.

runtime/mercury_memory.c:
    Add a Win32 version of getpagesize().

*** relative diff ***
Common subdirectories: runtime.old/CVS and runtime/CVS
Common subdirectories: runtime.old/GETOPT and runtime/GETOPT
Common subdirectories: runtime.old/machdeps and runtime/machdeps
diff -u runtime.old/mercury_conf.h.in runtime/mercury_conf.h.in
--- runtime.old/mercury_conf.h.in	Thu Jun  8 09:59:04 2000
+++ runtime/mercury_conf.h.in	Wed Jun 28 14:42:23 2000
@@ -346,12 +346,6 @@
 #undef  HAVE_READLINE_READLINE
 #undef  HAVE_READLINE_HISTORY
 
-/*
-** MR_WIN32
-**	Set this if you are using Microsoft Visual C++ as your C compiler.
-*/	
-#undef	MR_WIN32
-
 /*---------------------------------------------------------------------------*/
 
 #include "mercury_conf_param.h"
diff -u runtime.old/mercury_conf_param.h runtime/mercury_conf_param.h
--- runtime.old/mercury_conf_param.h	Tue Jun 27 14:15:52 2000
+++ runtime/mercury_conf_param.h	Wed Jun 28 14:52:06 2000
@@ -345,18 +345,29 @@
   #define MR_CAN_GET_PC_AT_SIGNAL
 #endif
 
-        /* We can check for overflow using mprotect like functionality */
-#if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(MR_WIN32)
+/*
+** MR_CHECK_OVERFLOW_VIA_MPROTECT  --	Can check for overflow of various
+**					memory zones using mprotect() like
+**					functionality.
+*/
+#if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(_WIN32)
   #define MR_CHECK_OVERFLOW_VIA_MPROTECT
 #endif
 
-        /* The functionality of mprotect can be provided */
-#if defined(HAVE_MPROTECT) || defined(MR_WIN32)
+/*
+** MR_PROTECTPAGE   -- 	MR_protect_pages() can be defined to provide the same
+**			functionality as the system call mprotect().
+*/
+#if defined(HAVE_MPROTECT) || defined(_WIN32)
   #define MR_PROTECTPAGE
 #endif
 
-#if defined(MR_WIN32)
-  #define MR_WIN32_STRUCTURED_EXCEPTIONS
+/*
+** MR_MSVC_STRUCTURED_EXCEPTIONS
+** 	Use Microsoft Visual C structured exceptions for signal handling.
+*/
+#if defined(_MSC_VER)
+  #define MR_MSVC_STRUCTURED_EXCEPTIONS
 #endif
 
 /*---------------------------------------------------------------------------*/
@@ -364,9 +375,18 @@
 /*
 ** Win32 API specific.
 */
-#if defined(MR_WIN32)
-  #define MR_WIN32_GETSYSTEMINFO	/* to determine page size */
-  #define MR_WIN32_VIRTUAL_ALLOC	/* to provide mprotect functionality */
+
+/*
+** MR_WIN32 -- The Win32 API is available.
+**
+** MR_WIN32_GETSYSTEMINFO -- Is GetSystemInfo() available?
+**
+** MR_WIN32_VIRTUAL_ALLOC -- Is VirtualAlloc() available?
+*/
+#if _WIN32
+  #define MR_WIN32
+  #define MR_WIN32_GETSYSTEMINFO
+  #define MR_WIN32_VIRTUAL_ALLOC
 #endif
 
 /*---------------------------------------------------------------------------*/
diff -u runtime.old/mercury_memory.c runtime/mercury_memory.c
--- runtime.old/mercury_memory.c	Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory.c	Wed Jun 28 14:42:23 2000
@@ -99,8 +99,8 @@
   #if defined(MR_WIN32_GETSYSTEMINFO)
     #include <windows.h>
 
-    static
-    size_t getpagesize(void)
+    static size_t
+    getpagesize(void)
     {
 	SYSTEM_INFO SysInfo;
 	GetSystemInfo(&SysInfo);
diff -u runtime.old/mercury_memory_handlers.c runtime/mercury_memory_handlers.c
--- runtime.old/mercury_memory_handlers.c	Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_handlers.c	Wed Jun 28 14:42:23 2000
@@ -222,7 +222,8 @@
 	    (int)zone_size);
 	}
 	if (MR_protect_pages((char *)zone->redzone, zone_size,
-		PROT_READ|PROT_WRITE) < 0) {
+		PROT_READ|PROT_WRITE) < 0)
+	{
 	    char buf[2560];
 	    sprintf(buf, "Mercury runtime: cannot unprotect %s#%d zone",
 		zone->name, zone->id);
@@ -262,10 +263,11 @@
 setup_signals(void)
 {
 /*
-** When using Win32 structured exceptions don't set any signal handler.
+** When using Microsoft Visual C structured exceptions don't set any
+** signal handlers.
 ** See mercury_wrapper.c for the reason why.
 */
-#ifndef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifndef MR_MSVC_STRUCTURED_EXCEPTIONS
   #ifdef SIGBUS
 	MR_setup_signal(SIGBUS, (Code *) bus_handler, TRUE,
 		"Mercury runtime: cannot set SIGBUS handler");
@@ -553,21 +555,25 @@
 
 #endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
 
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
-#include <tchar.h>
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+static const char *MR_find_exception_name(DWORD exception_code);
+static void MR_explain_exception_record(EXCEPTION_RECORD *rec);
+static void MR_dump_exception_record(EXCEPTION_RECORD *rec);
+static bool MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+		void **address_ptr, int *access_mode_ptr);
 
 /*
 ** Exception code and their string representation
 */
-#define DEFINE_EXCEPTION_NAME(a)   {a,_T(#a)}
+#define DEFINE_EXCEPTION_NAME(a)   {a,#a}
 
 typedef struct
 {
-	DWORD exception_code;
-	LPTSTR exception_name;
+	DWORD		exception_code;
+	const char	*exception_name;
 } MR_ExceptionName;
 
-static
+static const
 MR_ExceptionName MR_exception_names[] =
 {
 	DEFINE_EXCEPTION_NAME(EXCEPTION_ACCESS_VIOLATION),
@@ -598,17 +604,18 @@
 /*
 ** Retrieve the name of a Win32 exception code as a string
 */
-static
-LPTSTR MR_find_exception_name(DWORD exception_code)
+static const char *
+MR_find_exception_name(DWORD exception_code)
 {
 	int i;
 	for (i = 0; i < sizeof(MR_exception_names)
-			/ sizeof(MR_ExceptionName); i++) {
+			/ sizeof(MR_ExceptionName); i++)
+	{
 		if (MR_exception_names[i].exception_code == exception_code) {
 			return MR_exception_names[i].exception_name;
 		}
 	}
-	return _T("Unknown exception code");
+	return "Unknown exception code";
 }
 
 /*
@@ -621,8 +628,8 @@
 /*
 ** Explain an EXCEPTION_RECORD content into stderr.
 */
-static
-void MR_explain_exception_record(EXCEPTION_RECORD *rec)
+static void
+MR_explain_exception_record(EXCEPTION_RECORD *rec)
 {
 	fprintf(stderr, "\n");
 	fprintf(stderr, "\n*** Explanation of the exception record");
@@ -634,11 +641,12 @@
 		int access_mode;
 		
 		/* If the exception is an access violation */
-		if (MR_ExceptionrecordIsAccessViolation(rec,
-					&address, &access_mode)) {
+		if (MR_exception_record_is_access_violation(rec,
+					&address, &access_mode))
+		{
 			MemoryZone *zone;
 
-			/* Display AV address and acces mode */
+			/* Display AV address and access mode */
 			fprintf(stderr, "\n***   An access violation occured"
 					" at address 0x%08lx, while attempting"
 					" to ", (unsigned long) address);
@@ -666,21 +674,23 @@
 			while(zone != NULL) {
 				fprintf(stderr,
 						"\n***    Checking zone %s#%d: "
-						"0x%08x - 0x%08x - 0x%08x",
+						"0x%08lx - 0x%08lx - 0x%08lx",
 						zone->name, zone->id,
-						(void *) zone->bottom,
-						(void *) zone->redzone,
-						(void *) zone->top);
+						(unsigned long) zone->bottom,
+						(unsigned long) zone->redzone,
+						(unsigned long) zone->top);
 
 				if ((zone->redzone <= address) &&
-						(address <= zone->top)) {
+						(address <= zone->top))
+				{
 					fprintf(stderr,
 						"\n***     Address is within"
 						" redzone of "
 						"%s#%d (!!zone overflowed!!)\n",
 						zone->name, zone->id);
 				} else if ((zone->bottom <= address) &&
-						(address <= zone->top)) {
+						(address <= zone->top))
+				{
 					fprintf(stderr, "\n***     Address is"
 							" within zone %s#%d\n",
 							zone->name, zone->id);
@@ -701,8 +711,8 @@
 /*
 ** Dump an EXCEPTION_RECORD content into stderr.
 */
-static
-void MR_dump_exception_record(EXCEPTION_RECORD *rec)
+static void
+MR_dump_exception_record(EXCEPTION_RECORD *rec)
 {
 	int i;
 	
@@ -712,16 +722,20 @@
 	
 	fprintf(stderr, "\n***   Exception record at 0x%08lx:",
 			(unsigned long) rec);
-	fprintf(stderr, "\n***    Code        : 0x%08x (%s)",
-			rec->ExceptionCode,
+	fprintf(stderr, "\n***    Code        : 0x%08lx (%s)",
+			(unsigned long) rec->ExceptionCode,
 			MR_find_exception_name(rec->ExceptionCode));
-	fprintf(stderr, "\n***    Flags       : 0x%08x", rec->ExceptionFlags);
-	fprintf(stderr, "\n***    Address     : 0x%08x", rec->ExceptionAddress);
+	fprintf(stderr, "\n***    Flags       : 0x%08lx",
+			(unsigned long) rec->ExceptionFlags);
+	fprintf(stderr, "\n***    Address     : 0x%08lx",
+			(unsigned long) rec->ExceptionAddress);
+
 	for (i = 0; i < rec->NumberParameters; i++) {
-		fprintf(stderr, "\n***    Parameter %d : 0x%08x", i,
-				rec->ExceptionInformation[i]);
+		fprintf(stderr, "\n***    Parameter %d : 0x%08lx", i,
+				(unsigned long) rec->ExceptionInformation[i]);
 	}
-	fprintf(stderr, "\n***    Next record : 0x%08x", rec->ExceptionRecord);
+	fprintf(stderr, "\n***    Next record : 0x%08lx",
+			(unsigned long) rec->ExceptionRecord);
 	
 	/* Try to explain the exception more "gracefully" */
 	MR_explain_exception_record(rec);
@@ -730,17 +744,19 @@
 
 
 /*
-** Return TRUE iff ExecpPtrs indicates an Access Violation
-** If TRUE, lpAddress is set to the accessed address and
-** lpAccessMode is set to the desired access (0 = read, 1 = write)
+** Return TRUE iff exception_ptrs indicates an access violation.
+** If TRUE, the dereferenced address_ptr is set to the accessed address and
+** the dereferenced access_mode_ptr is set to the desired access
+** (0 = read, 1 = write)
 */
-bool MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
-		void **address, int *access_mode)
+static bool
+MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+		void **address_ptr, int *access_mode_ptr)
 {
 	if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
 		if (rec->NumberParameters >= 2) {
-			(*access_mode) = (int)rec->ExceptionInformation[0];
-			(*address) = (void *)rec->ExceptionInformation[1];
+			(*access_mode_ptr) = (int) rec->ExceptionInformation[0];
+			(*address_ptr) = (void *) rec->ExceptionInformation[1];
 			return TRUE;
 		}
 	}
@@ -749,8 +765,7 @@
 
 
 /*
-** Filter a Win32 exception (to be called in the __except filter
-** part).
+** Filter a Win32 exception (to be called in the __except filter part).
 ** Possible return values are:
 **
 ** EXCEPTION_CONTINUE_EXECUTION (-1)
@@ -768,7 +783,8 @@
 **  execution at the assembly instruction that was executing
 **  when the exception was raised. 
 */
-int MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs)
+int
+MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs)
 {
 	void *address;
 	int access_mode;
@@ -776,7 +792,8 @@
 		/* If the exception is an access violation */
 	if (MR_exception_record_is_access_violation(
 			exception_ptrs->ExceptionRecord,
-			&address, &access_mode)) {
+			&address, &access_mode))
+	{
 
 			/* If we can unprotect the memory zone */
 		if (try_munprotect(address, exception_ptrs)) {
@@ -803,14 +820,14 @@
 	fflush(stderr);
 		  
 	/*
-	 * Pass exception back to upper handler. In most cases, this
-	 * means activating UnhandledExceptionFilter, which will display
-	 * a dialog box asking to user ro activate the Debugger or simply
-	 * to kill the application
-	 */
+	** Pass exception back to upper handler. In most cases, this
+	** means activating UnhandledExceptionFilter, which will display
+	** a dialog box asking to user ro activate the Debugger or simply
+	** to kill the application
+	*/
 	return  EXCEPTION_CONTINUE_SEARCH;
 }
-#endif /* MR_WIN32_STRUCTURED_EXCEPTIONS */
+#endif /* MR_MSVC_STRUCTURED_EXCEPTIONS */
 
 
 /*
diff -u runtime.old/mercury_memory_handlers.h runtime/mercury_memory_handlers.h
--- runtime.old/mercury_memory_handlers.h	Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_handlers.h	Wed Jun 28 14:42:23 2000
@@ -37,7 +37,7 @@
 
 void	setup_signals(void);
 
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
 /*
 ** Filter a Win32 exception (to be called in the __except filter
 ** part).
diff -u runtime.old/mercury_memory_zones.c runtime/mercury_memory_zones.c
--- runtime.old/mercury_memory_zones.c	Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_zones.c	Wed Jun 28 15:15:37 2000
@@ -51,7 +51,7 @@
   #include "mercury_thread.h"
 #endif
 
-#ifdef MR_WIN32
+#ifdef MR_WIN32_VIRTUAL_ALLOC
   #include <windows.h>
 #endif
 
@@ -63,9 +63,9 @@
 */
 #if defined(HAVE_MPROTECT)
 int
-MR_protect_pages(void *Addr, size_t Size, int ProtFlags)
+MR_protect_pages(void *addr, size_t size, int prot_flags)
 {
-	return mprotect((char *)Addr, Size, ProtFlags);
+	return mprotect((char *) addr, size, prot_flags);
 }
 #elif defined(MR_WIN32_VIRTUAL_ALLOC)
 /*
@@ -79,23 +79,24 @@
 	DWORD Flags, OldFlags;
 
 	if (prot_flags & PROT_WRITE) {
-		Flags = PAGE_READWRITE;
+		flags = PAGE_READWRITE;
 	} else if (prot_flags & PROT_READ) {
-		Flags = PAGE_READONLY;
+		flags = PAGE_READONLY;
 	} else {
-		Flags = PAGE_NOACCESS;
+		flags = PAGE_NOACCESS;
 	}
 	
-	rc = (VirtualAlloc(addr, size, MEM_COMMIT, Flags) ? 0 : -1);
+	rc = (VirtualAlloc(addr, size, MEM_COMMIT, flags) ? 0 : -1);
 	if (rc < 0) {
 		fprintf(stderr,
-			"Error in VirtualProtect(addr=0x%08x, size=0x%08x):"
-			" 0x%08x\n", addr, size, GetLastError());
+			"Error in VirtualProtect(addr=0x%08lx, size=0x%08lx):"
+			" 0x%08lx\n", (unsigned long) addr,
+			(unsigned long) size, (unsigned long) GetLastError());
 	}
 
 	return rc;
 }
-#endif	/* HAVE_MPROTECT */
+#endif	/* MR_WIN32_VIRTUAL_ALLOC */
 
 
 /*---------------------------------------------------------------------------*/
@@ -110,23 +111,24 @@
 void *
 memalign(size_t unit, size_t size)
 {
-	void *rc;
+	void *ptr;
 
 	/*
 	** We don't need to use the 'unit' value as the memory is always
 	** aligned under Win32.
 	*/
-	rc = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
-	if (rc == NULL) {
-		fprintf(stderr, "Error in VirtualAlloc(size=0x%08x): 0x%08x\n",
-				size, GetLastError());
+	ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
+	if (ptr == NULL) {
+		fprintf(stderr, "Error in VirtualAlloc(size=0x%08lx):"
+				" 0x%08lx\n", (unsigned long) size,
+				(unsigned long) GetLastError());
 	}
 
   #ifdef CONSERVATIVE_GC
-	if (rc != NULL)
-		GC_add_roots((char *)rc, (char *)rc + size);
+	if (ptr != NULL)
+		GC_add_roots((char *)ptr, (char *)ptr + size);
   #endif
-	return rc;
+	return ptr;
 }
 #elif defined(CONSERVATIVE_GC)
   #define	memalign(a,s)   GC_MALLOC_UNCOLLECTABLE(s)
@@ -389,7 +391,8 @@
 	zone->redzone_base = zone->redzone = (Word *)
 			round_up((Unsigned)base + size - redsize, unit);
 	if (MR_protect_pages((char *)zone->redzone,
-			redsize + unit, MY_PROT) < 0) {
+			redsize + unit, MY_PROT) < 0)
+	{
 		char buf[2560];
 		sprintf(buf, "unable to set %s#%d redzone\n"
 			"base=%p, redzone=%p",
diff -u runtime.old/mercury_memory_zones.h runtime/mercury_memory_zones.h
--- runtime.old/mercury_memory_zones.h	Tue Jun 27 14:08:08 2000
+++ runtime/mercury_memory_zones.h	Wed Jun 28 14:42:23 2000
@@ -154,7 +154,7 @@
     #endif
   #endif
 
-int MR_protect_pages(void *Addr, size_t Size, int ProtFlags);
+int MR_protect_pages(void *addr, size_t size, int prot_flags);
 #endif
 
 /*
diff -u runtime.old/mercury_wrapper.c runtime/mercury_wrapper.c
--- runtime.old/mercury_wrapper.c	Tue Jun 27 14:08:08 2000
+++ runtime/mercury_wrapper.c	Wed Jun 28 14:42:23 2000
@@ -32,7 +32,7 @@
 #include	<stdio.h>
 #include	<string.h>
 
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
   #include <excpt.h>
 #endif
 
@@ -898,7 +898,7 @@
 
 	static	int	repcounter;
 
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
 	/*
 	** Under Win32 we use the following construction to handle exceptions.
 	**   __try
@@ -1018,7 +1018,7 @@
 	save_registers();
 	restore_regs_from_mem(c_regs);
 
-#ifdef MR_WIN32_STRUCTURED_EXCEPTIONS
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
 	}
 	__except(MR_filter_win32_exception(GetExceptionInformation()))
 	{

*** full diff ***
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.211
diff -u -r1.211 configure.in
--- configure.in	2000/06/23 07:40:34	1.211
+++ configure.in	2000/06/28 12:58:09
@@ -261,8 +261,6 @@
 
 	CYGPATH="cygpath -w"
 
-	AC_DEFINE(MR_WIN32)
-
 		# MS doesn't use a ranlib.
 	RANLIB="echo"
 	AC_SUBST(RANLIB)
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.26
diff -u -r1.26 mercury_conf.h.in
--- runtime/mercury_conf.h.in	2000/06/08 07:59:04	1.26
+++ runtime/mercury_conf.h.in	2000/06/28 12:58:22
@@ -346,12 +346,6 @@
 #undef  HAVE_READLINE_READLINE
 #undef  HAVE_READLINE_HISTORY
 
-/*
-** MR_WIN32
-**	Set this if you are using Microsoft Visual C++ as your C compiler.
-*/	
-#undef	MR_WIN32
-
 /*---------------------------------------------------------------------------*/
 
 #include "mercury_conf_param.h"
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.36
diff -u -r1.36 mercury_conf_param.h
--- runtime/mercury_conf_param.h	2000/04/05 06:28:55	1.36
+++ runtime/mercury_conf_param.h	2000/06/28 12:58:31
@@ -345,8 +345,48 @@
   #define MR_CAN_GET_PC_AT_SIGNAL
 #endif
 
-#if defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)
+/*
+** MR_CHECK_OVERFLOW_VIA_MPROTECT  --	Can check for overflow of various
+**					memory zones using mprotect() like
+**					functionality.
+*/
+#if (defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)) || defined(_WIN32)
   #define MR_CHECK_OVERFLOW_VIA_MPROTECT
+#endif
+
+/*
+** MR_PROTECTPAGE   -- 	MR_protect_pages() can be defined to provide the same
+**			functionality as the system call mprotect().
+*/
+#if defined(HAVE_MPROTECT) || defined(_WIN32)
+  #define MR_PROTECTPAGE
+#endif
+
+/*
+** MR_MSVC_STRUCTURED_EXCEPTIONS
+** 	Use Microsoft Visual C structured exceptions for signal handling.
+*/
+#if defined(_MSC_VER)
+  #define MR_MSVC_STRUCTURED_EXCEPTIONS
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** Win32 API specific.
+*/
+
+/*
+** MR_WIN32 -- The Win32 API is available.
+**
+** MR_WIN32_GETSYSTEMINFO -- Is GetSystemInfo() available?
+**
+** MR_WIN32_VIRTUAL_ALLOC -- Is VirtualAlloc() available?
+*/
+#if _WIN32
+  #define MR_WIN32
+  #define MR_WIN32_GETSYSTEMINFO
+  #define MR_WIN32_VIRTUAL_ALLOC
 #endif
 
 /*---------------------------------------------------------------------------*/
Index: runtime/mercury_memory.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.c,v
retrieving revision 1.18
diff -u -r1.18 mercury_memory.c
--- runtime/mercury_memory.c	2000/06/08 07:59:04	1.18
+++ runtime/mercury_memory.c	2000/06/28 12:58:33
@@ -96,7 +96,19 @@
 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
   #define	getpagesize()	sysconf(_SC_PAGESIZE)
 #elif !defined(HAVE_GETPAGESIZE)
-  #define	getpagesize()	8192
+  #if defined(MR_WIN32_GETSYSTEMINFO)
+    #include <windows.h>
+
+    static size_t
+    getpagesize(void)
+    {
+	SYSTEM_INFO SysInfo;
+	GetSystemInfo(&SysInfo);
+	return (size_t) SysInfo.dwPageSize;
+    }
+  #else
+    #define	getpagesize()	8192
+  #endif
 #endif
 
 /*---------------------------------------------------------------------------*/
Index: runtime/mercury_memory_handlers.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_handlers.c,v
retrieving revision 1.11
diff -u -r1.11 mercury_memory_handlers.c
--- runtime/mercury_memory_handlers.c	2000/06/08 07:59:04	1.11
+++ runtime/mercury_memory_handlers.c	2000/06/28 12:58:37
@@ -132,7 +132,7 @@
 static bool 
 try_munprotect(void *addr, void *context)
 {
-#ifndef HAVE_SIGINFO
+#if !(defined(HAVE_SIGINFO) || defined(MR_WIN32))
 	return FALSE;
 #else
 	Word *    fault_addr;
@@ -221,8 +221,8 @@
 	    zone->name, zone->id, (void *) zone->redzone, (void *) new_zone,
 	    (int)zone_size);
 	}
-	if (mprotect((char *)zone->redzone, zone_size,
-	    PROT_READ|PROT_WRITE) < 0)
+	if (MR_protect_pages((char *)zone->redzone, zone_size,
+		PROT_READ|PROT_WRITE) < 0)
 	{
 	    char buf[2560];
 	    sprintf(buf, "Mercury runtime: cannot unprotect %s#%d zone",
@@ -262,12 +262,19 @@
 void
 setup_signals(void)
 {
-#ifdef SIGBUS
+/*
+** When using Microsoft Visual C structured exceptions don't set any
+** signal handlers.
+** See mercury_wrapper.c for the reason why.
+*/
+#ifndef MR_MSVC_STRUCTURED_EXCEPTIONS
+  #ifdef SIGBUS
 	MR_setup_signal(SIGBUS, (Code *) bus_handler, TRUE,
 		"Mercury runtime: cannot set SIGBUS handler");
-#endif
+  #endif
 	MR_setup_signal(SIGSEGV, (Code *) segv_handler, TRUE,
 		"Mercury runtime: cannot set SIGSEGV handler");
+#endif
 }
 
 static char *
@@ -547,6 +554,281 @@
 }
 
 #endif /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
+
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+static const char *MR_find_exception_name(DWORD exception_code);
+static void MR_explain_exception_record(EXCEPTION_RECORD *rec);
+static void MR_dump_exception_record(EXCEPTION_RECORD *rec);
+static bool MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+		void **address_ptr, int *access_mode_ptr);
+
+/*
+** Exception code and their string representation
+*/
+#define DEFINE_EXCEPTION_NAME(a)   {a,#a}
+
+typedef struct
+{
+	DWORD		exception_code;
+	const char	*exception_name;
+} MR_ExceptionName;
+
+static const
+MR_ExceptionName MR_exception_names[] =
+{
+	DEFINE_EXCEPTION_NAME(EXCEPTION_ACCESS_VIOLATION),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_DATATYPE_MISALIGNMENT),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_BREAKPOINT),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_SINGLE_STEP),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_DENORMAL_OPERAND),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_DIVIDE_BY_ZERO),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_INEXACT_RESULT),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_INVALID_OPERATION),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_OVERFLOW),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_STACK_CHECK),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_FLT_UNDERFLOW),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_INT_DIVIDE_BY_ZERO),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_INT_OVERFLOW),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_PRIV_INSTRUCTION),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_IN_PAGE_ERROR),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_ILLEGAL_INSTRUCTION),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_NONCONTINUABLE_EXCEPTION),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_STACK_OVERFLOW),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_INVALID_DISPOSITION),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_GUARD_PAGE),
+	DEFINE_EXCEPTION_NAME(EXCEPTION_INVALID_HANDLE)
+};
+
+
+/*
+** Retrieve the name of a Win32 exception code as a string
+*/
+static const char *
+MR_find_exception_name(DWORD exception_code)
+{
+	int i;
+	for (i = 0; i < sizeof(MR_exception_names)
+			/ sizeof(MR_ExceptionName); i++)
+	{
+		if (MR_exception_names[i].exception_code == exception_code) {
+			return MR_exception_names[i].exception_name;
+		}
+	}
+	return "Unknown exception code";
+}
+
+/*
+** symbolic constants for these alternatives.
+*/
+#define READ	0
+#define WRITE	1
+
+/*
+** Explain an EXCEPTION_RECORD content into stderr.
+*/
+static void
+MR_explain_exception_record(EXCEPTION_RECORD *rec)
+{
+	fprintf(stderr, "\n");
+	fprintf(stderr, "\n*** Explanation of the exception record");
+	if (rec == NULL) {
+		fprintf(stderr, "\n***   Cannot explain because it is NULL");
+		return;
+	} else {
+		void *address;
+		int access_mode;
+		
+		/* If the exception is an access violation */
+		if (MR_exception_record_is_access_violation(rec,
+					&address, &access_mode))
+		{
+			MemoryZone *zone;
+
+			/* Display AV address and access mode */
+			fprintf(stderr, "\n***   An access violation occured"
+					" at address 0x%08lx, while attempting"
+					" to ", (unsigned long) address);
+			
+			if (access_mode == READ) {
+				fprintf(stderr, "\n***   read "
+						"inaccessible data");
+			} else if (access_mode == WRITE) {
+				fprintf(stderr, "\n***   write to an "
+						"inaccessible (or protected)"
+						" address");
+			} else {
+						"mode %d (strange...)]",
+						access_mode);
+			}
+				
+			fprintf(stderr, "\n***   Trying to see if this "
+					"stands within a mercury zone...");
+			/*
+			** Browse the mercury memory zones to see if the
+			** AV address references one of them.
+			*/
+			zone = get_used_memory_zones();
+			while(zone != NULL) {
+				fprintf(stderr,
+						"\n***    Checking zone %s#%d: "
+						"0x%08lx - 0x%08lx - 0x%08lx",
+						zone->name, zone->id,
+						(unsigned long) zone->bottom,
+						(unsigned long) zone->redzone,
+						(unsigned long) zone->top);
+
+				if ((zone->redzone <= address) &&
+						(address <= zone->top))
+				{
+					fprintf(stderr,
+						"\n***     Address is within"
+						" redzone of "
+						"%s#%d (!!zone overflowed!!)\n",
+						zone->name, zone->id);
+				} else if ((zone->bottom <= address) &&
+						(address <= zone->top))
+				{
+					fprintf(stderr, "\n***     Address is"
+							" within zone %s#%d\n",
+							zone->name, zone->id);
+				}
+				/*
+				** Don't need to call handler, because it
+				** has much less information than we do.
+				*/
+				/* return zone->handler(fault_addr,
+				 		zone, rec); */
+				zone = zone->next;
+			}
+		}
+		return;
+	}
+}
+
+/*
+** Dump an EXCEPTION_RECORD content into stderr.
+*/
+static void
+MR_dump_exception_record(EXCEPTION_RECORD *rec)
+{
+	int i;
+	
+	if (rec == NULL) {
+		return;
+	}
+	
+	fprintf(stderr, "\n***   Exception record at 0x%08lx:",
+			(unsigned long) rec);
+	fprintf(stderr, "\n***    Code        : 0x%08lx (%s)",
+			(unsigned long) rec->ExceptionCode,
+			MR_find_exception_name(rec->ExceptionCode));
+	fprintf(stderr, "\n***    Flags       : 0x%08lx",
+			(unsigned long) rec->ExceptionFlags);
+	fprintf(stderr, "\n***    Address     : 0x%08lx",
+			(unsigned long) rec->ExceptionAddress);
+
+	for (i = 0; i < rec->NumberParameters; i++) {
+		fprintf(stderr, "\n***    Parameter %d : 0x%08lx", i,
+				(unsigned long) rec->ExceptionInformation[i]);
+	}
+	fprintf(stderr, "\n***    Next record : 0x%08lx",
+			(unsigned long) rec->ExceptionRecord);
+	
+	/* Try to explain the exception more "gracefully" */
+	MR_explain_exception_record(rec);
+	MR_dump_exception_record(rec->ExceptionRecord);
+}
+
+
+/*
+** Return TRUE iff exception_ptrs indicates an access violation.
+** If TRUE, the dereferenced address_ptr is set to the accessed address and
+** the dereferenced access_mode_ptr is set to the desired access
+** (0 = read, 1 = write)
+*/
+static bool
+MR_exception_record_is_access_violation(EXCEPTION_RECORD *rec,
+		void **address_ptr, int *access_mode_ptr)
+{
+	if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+		if (rec->NumberParameters >= 2) {
+			(*access_mode_ptr) = (int) rec->ExceptionInformation[0];
+			(*address_ptr) = (void *) rec->ExceptionInformation[1];
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+
+/*
+** Filter a Win32 exception (to be called in the __except filter part).
+** Possible return values are:
+**
+** EXCEPTION_CONTINUE_EXECUTION (-1)
+**  Exception is dismissed. Continue execution at the point where
+**  the exception occurred.
+**
+** EXCEPTION_CONTINUE_SEARCH (0)
+**  Exception is not recognized. Continue to search up the stack for
+**  a handler, first for containing try-except statements, then for
+**  handlers with the next highest precedence.
+**
+** EXCEPTION_EXECUTE_HANDLER (1)
+**  Exception is recognized. Transfer control to the exception handler
+**  by executing the __except compound statement, then continue
+**  execution at the assembly instruction that was executing
+**  when the exception was raised. 
+*/
+int
+MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs)
+{
+	void *address;
+	int access_mode;
+
+		/* If the exception is an access violation */
+	if (MR_exception_record_is_access_violation(
+			exception_ptrs->ExceptionRecord,
+			&address, &access_mode))
+	{
+
+			/* If we can unprotect the memory zone */
+		if (try_munprotect(address, exception_ptrs)) {
+			if (MR_memdebug) {
+				fprintf(stderr, "returning from "
+						"signal handler\n\n");
+			}
+				/* Continue execution where it stopped */
+			return  EXCEPTION_CONTINUE_EXECUTION;
+		}
+	}
+		
+	/*
+	** We can't handle the exception. Just dump all the information we got
+	*/
+	fflush(stdout);
+	fprintf(stderr, "\n*** Mercury runtime: Unhandled exception ");
+	MR_dump_exception_record(exception_ptrs->ExceptionRecord);
+
+	print_dump_stack();
+	dump_prev_locations();
+	
+	fprintf(stderr, "\n\n*** Now passing exception to default handler\n\n");
+	fflush(stderr);
+		  
+	/*
+	** Pass exception back to upper handler. In most cases, this
+	** means activating UnhandledExceptionFilter, which will display
+	** a dialog box asking to user ro activate the Debugger or simply
+	** to kill the application
+	*/
+	return  EXCEPTION_CONTINUE_SEARCH;
+}
+#endif /* MR_MSVC_STRUCTURED_EXCEPTIONS */
+
 
 /*
 ** get_pc_from_context:
Index: runtime/mercury_memory_handlers.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_handlers.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_memory_handlers.h
--- runtime/mercury_memory_handlers.h	1998/05/14 06:35:09	1.2
+++ runtime/mercury_memory_handlers.h	2000/06/28 12:58:37
@@ -37,4 +37,30 @@
 
 void	setup_signals(void);
 
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+/*
+** Filter a Win32 exception (to be called in the __except filter
+** part).
+** Possible return values are:
+**
+** EXCEPTION_CONTINUE_EXECUTION (-1)
+**  Exception is dismissed. Continue execution at the point where
+**  the exception occurred.
+**
+** EXCEPTION_CONTINUE_SEARCH (0)
+**  Exception is not recognized. Continue to search up the stack for
+**  a handler, first for containing try-except statements, then for
+**  handlers with the next highest precedence.
+**
+** EXCEPTION_EXECUTE_HANDLER (1)
+**  Exception is recognized. Transfer control to the exception handler
+**  by executing the __except compound statement, then continue
+**  execution at the assembly instruction that was executing
+**  when the exception was raised. 
+*/
+#include <windows.h>
+
+int MR_filter_win32_exception(LPEXCEPTION_POINTERS exception_ptrs);
+#endif
+
 #endif /* not MERCURY_MEMORY_HANDLERS_H */
Index: runtime/mercury_memory_zones.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
retrieving revision 1.10
diff -u -r1.10 mercury_memory_zones.c
--- runtime/mercury_memory_zones.c	2000/06/08 07:59:05	1.10
+++ runtime/mercury_memory_zones.c	2000/06/28 12:58:39
@@ -51,9 +51,86 @@
   #include "mercury_thread.h"
 #endif
 
+#ifdef MR_WIN32_VIRTUAL_ALLOC
+  #include <windows.h>
+#endif
+
 /*---------------------------------------------------------------------------*/
+
+/*
+** MR_PROTECTPAGE is now defined if we have some sort of mprotect like
+** functionality, all checks for HAVE_MPROTECT should now use MR_PROTECTPAGE.
+*/
+#if defined(HAVE_MPROTECT)
+int
+MR_protect_pages(void *Addr, size_t Size, int ProtFlags)
+{
+	return mprotect((char *)Addr, Size, ProtFlags);
+}
+#elif defined(MR_WIN32_VIRTUAL_ALLOC)
+/*
+** Emulate mprotect under Win32.
+** Return -1 on failure
+*/
+int
+MR_protect_pages(void *addr, size_t size, int prot_flags)
+{
+	int rc;
+	DWORD Flags, OldFlags;
+
+	if (prot_flags & PROT_WRITE) {
+		Flags = PAGE_READWRITE;
+	} else if (prot_flags & PROT_READ) {
+		Flags = PAGE_READONLY;
+	} else {
+		Flags = PAGE_NOACCESS;
+	}
+	
+	if (rc < 0) {
+		fprintf(stderr,
+			"Error in VirtualProtect(addr=0x%08lx, size=0x%08lx):"
+			" 0x%08lx\n", (unsigned long) addr,
+			(unsigned long) size, (unsigned long) GetLastError());
+	}
+
+	return rc;
+}
+#endif	/* MR_WIN32_VIRTUAL_ALLOC */
+
 
-#ifdef	CONSERVATIVE_GC
+/*---------------------------------------------------------------------------*/
+
+
+#if defined(MR_WIN32_VIRTUAL_ALLOC)
+/*
+** Under Win32, we use VirtualAlloc instead of the standard malloc,
+** since we will have to call VirtualProtect later on the pages
+** allocated here.
+*/
+void *
+memalign(size_t unit, size_t size)
+{
+	void *ptr;
+
+	/*
+	** We don't need to use the 'unit' value as the memory is always
+	** aligned under Win32.
+	*/
+	ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
+	if (ptr == NULL) {
+		fprintf(stderr, "Error in VirtualAlloc(size=0x%08lx):"
+				" 0x%08lx\n", (unsigned long) size,
+				(unsigned long) GetLastError());
+	}
+
+  #ifdef CONSERVATIVE_GC
+	if (ptr != NULL)
+		GC_add_roots((char *)ptr, (char *)ptr + size);
+  #endif
+	return ptr;
+}
+#elif defined(CONSERVATIVE_GC)
   #define	memalign(a,s)   GC_MALLOC_UNCOLLECTABLE(s)
 #elif defined(HAVE_MEMALIGN)
   extern void	*memalign(size_t, size_t);
@@ -74,7 +151,7 @@
 ** PROT_EXEC    page can be executed
 ** PROT_NONE    page can not be accessed
 */
-#ifdef  HAVE_MPROTECT
+#ifdef MR_PROTECTPAGE
 
   #ifdef CONSERVATIVE_GC
     /*
@@ -94,7 +171,7 @@
     #define PROT_NONE 0
   #endif
 
-#endif /* HAVE_MPROTECT */
+#endif /* MR_PROTECTPAGE */
 
 /*---------------------------------------------------------------------------*/
 
@@ -256,13 +333,13 @@
 		**	unit		(an extra page for protection if
 		**			 mprotect is being used)
 		*/
-#ifdef	HAVE_MPROTECT
+#ifdef	MR_PROTECTPAGE
 	total_size = size + 2 * unit;
 #else
 	total_size = size + unit;
 #endif
 
-	base = memalign(unit, total_size);
+	base = (Word *) memalign(unit, total_size);
 	if (base == NULL) {
 		char buf[2560];
 		sprintf(buf, "unable allocate memory zone: %s#%d", name, id);
@@ -295,11 +372,11 @@
 
 	zone->bottom = base;
 
-#ifdef 	HAVE_MPROTECT
+#ifdef 	MR_PROTECTPAGE
 	total_size = size + unit;
 #else
 	total_size = size;
-#endif	/* HAVE_MPROTECT */
+#endif	/* MR_PROTECTPAGE */
 
 	zone->top = (Word *) ((char *)base + total_size);
 	zone->min = (Word *) ((char *)base + offset);
@@ -313,7 +390,9 @@
 #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
 	zone->redzone_base = zone->redzone = (Word *)
 			round_up((Unsigned)base + size - redsize, unit);
-	if (mprotect((char *)zone->redzone, redsize + unit, MY_PROT) < 0) {
+	if (MR_protect_pages((char *)zone->redzone,
+			redsize + unit, MY_PROT) < 0)
+	{
 		char buf[2560];
 		sprintf(buf, "unable to set %s#%d redzone\n"
 			"base=%p, redzone=%p",
@@ -325,9 +404,9 @@
 	/*
 	** setup the hardzone
 	*/
-#if	defined(HAVE_MPROTECT)
+#if	defined(MR_PROTECTPAGE)
 	zone->hardmax = (Word *) round_up((Unsigned)zone->top - unit, unit);
-	if (mprotect((char *)zone->hardmax, unit, MY_PROT) < 0) {
+	if (MR_protect_pages((char *)zone->hardmax, unit, MY_PROT) < 0) {
 		char buf[2560];
 		sprintf(buf, "unable to set %s#%d hardmax\n"
 			"base=%p, hardmax=%p top=%p",
@@ -335,7 +414,7 @@
 			zone->top);
 		fatal_error(buf);
 	}
-#endif	/* HAVE_MPROTECT */
+#endif	/* MR_PROTECTPAGE */
 
 
 	return zone;
@@ -347,9 +426,8 @@
 #ifdef	MR_CHECK_OVERFLOW_VIA_MPROTECT
 	zone->redzone = zone->redzone_base;
 
-	if (mprotect((char *)zone->redzone,
-		((char *)zone->top) - ((char *) zone->redzone), MY_PROT) < 0)
-	{
+	if (MR_protect_pages((char *)zone->redzone,
+		((char *)zone->top) - ((char *) zone->redzone), MY_PROT) < 0) {
 		char buf[2560];
 		sprintf(buf, "unable to reset %s#%d redzone\n"
 			"base=%p, redzone=%p",
@@ -397,7 +475,7 @@
 		fprintf(stderr, "%-16s#%d-redzone_base	= %p\n",
 			zone->name, zone->id, (void *) zone->redzone_base);
 #endif	/* MR_CHECK_OVERFLOW_VIA_MPROTECT */
-#ifdef	HAVE_MPROTECT
+#ifdef	MR_PROTECTPAGE
 		fprintf(stderr, "%-16s#%d-hardmax		= %p\n",
 			zone->name, zone->id, (void *) zone->hardmax);
 		fprintf(stderr, "%-16s#%d-size		= %lu\n",
@@ -407,7 +485,7 @@
 		fprintf(stderr, "%-16s#%d-size		= %lu\n",
 			zone->name, zone->id, (unsigned long)
 			((char *)zone->top - (char *)zone->min));
-#endif	/* HAVE_MPROTECT */
+#endif	/* MR_PROTECTPAGE */
 		fprintf(stderr, "\n");
 	}
 }
Index: runtime/mercury_memory_zones.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_memory_zones.h
--- runtime/mercury_memory_zones.h	1999/10/05 20:21:41	1.5
+++ runtime/mercury_memory_zones.h	2000/06/28 12:58:41
@@ -101,10 +101,10 @@
 	Word	*max;		/* highest word of the area to be used;
 				   computed only if MR_LOWLEVEL_DEBUG is
 				   enabled */
-#ifdef HAVE_MPROTECT
+#ifdef MR_PROTECTPAGE
 	Word	*hardmax;	/* last page of the zone which can't be
 				   unprotected */
-#endif	/* HAVE_MPROTECT */
+#endif	/* MR_PROTECTPAGE */
 #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
 	Word	*redzone_base;	/* beginning of the original redzone */
 	Word	*redzone;	/* beginning of the current redzone */
@@ -118,7 +118,7 @@
 	*/
 #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
 	#define MR_zone_end	redzone
-#elif defined(HAVE_MPROTECT)
+#elif defined(MR_PROTECTPAGE)
 	#define MR_zone_end	hardmax
 #else
 	#define MR_zone_end	top
@@ -137,6 +137,27 @@
 		(char*)((zone)->MR_zone_end) - (char *)(start_address)))
 
 /*
+** Rather then using mprotect directly, we call MR_protect_pages which
+** is OS independent.
+*/
+#ifdef MR_PROTECTPAGE
+
+  #ifdef MR_WIN32
+    #ifndef PROT_NONE
+      #define PROT_NONE  0x0000
+    #endif
+    #ifndef PROT_READ
+      #define PROT_READ  0x0001
+    #endif
+    #ifndef PROT_WRITE
+      #define PROT_WRITE 0x0002
+    #endif
+  #endif
+
+int MR_protect_pages(void *addr, size_t size, int prot_flags);
+#endif
+
+/*
 ** init_memory_arena() allocates (if necessary) the top-level memory pool
 ** from which all allocations should come. If PARALLEL is defined, then
 ** this pool should be shared memory. In the absence of PARALLEL, it
@@ -175,7 +196,7 @@
 ** construct_zone(Name, Id, Base, Size, Offset, RedZoneSize, FaultHandler)
 ** has the same behaviour as create_zone, except instread of allocating
 ** the memory, it takes a pointer to a region of memory that must be at
-** least Size + unit[*] bytes, or if HAVE_MPROTECT is defined, then it
+** least Size + unit[*] bytes, or if MR_PROTECTPAGE is defined, then it
 ** must be at least Size + 2 * unit[*] bytes.
 ** If it fails to protect the redzone then it exits.
 ** If MR_CHECK_OVERFLOW_VIA_MPROTECT is unavailable, then the last two
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.62
diff -u -r1.62 mercury_wrapper.c
--- runtime/mercury_wrapper.c	2000/06/08 07:59:06	1.62
+++ runtime/mercury_wrapper.c	2000/06/28 12:58:45
@@ -32,6 +32,10 @@
 #include	<stdio.h>
 #include	<string.h>
 
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+  #include <excpt.h>
+#endif
+
 #include	"mercury_getopt.h"
 #include	"mercury_timing.h"
 #include	"mercury_init.h"
@@ -894,6 +898,30 @@
 
 	static	int	repcounter;
 
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+	/*
+	** Under Win32 we use the following construction to handle exceptions.
+	**   __try
+	**   {
+	**     <various stuff>
+	**   }
+	**   __except(MR_filter_win32_exception(GetExceptionInformation())
+	**   {
+	**   }
+	**
+	** This type of contruction allows us to retrieve all the information
+	** we need (exception type, address, etc) to display a "meaningful"
+	** message to the user.  Using signal() in Win32 is less powerful,
+	** since we can only trap a subset of all possible exceptions, and
+	** we can't retrieve the exception address.  The VC runtime implements
+	** signal() by surrounding main() with a __try __except block and
+	** calling the signal handler in the __except filter, exactly the way
+	** we do it here.
+	*/
+	__try
+	{
+#endif
+
 	/*
 	** Save the C callee-save registers
 	** and restore the Mercury registers
@@ -989,6 +1017,14 @@
 	*/
 	save_registers();
 	restore_regs_from_mem(c_regs);
+
+#ifdef MR_MSVC_STRUCTURED_EXCEPTIONS
+	}
+	__except(MR_filter_win32_exception(GetExceptionInformation()))
+	{
+		/* Everything is done in MR_filter_win32_exception */
+	}
+#endif
 
 } /* end mercury_runtime_main() */
 

--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list