1.0.1.28: Fix SBCL on PPC with 65k pages.
authorJuho Snellman <jsnell@iki.fi>
Mon, 15 Jan 2007 22:15:48 +0000 (22:15 +0000)
committerJuho Snellman <jsnell@iki.fi>
Mon, 15 Jan 2007 22:15:48 +0000 (22:15 +0000)
        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).

14 files changed:
NEWS
src/code/linux-os.lisp
src/code/room.lisp
src/compiler/generic/genesis.lisp
src/compiler/ppc/backend-parms.lisp
src/compiler/ppc/parms.lisp
src/compiler/x86-64/backend-parms.lisp
src/compiler/x86-64/parms.lisp
src/compiler/x86/backend-parms.lisp
src/compiler/x86/parms.lisp
src/runtime/coreparse.c
src/runtime/gencgc-internal.h
src/runtime/linux-os.c
version.lisp-expr

diff --git a/NEWS b/NEWS
index b8adb5c..5be2eb0 100644 (file)
--- 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.
index 1e1e786..640320e 100644 (file)
@@ -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
index 6102f23..6e0ed5a 100644 (file)
   (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))
index 90c22bd..eb1ab4a 100644 (file)
@@ -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
index 9f061d6..ebaf637 100644 (file)
@@ -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*)
index afef13c..49dd23c 100644 (file)
 ;;; 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)
index 1ef5f6f..595ff0a 100644 (file)
 ;;; 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)
index 4f863fb..0249f13 100644 (file)
 ;;; 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:
index a1802f5..7414281 100644 (file)
 ;;; 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*)
index d22a4a5..e6cde61 100644 (file)
 ;;; 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:
index 4b4998f..e7dbdfd 100644 (file)
@@ -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++;
                 }
             }
 
index c9fe3b5..ba56529 100644 (file)
@@ -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 *);
 \f
+
+/* 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
index 4c6ef83..6724eb1 100644 (file)
@@ -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
index efcda04..50aa6da 100644 (file)
@@ -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"