[Top][All Lists]
[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
- RE: [Gcl-devel] Re: system, load-time-value, (continued)
- Re: [Gcl-devel] Re: system, load-time-value, Camm Maguire, 2004/02/16
- [Gcl-devel] Re: system, load-time-value, Debian User, 2004/02/17
- Re: [Gcl-devel] Re: system, load-time-value, Camm Maguire, 2004/02/17
- Re: [Gcl-devel] Re: system, load-time-value, Michael Koehne, 2004/02/17
- Re: [Gcl-devel] Re: system, load-time-value, Dennis Decker Jensen, 2004/02/17
- Re: [Gcl-devel] Re: system, load-time-value, Michael Koehne, 2004/02/17
[Gcl-devel] SGC and file I/O, Camm Maguire, 2004/02/11
[Gcl-devel] Runtime SGC fault address recovery tests,
Camm Maguire <=