From: Juho Snellman Date: Mon, 15 Jan 2007 22:15:48 +0000 (+0000) Subject: 1.0.1.28: Fix SBCL on PPC with 65k pages. X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;ds=sidebyside;h=4e5668af19abcf84587bf3f7a1c4294cd92c94a7;p=sbcl.git 1.0.1.28: Fix SBCL on PPC with 65k pages. It turns out that getpagesize() can return different values on different Linux kernel versions, for example on PPC where the ABI specifies the page size as 4k-65k. If getpagesize() and SB!C:*BACKEND-PAGE-SIZE* disagree, the result will be a segfault at startup. Fix this. (Thanks to David Woodhouse). * SB!SYS:GET-PAGE-SIZE and os_vm_page_size use the hardcoded SB!C:*BACKEND-PAGE-SIZE* on Linux, since getpagesize() is unreliable. * Remove the obsolete LISPOBJ() kludge in genesis for forcing values to unsigned. * Fix buffer overflow in coreparse for sufficiently small page tables. * Allow using 65k or gencgc pages (with a slightly less efficient page table structure layout). --- diff --git a/NEWS b/NEWS index b8adb5c..5be2eb0 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,8 @@ changes in sbcl-1.0.2 relative to sbcl-1.0.1: * bug fix: Win32 port can now handle foreign code unwinding Lisp stack frames from alien callbacks. * bug fix: ATANH returned incorrect results on win32 (thanks to Pierre Mai) + * bug fix: SBCL works on Linux/ppc systems with a kernel configured to use + 65k pages (thanks to David Woodhouse) changes in sbcl-1.0.1 relative to sbcl-1.0: * new platform: FreeBSD/x86-64, including support for threading. diff --git a/src/code/linux-os.lisp b/src/code/linux-os.lisp index 1e1e786..640320e 100644 --- a/src/code/linux-os.lisp +++ b/src/code/linux-os.lisp @@ -45,7 +45,4 @@ ;;; Return the system page size. (defun get-page-size () - ;; probably should call getpagesize() - ;; FIXME: Or we could just get rid of this, since the uses of it look - ;; disposable. - 4096) + sb!c:*backend-page-size*) \ No newline at end of file diff --git a/src/code/room.lisp b/src/code/room.lisp index 6102f23..6e0ed5a 100644 --- a/src/code/room.lisp +++ b/src/code/room.lisp @@ -207,7 +207,14 @@ (define-alien-type (struct page) (struct page (start long) - (bytes-used (unsigned 16)) + ;; On platforms with small enough GC pages, this field + ;; will be a short. On platforms with larger ones, it'll + ;; be an int. + (bytes-used (unsigned + #.(if (typep sb!vm:gencgc-page-size + '(unsigned-byte 16)) + 16 + 32))) (flags (unsigned 8)) (gen (signed 8)))) (declaim (inline find-page-index)) diff --git a/src/compiler/generic/genesis.lisp b/src/compiler/generic/genesis.lisp index 90c22bd..eb1ab4a 100644 --- a/src/compiler/generic/genesis.lisp +++ b/src/compiler/generic/genesis.lisp @@ -2728,22 +2728,17 @@ core and return a descriptor to it." (setf prev-priority priority)) (format t "#define ~A " name) (format t - ;; KLUDGE: As of sbcl-0.6.7.14, we're dumping two - ;; different kinds of values here, (1) small codes - ;; and (2) machine addresses. The small codes can be - ;; dumped as bare integer values. The large machine - ;; addresses might cause problems if they're large - ;; and represented as (signed) C integers, so we - ;; want to force them to be unsigned. We do that by - ;; wrapping them in the LISPOBJ macro. (We could do - ;; it with a bare "(unsigned)" cast, except that - ;; this header file is used not only in C files, but - ;; also in assembly files, which don't understand - ;; the cast syntax. The LISPOBJ macro goes away in - ;; assembly files, but that shouldn't matter because - ;; we don't do arithmetic on address constants in - ;; assembly files. See? It really is a kludge..) -- - ;; WHN 2000-10-18 + ;; KLUDGE: We're dumping two different kinds of + ;; values here, (1) small codes and (2) machine + ;; addresses. The small codes can be dumped as bare + ;; integer values. The large machine addresses might + ;; cause problems if they're large and represented + ;; as (signed) C integers, so we want to force them + ;; to be unsigned by appending an U to the + ;; literal. We can't dump all the values using the + ;; literal-U syntax, since the assembler doesn't + ;; support that syntax and some of the small + ;; constants can be used in assembler files. (let (;; cutoff for treatment as a small code (cutoff (expt 2 16))) (cond ((minusp value) @@ -2751,7 +2746,7 @@ core and return a descriptor to it." ((< value cutoff) "~D") (t - "LISPOBJ(~DU)"))) + "~DU"))) value) (format t " /* 0x~X */~@[ /* ~A */~]~%" value doc)))) (terpri)) @@ -2768,6 +2763,13 @@ core and return a descriptor to it." i))))) (terpri) + ;; I'm not really sure why this is in SB!C, since it seems + ;; conceptually like something that belongs to SB!VM. In any case, + ;; it's needed C-side. + (format t "#define BACKEND_PAGE_SIZE ~DU~%" sb!c:*backend-page-size*) + + (terpri) + ;; FIXME: The SPARC has a PSEUDO-ATOMIC-TRAP that differs between ;; platforms. If we export this from the SB!VM package, it gets ;; written out as #define trap_PseudoAtomic, which is confusing as diff --git a/src/compiler/ppc/backend-parms.lisp b/src/compiler/ppc/backend-parms.lisp index 9f061d6..ebaf637 100644 --- a/src/compiler/ppc/backend-parms.lisp +++ b/src/compiler/ppc/backend-parms.lisp @@ -3,5 +3,15 @@ (def!constant +backend-fasl-file-implementation+ :ppc) (setf *backend-register-save-penalty* 3) (setf *backend-byte-order* :big-endian) -(setf *backend-page-size* 4096) +(eval-when (:compile-toplevel :load-toplevel :execute) + ;; On Linux, the ABI specifies the page size to be 4k-65k, use the + ;; maximum of that range. FIXME: it'd be great if somebody would + ;; find out whether using exact multiples of the page size actually + ;; matters in the few places where that's done, or whether we could + ;; just use 4k everywhere. + (setf *backend-page-size* #!+linux 65536 #!-linux 4096)) + +;;; The size in bytes of the GENCGC pages. Should be a multiple of the +;;; architecture page size. +(def!constant gencgc-page-size *backend-page-size*) diff --git a/src/compiler/ppc/parms.lisp b/src/compiler/ppc/parms.lisp index afef13c..49dd23c 100644 --- a/src/compiler/ppc/parms.lisp +++ b/src/compiler/ppc/parms.lisp @@ -24,11 +24,6 @@ ;;; object (def!constant n-byte-bits 8) - -;;; The size in bytes of the GENCGC pages. Should be a multiple of the -;;; architecture code size. -(def!constant gencgc-page-size 4096) - ;;; flags for the generational garbage collector (def!constant pseudo-atomic-interrupted-flag 1) (def!constant pseudo-atomic-flag 4) diff --git a/src/compiler/x86-64/backend-parms.lisp b/src/compiler/x86-64/backend-parms.lisp index 1ef5f6f..595ff0a 100644 --- a/src/compiler/x86-64/backend-parms.lisp +++ b/src/compiler/x86-64/backend-parms.lisp @@ -28,24 +28,13 @@ ;;; general have our C runtime code running to ask, so instead we set ;;; it by hand. -- WHN 2001-04-15 ;;; -;;; Though note that POSIX specifies (as far as I can tell) -;;; -;;; sysconf(_SC_PAGE_SIZE); -;;; -;;; as a portable way of retrieving this information; a call to this -;;; could be made in grovel-headers (which, strictly speaking, would -;;; no longer solely be grovelling headers), though the question of -;;; how to make this information appear in GENESIS, which is built and -;;; run from host-1 files (which are made before grovel-headers runs) -;;; would remain. -- CSR, 2002-09-01 -(setf *backend-page-size* 4096) -;;; comment from CMU CL: -;;; -;;; in case we ever wanted to do this for Windows NT.. -;;; -;;; Windows NT uses a memory system granularity of 64K, which means -;;; everything that gets mapped must be a multiple of that. The real -;;; page size is 512, but that doesn't do us a whole lot of good. -;;; Effectively, the page size is 64K. -;;; -;;; would be: (setf *backend-page-size* 65536) +;;; Actually any information that we can retrieve C-side would be +;;; useless in SBCL, since it's possible for otherwise binary +;;; compatible systems to return different values for getpagesize(). +;;; -- JES, 2007-01-06 +(eval-when (:compile-toplevel :load-toplevel :execute) + (setf *backend-page-size* 4096)) + +;;; The size in bytes of the GENCGC pages. Should be a multiple of the +;;; architecture code size. +(def!constant gencgc-page-size 4096) diff --git a/src/compiler/x86-64/parms.lisp b/src/compiler/x86-64/parms.lisp index 4f863fb..0249f13 100644 --- a/src/compiler/x86-64/parms.lisp +++ b/src/compiler/x86-64/parms.lisp @@ -35,10 +35,6 @@ ;;; addressable object (def!constant n-byte-bits 8) -;;; The size in bytes of the GENCGC pages. Should be a multiple of the -;;; architecture code size. -(def!constant gencgc-page-size 4096) - (def!constant float-sign-shift 31) ;;; comment from CMU CL: diff --git a/src/compiler/x86/backend-parms.lisp b/src/compiler/x86/backend-parms.lisp index a1802f5..7414281 100644 --- a/src/compiler/x86/backend-parms.lisp +++ b/src/compiler/x86/backend-parms.lisp @@ -28,17 +28,12 @@ ;;; general have our C runtime code running to ask, so instead we set ;;; it by hand. -- WHN 2001-04-15 ;;; -;;; Though note that POSIX specifies (as far as I can tell) -;;; -;;; sysconf(_SC_PAGE_SIZE); -;;; -;;; as a portable way of retrieving this information; a call to this -;;; could be made in grovel-headers (which, strictly speaking, would -;;; no longer solely be grovelling headers), though the question of -;;; how to make this information appear in GENESIS, which is built and -;;; run from host-1 files (which are made before grovel-headers runs) -;;; would remain. -- CSR, 2002-09-01 -(setf *backend-page-size* 4096) +;;; Actually any information that we can retrieve C-side would be +;;; useless in SBCL, since it's possible for otherwise binary +;;; compatible systems to return different values for getpagesize(). +;;; -- JES, 2007-01-06 +(eval-when (:compile-toplevel :load-toplevel :execute) + (setf *backend-page-size* 4096)) ;;; comment from CMU CL: ;;; ;;; in case we ever wanted to do this for Windows NT.. @@ -49,3 +44,7 @@ ;;; Effectively, the page size is 64K. ;;; ;;; would be: (setf *backend-page-size* 65536) + +;;; The size in bytes of the GENCGC pages. Should be a multiple of the +;;; architecture code size. +(def!constant gencgc-page-size *backend-page-size*) diff --git a/src/compiler/x86/parms.lisp b/src/compiler/x86/parms.lisp index d22a4a5..e6cde61 100644 --- a/src/compiler/x86/parms.lisp +++ b/src/compiler/x86/parms.lisp @@ -35,10 +35,6 @@ ;;; addressable object (def!constant n-byte-bits 8) -;;; The size in bytes of the GENCGC pages. Should be a multiple of the -;;; architecture code size. -(def!constant gencgc-page-size 4096) - (def!constant float-sign-shift 31) ;;; comment from CMU CL: diff --git a/src/runtime/coreparse.c b/src/runtime/coreparse.c index 4b4998f..e7dbdfd 100644 --- a/src/runtime/coreparse.c +++ b/src/runtime/coreparse.c @@ -349,7 +349,16 @@ load_core_file(char *file, os_vm_offset_t file_offset) size -= bytes_read; while (bytes_read) { bytes_read -= sizeof(long); - page_table[offset++].first_object_offset = data[i++]; + /* Ignore all zeroes. The size of the page table + * core entry was rounded up to os_vm_page_size + * during the save, and might now have more + * elements than the page table. + */ + if (data[i]) { + page_table[offset].first_object_offset = data[i]; + } + i++; + offset++; } } diff --git a/src/runtime/gencgc-internal.h b/src/runtime/gencgc-internal.h index c9fe3b5..ba56529 100644 --- a/src/runtime/gencgc-internal.h +++ b/src/runtime/gencgc-internal.h @@ -29,6 +29,15 @@ inline page_index_t find_page_index(void *); inline void *page_address(page_index_t); int gencgc_handle_wp_violation(void *); + +/* Note that this structure is also used from Lisp-side in + * src/code/room.lisp, and the Lisp-side structure layout is currently + * not groveled from C code but hardcoded. Any changes to the + * structure layout need to be also made there. + * + * FIXME: We should probably just define this structure in Lisp, and + * output the C version in genesis. -- JES, 2006-12-30. + */ struct page { /* The name of this field is not well-chosen for its actual use. * This is the offset from the start of the page to the start @@ -40,15 +49,11 @@ struct page { * than the actual bytes used for pages within the current * allocation regions. It should be 0 for all unallocated pages (not * hard to achieve). - * - * Currently declared as an unsigned short to make the struct size - * smaller. This means that GENCGC-PAGE-SIZE is constrained to fit - * inside a short. */ +#if PAGE_BYTES > USHRT_MAX + unsigned int bytes_used; +#else unsigned short bytes_used; - -#if USHRT_MAX < PAGE_BYTES -#error "PAGE_BYTES too large" #endif unsigned diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index 4c6ef83..6724eb1 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -185,7 +185,12 @@ os_init(char *argv[], char *envp[]) "LD_ASSUME_KERNEL\n"); } #endif - os_vm_page_size = getpagesize(); + + /* Don't use getpagesize(), since it's not constant across Linux + * kernel versions on some architectures (for example PPC). FIXME: + * possibly the same should be done on other architectures too. + */ + os_vm_page_size = BACKEND_PAGE_SIZE; /* KLUDGE: Disable memory randomization on new Linux kernels * by setting a personality flag and re-executing. (We need diff --git a/version.lisp-expr b/version.lisp-expr index efcda04..50aa6da 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"1.0.1.27" +"1.0.1.28"