gcl-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gcl-devel] Runtime SGC fault address recovery tests


From: Camm Maguire
Subject: [Gcl-devel] Runtime SGC fault address recovery tests
Date: 11 Feb 2004 17:34:18 -0500
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2

Greetings!  In preparing for the 2.6.2 stable release, it has become
apparent that two more supported architectures are now capable of
using the SGC garbage collection optimization algorithm -- hppa and
arm. 

I've received email from a Debian hppa kernel contributor who tells me
that the situation may vary by kernel version, and 64bit/32bit
kernel/user combination.  In general, we've been rather loose about
enabling SGC at compile time and turning a blind eye to whether it
works in the runtime environment.  This has become more evident as
libc6.1 on Debian alpha has just developed a bug which prevents the
signal handling mechanism used by SGC to return to the same code
address as initiated the fault after the handler has completed.
Previously build acl2 on this platform now (temporarily, I'm sure)
fails to execute as SGC was turned on and saved in the image, which
worked flawlessly at compile time, but not now at runtime.

I have a patch which implements a runtime test of the SGC fault
address recovery mechanism on image startup.  If any of a number of
failures appear, a diagnostic message is printed indicating why sgc is
being disabled, and, if recovery from the test failure is possible,
sgc is turned off and prevented from being turned on as long as the
image is being run.  The test is only run when sgc is compiled in and
is attempted to be enabled, or on image startup if the image was saved
with sgc enabled.  The test is only run once per image invocation.  

I'm leaning toward getting this in the stable branch after thorough
testing, as I think it will significantly diminish possible
inexplicable error reports throughout the lifetime of 2.6.2.  In any
case, comments/tests welcome.  Here is the patch:

Index: h/protoize.h
===================================================================
RCS file: /cvsroot/gcl/gcl/h/protoize.h,v
retrieving revision 1.26.4.1.2.1.2.4
diff -u -b -r1.26.4.1.2.1.2.4 protoize.h
--- h/protoize.h        2 Dec 2003 14:57:09 -0000       1.26.4.1.2.1.2.4
+++ h/protoize.h        11 Feb 2004 21:44:08 -0000
@@ -1747,6 +1747,12 @@
 void *
 gcl_gmp_alloc(size_t);
 
+#ifdef SGC
+void
+memprotect_test_reset(void);
+#endif
+
+
 #if defined (__MINGW32__)
 int bcmp ( const void *s1, const void *s2, size_t n );
 void bcopy ( const void *s1, void *s2, size_t n );
Index: o/main.c
===================================================================
RCS file: /cvsroot/gcl/gcl/o/main.c,v
retrieving revision 1.26.4.1.2.6
diff -u -b -r1.26.4.1.2.6 main.c
--- o/main.c    12 Nov 2003 15:41:35 -0000      1.26.4.1.2.6
+++ o/main.c    11 Feb 2004 21:44:09 -0000
@@ -284,6 +284,9 @@
 #endif 
 #endif 
        
+#ifdef SGC
+       memprotect_test_reset();
+#endif
 
        if (initflag) {
                if (saving_system) {
Index: o/sgbc.c
===================================================================
RCS file: /cvsroot/gcl/gcl/o/sgbc.c,v
retrieving revision 1.9.4.1.2.3
diff -u -b -r1.9.4.1.2.3 sgbc.c
--- o/sgbc.c    12 Nov 2003 15:41:36 -0000      1.9.4.1.2.3
+++ o/sgbc.c    11 Feb 2004 21:44:09 -0000
@@ -1035,6 +1035,134 @@
 
 #endif   
 
+typedef enum {memprotect_none,memprotect_cannot_protect,memprotect_sigaction,
+             memprotect_bad_return,memprotect_no_signal,
+             memprotect_multiple_invocations,memprotect_no_restart,
+             memprotect_bad_fault_address,memprotect_success} memprotect_enum;
+static memprotect_enum memprotect_result;
+static int memprotect_handler_invocations,memprotect_print_enable;
+static void *memprotect_test_address;
+
+#define MEM_ERR_CASE(a_) \
+  case a_: \
+    fprintf(stderr,"The SGC segfault recovery test failed with %s, SGC 
disabled\n",#a_); \
+    break
+
+static void
+memprotect_print(void) {
+
+  if (!memprotect_print_enable)
+    return;
+
+  switch(memprotect_result) {
+  case memprotect_none: case memprotect_success:
+    break;
+
+    MEM_ERR_CASE(memprotect_cannot_protect);
+    MEM_ERR_CASE(memprotect_sigaction);
+    MEM_ERR_CASE(memprotect_bad_return);
+    MEM_ERR_CASE(memprotect_no_signal);
+    MEM_ERR_CASE(memprotect_no_restart);
+    MEM_ERR_CASE(memprotect_bad_fault_address);
+    MEM_ERR_CASE(memprotect_multiple_invocations);
+
+  }
+
+}
+
+
+static void
+memprotect_handler_test(int sig, long code, void *scp, char *addr) {
+
+  char *faddr;
+  faddr=GET_FAULT_ADDR(sig,code,scp,addr); 
+
+  if (memprotect_handler_invocations) {
+    memprotect_result=memprotect_multiple_invocations;
+    exit(-1);
+  }
+  memprotect_handler_invocations=1;
+  if (faddr!=memprotect_test_address)
+    memprotect_result=memprotect_bad_fault_address;
+  else
+    memprotect_result=memprotect_none;
+  mprotect(memprotect_test_address,PAGESIZE,PROT_READ|PROT_WRITE);
+
+}
+
+static int
+memprotect_test(void) {
+
+  char b1[2*PAGESIZE],b2[PAGESIZE];
+  struct sigaction sa,sao;
+
+  if (memprotect_result!=memprotect_none)
+    return memprotect_result!=memprotect_success;
+  if (atexit(memprotect_print)) {
+    fprintf(stderr,"Cannot setup memprotect_print on exit\n");
+    exit(-1);
+  }
+
+  memset(b1,32,sizeof(b1));
+  memset(b2,0,sizeof(b2));
+  memprotect_test_address=(void *)(((unsigned long)b1+PAGESIZE-1) & 
~(PAGESIZE-1));
+  if (mprotect(memprotect_test_address,PAGESIZE,PROT_READ)) {
+    memprotect_result=memprotect_cannot_protect;
+    return -1;
+  }
+  sa.sa_sigaction=(void *)memprotect_handler_test;
+  sa.sa_flags=MPROTECT_ACTION_FLAGS;
+  if (sigaction(SIGSEGV,&sa,&sao)) {
+    memprotect_result=memprotect_sigaction;
+    return -1;
+  }
+  memprotect_result=memprotect_bad_return;
+  memset(memprotect_test_address,0,PAGESIZE);
+  if (memprotect_result==memprotect_bad_return)
+    memprotect_result=memprotect_no_signal;
+  if (memprotect_result!=memprotect_none) {
+    sigaction(SIGSEGV,&sao,NULL);
+    return -1;
+  }
+  if (memcmp(memprotect_test_address,b2,PAGESIZE)) {
+    memprotect_result=memprotect_no_restart;
+    sigaction(SIGSEGV,&sao,NULL);
+    return -1;
+  }
+  memprotect_result=memprotect_success;
+  sigaction(SIGSEGV,&sao,NULL);
+  return 0;
+
+}
+
+static int
+do_memprotect_test(void) {
+
+  int rc=0;
+
+  memprotect_print_enable=1;
+  if (memprotect_test()) {
+    memprotect_print();
+    if (sgc_enabled)
+      sgc_quit();
+    rc=-1;
+  }
+  memprotect_print_enable=0;
+  return rc;
+
+}
+
+void
+memprotect_test_reset(void) {
+
+  memprotect_result=memprotect_none;
+  memprotect_handler_invocations=0;
+  memprotect_test_address=NULL;
+
+  if (sgc_enabled)
+    do_memprotect_test();
+
+}
+
 int
 sgc_start(void) {
 
@@ -1044,6 +1172,10 @@
   object f;
   struct typemanager *tm;
   int npages;
+
+  if (memprotect_result!=memprotect_success && do_memprotect_test())
+    return 0;
+
   if (sgc_type_map[page((&sgc_type_map[0]))] != SGC_PERM_WRITABLE)
     perm_writable(&sgc_type_map[0],sizeof(sgc_type_map));
   if (sgc_enabled)
@@ -1567,7 +1699,8 @@
   check_arg(1);
   if(vs_base[0]==Cnil) 
     sgc_quit();
-  else sgc_start();
+  else 
+    vs_base[0]=sgc_start() ? Ct : Cnil;
 }
 
 /* make permanently writable pages containing pointers p thru p+n-1 */



-- 
Camm Maguire                                            address@hidden
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah




reply via email to

[Prev in Thread] Current Thread [Next in Thread]