We use Guile on a number of platforms, including HP-UX 11.23 on Itanium. While Guile seems to build on IA64 HPUX, it crashes while running because of GC failing to mark some objects reachable through the stack.
There are three distinct problems that require attention: 1. The checks for __ia64__ don't work on HPUX because its compilers set __ia64, not __ia64__. 2. The GC code under #ifdef __ia64__ accesses Linux-specific fields of ucontext_t and the Linux-specific variable __libc_ia64_register_backing_store_base. 3. The implementation of continuations under IA64 Linux makes use of a non-standard and (to the best of my knowledge) undocumented extension to getcontext. It declares getcontext to return two values, and uses the second one to determine whether the code after getcontext is executed linearly or as a result to a call to setcontext. The first problem can be solved by either changing the ifdefs, or by #definining __ia64__ if defined(__ia64) && !defined(__ia64__). That's the easy one. The second problem can be solved by using the libuca library on HPUX to retrieve the Itanium-specific fields of the opaque ucontext_t structure. This requires a change to configure to detect libuca, but the change is trivial, since libuca is a "system library", therefore not requiring special link magic. As for __libc_ia64_register_backing_store_base, its HPUX equivalent can be retrieved using the `pstat_getprocvm', as is done in the Boehm collector. The third issue requires the addition of a simple boolean field to scm_t_contregs, which make_continuation uses to keep track of whether the context was reached by setcontext or by falling through the call to getcontext. As far as I can tell, the non-standard use of getcontext is really not necessary for this to work. Putting all this together, I assembled a patch which, when applied, should make Guile buildable on both IA64 HPUX and Linux, without affecting other architectures. After applying the patch, you will need to run autoconf and autoheader. Unfortunately the patch is for Guile 1.6.7 (which we use locally), but it should be trivial to port to 1.8.1 or 1.6.8.
diff -ru guile-1.6.7-orig/configure guile-1.6.7/configure --- guile-1.6.7-orig/configure.in 2004-08-27 04:16:31.000000000 +0200 +++ guile-1.6.7/configure.in 2006-10-25 15:33:15.000000000 +0200 @@ -220,6 +220,7 @@ if test $ac_cv_func_connect = no; then AC_CHECK_LIB(socket, connect) fi +AC_CHECK_LIB(uca, __uc_get_ar_bsp) # Check for dynamic linking diff -ru guile-1.6.7-orig/libguile/continuations.c guile-1.6.7/libguile/continuations.c --- guile-1.6.7-orig/libguile/continuations.c 2003-09-12 20:58:00.000000000 +0200 +++ guile-1.6.7/libguile/continuations.c 2006-10-25 16:06:30.000000000 +0200 @@ -114,15 +114,6 @@ return 1; } -#ifdef __ia64__ -struct rv -{ - long retval; - long first_return; -}; -extern struct rv ia64_getcontext (ucontext_t *) __asm__ ("getcontext"); -#endif /* __ia64__ */ - /* this may return more than once: the first time with the escape procedure, then subsequently with the value to be passed to the continuation. */ @@ -135,9 +126,6 @@ scm_t_contregs *rootcont = SCM_CONTREGS (scm_rootcont); long stack_size; SCM_STACKITEM * src; -#ifdef __ia64__ - struct rv rv; -#endif SCM_ENTER_A_SECTION; SCM_FLUSH_REGISTER_WINDOWS; @@ -162,19 +150,22 @@ memcpy (continuation->stack, src, sizeof (SCM_STACKITEM) * stack_size); #ifdef __ia64__ - rv = ia64_getcontext (&continuation->ctx); - if (rv.first_return) + continuation->fresh = 1; + getcontext (&continuation->ctx); + if (continuation->fresh) { - continuation->backing_store_size = - continuation->ctx.uc_mcontext.sc_ar_bsp - - __libc_ia64_register_backing_store_base; + continuation->backing_store_size = + (char *) scm_ia64_ar_bsp(&continuation->ctx) + - + (char *) scm_ia64_register_backing_store_base (); continuation->backing_store = NULL; continuation->backing_store = scm_must_malloc (continuation->backing_store_size, FUNC_NAME); memcpy (continuation->backing_store, - (void *) __libc_ia64_register_backing_store_base, + (void *) scm_ia64_register_backing_store_base (), continuation->backing_store_size); *first = 1; + continuation->fresh = 0; return cont; } else @@ -235,7 +226,7 @@ continuation->throw_value = val; #ifdef __ia64__ - memcpy ((void *) __libc_ia64_register_backing_store_base, + memcpy (scm_ia64_register_backing_store_base (), continuation->backing_store, continuation->backing_store_size); setcontext (&continuation->ctx); diff -ru guile-1.6.7-orig/libguile/continuations.h guile-1.6.7/libguile/continuations.h --- guile-1.6.7-orig/libguile/continuations.h 2003-09-12 20:58:00.000000000 +0200 +++ guile-1.6.7/libguile/continuations.h 2006-10-25 16:29:55.000000000 +0200 @@ -46,10 +46,8 @@ #include "libguile/__scm.h" #ifdef __ia64__ -#include <ucontext.h> -extern unsigned long __libc_ia64_register_backing_store_base; +# include <ucontext.h> #endif - /* a continuation SCM is a non-immediate pointing to a heap cell with: word 0: bits 0-15: smob type tag: scm_tc16_continuation. @@ -68,6 +66,7 @@ SCM dynenv; #ifdef __ia64__ ucontext_t ctx; + int fresh; void *backing_store; unsigned long backing_store_size; #endif /* __ia64__ */ diff -ru guile-1.6.7-orig/libguile/gc.c guile-1.6.7/libguile/gc.c --- guile-1.6.7-orig/libguile/gc.c 2004-09-11 17:54:23.000000000 +0200 +++ guile-1.6.7/libguile/gc.c 2006-10-25 16:37:15.000000000 +0200 @@ -53,11 +53,6 @@ #include <string.h> #include <assert.h> -#ifdef __ia64__ -#include <ucontext.h> -extern unsigned long __libc_ia64_register_backing_store_base; -#endif - #include "libguile/_scm.h" #include "libguile/eval.h" #include "libguile/stime.h" @@ -1034,15 +1029,15 @@ scm_t_c_hook scm_after_gc_c_hook; #ifdef __ia64__ -# define SCM_MARK_BACKING_STORE() do { \ - ucontext_t ctx; \ - SCM_STACKITEM * top, * bot; \ - getcontext (&ctx); \ - scm_mark_locations ((SCM_STACKITEM *) &ctx.uc_mcontext, \ - ((size_t) (sizeof (SCM_STACKITEM) - 1 + sizeof ctx.uc_mcontext) \ - / sizeof (SCM_STACKITEM))); \ - bot = (SCM_STACKITEM *) __libc_ia64_register_backing_store_base; \ - top = (SCM_STACKITEM *) ctx.uc_mcontext.sc_ar_bsp; \ +# define SCM_MARK_BACKING_STORE() do { \ + ucontext_t ctx; \ + SCM_STACKITEM * top, * bot; \ + getcontext (&ctx); \ + scm_mark_locations ((SCM_STACKITEM *) &ctx.uc_mcontext, \ + ((size_t) (sizeof (SCM_STACKITEM) - 1 + sizeof ctx.uc_mcontext) \ + / sizeof (SCM_STACKITEM))); \ + bot = (SCM_STACKITEM *) scm_ia64_register_backing_store_base (); \ + top = (SCM_STACKITEM *) scm_ia64_ar_bsp (&ctx); \ scm_mark_locations (bot, top - bot); } while (0) #else # define SCM_MARK_BACKING_STORE() @@ -2915,8 +2910,49 @@ #include "libguile/gc.x" } +#ifdef __ia64__ +# ifdef __hpux +# include <sys/param.h> +# include <sys/pstat.h> +void * +scm_ia64_register_backing_store_base (void) +{ + struct pst_vm_status vm_status; + int i = 0; + while (pstat_getprocvm (&vm_status, sizeof (vm_status), 0, i++) == 1) + if (vm_status.pst_type == PS_RSESTACK) + return (void *) vm_status.pst_vaddr; + abort (); +} +void * +scm_ia64_ar_bsp (const void *ctx) +{ + uint64_t bsp; + __uc_get_ar_bsp(ctx, &bsp); + return (void *) bsp; +} +# endif /* hpux */ +# ifdef linux +# include <ucontext.h> +void * +scm_ia64_register_backing_store_base (void) +{ + extern void *__libc_ia64_register_backing_store_base; + return __libc_ia64_register_backing_store_base; +} +void * +scm_ia64_ar_bsp (const void *opaque) +{ + ucontext_t *ctx = opaque; + return (void *) ctx->uc_mcontext.sc_ar_bsp; +} +# endif /* linux */ +#endif /* __ia64__ */ + #endif /*MARK_DEPENDENCIES*/ + + /* Local Variables: c-file-style: "gnu" diff -ru guile-1.6.7-orig/libguile/gc.h guile-1.6.7/libguile/gc.h --- guile-1.6.7-orig/libguile/gc.h 2004-09-11 17:54:23.000000000 +0200 +++ guile-1.6.7/libguile/gc.h 2006-10-25 16:01:42.000000000 +0200 @@ -395,6 +395,11 @@ extern void *scm_get_stack_base (void); extern void scm_init_gc (void); +#ifdef __ia64__ +void *scm_ia64_register_backing_store_base (void); +void *scm_ia64_ar_bsp (const void *); +#endif + #if (SCM_DEBUG_DEPRECATED == 0) diff -ru guile-1.6.7-orig/libguile/_scm.h guile-1.6.7/libguile/_scm.h --- guile-1.6.7-orig/libguile/_scm.h 2002-12-07 23:41:31.000000000 +0100 +++ guile-1.6.7/libguile/_scm.h 2006-10-25 16:06:49.000000000 +0200 @@ -57,6 +57,9 @@ should go in __scm.h. */ +#if defined(__ia64) && !defined(__ia64__) +# define __ia64__ +#endif /* Include headers for those files central to the implementation. The rest should be explicitly #included in the C files themselves. */
_______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel