;;;; -*- coding: utf-8; -*-
changes in sbcl-0.9.19 (1.0.0?) relative to sbcl-0.9.18:
+ * improvement: runtime option --dynamic-space-size can be used
+ to set the size of the dynamic space reserved on startup.
* improvement: floating point modes in effect are now saved in
core, and restored on startup.
* improvement: GET-INTERNAL-REAL-TIME now reports the time since
nonstandard toplevel which does not recognize the standard toplevel
options.
-@item --noinform
+@item --dynamic-space-size @var{megabytes}
+Size of the dynamic space reserved on startup in megabytes. Default
+value is platform dependent.
+
+@Item --noinform
Suppress the printing of any banner or other informational message at
startup. This makes it easier to write Lisp programs which work
cleanly in Unix pipelines. See also the @code{--noprint} and
file, it may run a nonstandard toplevel which does not recognize the
standard toplevel options.
.TP 3
+.B \-\-dynamic-space-size <megabytes>
+Size of the dynamic space reserved on startup in megabytes. Default value
+is platform dependent.
+.TP 3
.B \-\-noinform
Suppress the printing of any banner or other informational message at
startup. (This makes it easier to write Lisp programs which work
#!+ppc "PSEUDO-ATOMIC-FLAG"
"GENESIS" "HALT-TRAP" "IGNORE-ME-SC-NUMBER"
"IMMEDIATE-CHARACTER-SC-NUMBER" "IMMEDIATE-SAP-SC-NUMBER"
- "IMMEDIATE-SC-NUMBER" "*INITIAL-DYNAMIC-SPACE-FREE-POINTER*"
+ "IMMEDIATE-SC-NUMBER"
"INSTANCE-HEADER-WIDETAG" "INSTANCE-POINTER-LOWTAG"
"INSTANCE-SLOTS-OFFSET" "INSTANCE-USAGE"
"INTERIOR-REG-SC-NUMBER" "INTERNAL-ERROR-ARGS"
*core-string*
*read-only-space-free-pointer*
sb!vm:*static-space-free-pointer*
- sb!vm:*initial-dynamic-space-free-pointer*
sb!vm::*current-catch-block*
sb!vm::*current-unwind-protect-block*
sb!vm::*alien-stack*
(allocate-cold-descriptor *static*
0
sb!vm:even-fixnum-lowtag))
- (cold-set 'sb!vm:*initial-dynamic-space-free-pointer*
- (allocate-cold-descriptor *dynamic*
- 0
- sb!vm:even-fixnum-lowtag))
(/show "done setting free pointers")
;; Write results to files.
;; bignums. -- WHN 2000-10-02
*read-only-space-free-pointer*
*static-space-free-pointer*
- *initial-dynamic-space-free-pointer*
;; things needed for non-local-exit
*current-catch-block*
if ( (pc < READ_ONLY_SPACE_START ||
pc >= READ_ONLY_SPACE_START+READ_ONLY_SPACE_SIZE) &&
(pc < current_dynamic_space ||
- pc >= current_dynamic_space + DYNAMIC_SPACE_SIZE))
+ pc >= current_dynamic_space + dynamic_space_size))
return NULL;
return context->uc_mcontext.sc_traparg_a0;
struct thread *th;
if(in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE) ||
in_range_p(addr, STATIC_SPACE_START , STATIC_SPACE_SIZE) ||
- in_range_p(addr, DYNAMIC_SPACE_START , DYNAMIC_SPACE_SIZE))
+ in_range_p(addr, DYNAMIC_SPACE_START , dynamic_space_size))
return 1;
for_each_thread(th) {
if((th->control_stack_start <= addr) && (addr < th->control_stack_end))
* RSS by zeroing the from_space or madvise(MADV_DONTNEED) or
* similar os-dependent tricks here */
os_zero((os_vm_address_t) from_space,
- (os_vm_size_t) DYNAMIC_SPACE_SIZE);
+ (os_vm_size_t) dynamic_space_size);
current_dynamic_space = new_space;
dynamic_space_free_pointer = new_space_free_pointer;
(unsigned long)((os_vm_address_t)dynamic_space_free_pointer
- (os_vm_address_t)current_dynamic_space));
- length = os_trunc_size_to_page(DYNAMIC_SPACE_SIZE - dynamic_usage);
+ length = os_trunc_size_to_page(dynamic_space_size - dynamic_usage);
if (length < 0)
lose("set_auto_gc_trigger: tried to set gc trigger too high! (0x%08lx)\n",
(unsigned long)dynamic_usage);
return;
addr = (os_vm_address_t)current_auto_gc_trigger;
- length = DYNAMIC_SPACE_SIZE + (os_vm_address_t)current_dynamic_space - addr;
+ length = dynamic_space_size + (os_vm_address_t)current_dynamic_space - addr;
#if defined(SUNOS) || defined(SOLARIS)
/* don't want to force whole space into swapping mode... */
switch (id) {
case DYNAMIC_CORE_SPACE_ID:
+ if (len > dynamic_space_size) {
+ fprintf(stderr,
+ "dynamic space too small for core: %ldKiB required, %ldKiB available.\n",
+ len >> 10,
+ (long)dynamic_space_size >> 10);
+ exit(1);
+ }
#ifdef LISP_FEATURE_GENCGC
if (addr != (os_vm_address_t)DYNAMIC_SPACE_START) {
fprintf(stderr, "in core: 0x%lx; in runtime: 0x%lx \n",
(long)DYNAMIC_0_SPACE_START,
(long)DYNAMIC_1_SPACE_START);
lose("warning: core/runtime address mismatch: DYNAMIC_SPACE_START\n");
- }
-#endif
+ }
+#endif
#if defined(ALLOCATION_POINTER)
SetSymbolValue(ALLOCATION_POINTER, (lispobj)free_pointer,0);
#else
#ifndef _GC_H_
#define _GC_H_
+
+#include "sbcl.h"
+
+#ifdef LISP_FEATURE_GENCGC
+#define PAGE_BYTES GENCGC_PAGE_SIZE
+#else
+#define PAGE_BYTES 0x1000
+#endif
+
typedef signed long page_index_t;
typedef signed char generation_index_t;
#include "gencgc-alloc-region.h"
#include "genesis/code.h"
-#define PAGE_BYTES GENCGC_PAGE_SIZE
-
void gc_free_heap(void);
inline page_index_t find_page_index(void *);
inline void *page_address(page_index_t);
/* values for the page.allocated field */
\f
-/* the number of pages needed for the dynamic space - rounding up */
-#define NUM_PAGES ((page_index_t) ((DYNAMIC_SPACE_SIZE+PAGE_BYTES-1)/PAGE_BYTES))
-
-extern struct page page_table[NUM_PAGES];
+extern unsigned page_table_pages;
+extern struct page *page_table;
\f
/* forward declarations */
page_index_t page_index=(void*)obj - (void *)DYNAMIC_SPACE_START;
return ((page_index >= 0)
&& ((page_index =
- ((unsigned long)page_index)/PAGE_BYTES) < NUM_PAGES)
+ ((unsigned long)page_index)/PAGE_BYTES) < page_table_pages)
&& (page_table[page_index].gen == space));
}
* <ftp://ftp.cs.utexas.edu/pub/garbage/bigsurv.ps>.
*/
+#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
extern unsigned long bytes_consed_between_gcs; /* gc-common.c */
unsigned long auto_gc_trigger = 0;
+size_t dynamic_space_size = DEFAULT_DYNAMIC_SPACE_SIZE;
+
/* the source and destination generations. These are set before a GC starts
* scavenging. */
generation_index_t from_space;
* saving a core), don't scan the stack / mark pages dont_move. */
static boolean conservative_stack = 1;
-/* An array of page structures is statically allocated.
+/* An array of page structures is allocated on gc initialization.
* This helps quickly map between an address its page structure.
- * NUM_PAGES is set from the size of the dynamic space. */
-struct page page_table[NUM_PAGES];
+ * page_table_pages is set from the size of the dynamic space. */
+unsigned page_table_pages;
+struct page *page_table;
/* To map addresses to page structures the address of the first page
* is needed. */
if (index >= 0) {
index = ((unsigned long)index)/PAGE_BYTES;
- if (index < NUM_PAGES)
+ if (index < page_table_pages)
return (index);
}
do {
first_page = restart_page;
if (large_p)
- while ((first_page < NUM_PAGES)
+ while ((first_page < page_table_pages)
&& (page_table[first_page].allocated != FREE_PAGE_FLAG))
first_page++;
else
- while (first_page < NUM_PAGES) {
+ while (first_page < page_table_pages) {
if(page_table[first_page].allocated == FREE_PAGE_FLAG)
break;
if((page_table[first_page].allocated ==
first_page++;
}
- if (first_page >= NUM_PAGES)
+ if (first_page >= page_table_pages)
gc_heap_exhausted_error_or_lose(0, nbytes);
gc_assert(page_table[first_page].write_protected == 0);
num_pages = 1;
while (((bytes_found < nbytes)
|| (!large_p && (num_pages < 2)))
- && (last_page < (NUM_PAGES-1))
+ && (last_page < (page_table_pages-1))
&& (page_table[last_page+1].allocated == FREE_PAGE_FLAG)) {
last_page++;
num_pages++;
gc_assert(bytes_found == region_size);
restart_page = last_page + 1;
- } while ((restart_page < NUM_PAGES) && (bytes_found < nbytes));
+ } while ((restart_page < page_table_pages) && (bytes_found < nbytes));
/* Check for a failure */
- if ((restart_page >= NUM_PAGES) && (bytes_found < nbytes))
+ if ((restart_page >= page_table_pages) && (bytes_found < nbytes))
gc_heap_exhausted_error_or_lose(bytes_found, nbytes);
*restart_page_ptr=first_page;
#define SC_GEN_CK 0
#if SC_GEN_CK
/* Clear the write_protected_cleared flags on all pages. */
- for (i = 0; i < NUM_PAGES; i++)
+ for (i = 0; i < page_table_pages; i++)
page_table[i].write_protected_cleared = 0;
#endif
#if SC_GEN_CK
/* Check that none of the write_protected pages in this generation
* have been written to. */
- for (i = 0; i < NUM_PAGES; i++) {
+ for (i = 0; i < page_table_pages; i++) {
if ((page_table[i].allocation != FREE_PAGE_FLAG)
&& (page_table[i].bytes_used != 0)
&& (page_table[i].gen == generation)
#if SC_NS_GEN_CK
/* Check that none of the write_protected pages in this generation
* have been written to. */
- for (i = 0; i < NUM_PAGES; i++) {
+ for (i = 0; i < page_table_pages; i++) {
if ((page_table[i].allocation != FREE_PAGE_FLAG)
&& (page_table[i].bytes_used != 0)
&& (page_table[i].gen == generation)
if (gencgc_verbose > 1)
SHOW("entering gc_free_heap");
- for (page = 0; page < NUM_PAGES; page++) {
+ for (page = 0; page < page_table_pages; page++) {
/* Skip free pages which should already be zero filled. */
if (page_table[page].allocated != FREE_PAGE_FLAG) {
void *page_start, *addr;
{
page_index_t i;
+ /* Compute the number of pages needed for the dynamic space.
+ * Dynamic space size should be aligned on page size. */
+ page_table_pages = dynamic_space_size/PAGE_BYTES;
+ gc_assert(dynamic_space_size == page_table_pages*PAGE_BYTES);
+
+ page_table = calloc(page_table_pages, sizeof(struct page));
+ gc_assert(page_table);
+
gc_init_tables();
scavtab[WEAK_POINTER_WIDETAG] = scav_weak_pointer;
transother[SIMPLE_ARRAY_WIDETAG] = trans_boxed_large;
heap_base = (void*)DYNAMIC_SPACE_START;
/* Initialize each page structure. */
- for (i = 0; i < NUM_PAGES; i++) {
+ for (i = 0; i < page_table_pages; i++) {
/* Initialize all pages as free. */
page_table[i].allocated = FREE_PAGE_FLAG;
page_table[i].bytes_used = 0;
#ifndef LANGUAGE_ASSEMBLY
extern int foreign_function_call_active;
-extern boolean stop_the_world;
+extern size_t dynamic_space_size;
#ifdef LISP_FEATURE_WIN32
#define ENVIRON _environ
else{
void *badaddr=arch_get_bad_addr(signal,info,context);
return (badaddr >= (void *)current_auto_gc_trigger &&
- badaddr <((void *)current_dynamic_space + DYNAMIC_SPACE_SIZE));
+ badaddr <((void *)current_dynamic_space + dynamic_space_size));
}
}
#endif
#endif
os_zero((os_vm_address_t) current_dynamic_space,
- (os_vm_size_t) DYNAMIC_SPACE_SIZE);
+ (os_vm_size_t) dynamic_space_size);
/* Zero the stack. Note that the stack is also zeroed by SUB-GC
* calling SCRUB-CONTROL-STACK - this zeros the stack on the x86. */
print_help()
{
puts(
-"SBCL is a Common Lisp programming environment. Ordinarily you shouldn't\n\
-need command line options when you invoke it interactively: you can just\n\
-start it and work with the customary Lisp READ-EVAL-PRINT loop.\n\
+"Usage: sbcl [runtime-options] [toplevel-options] [user-options]\n\
+Common runtime options:\n\
+ --help Print this message and exit.\n\
+ --version Print version information and exit.\n\
+ --core <filename> Use the specified core file instead of the default.\n\
+ --dynamic-space-size <MiB> Size of reserved dynamic space in megabytes.\n\
\n\
-One option idiom which is sometimes useful interactively (e.g. when\n\
-exercising a test case for a bug report) is\n\
- sbcl --no-sysinit --no-userinit\n\
-to keep SBCL from reading any initialization files at startup. And some\n\
-people like to suppress the default startup message:\n\
- sbcl --noinform\n\
+Common toplevel options:\n\
+ --sysinit <filename> System-wide init-file to use instead of default.\n\
+ --userinit <filename> Per-user init-file to use instead of default.\n\
+ --no-sysinit Inhibit processing of any system-wide init-file.\n\
+ --no-userinit Inhibit processing of any per-user init-file.\n\
\n\
-Other options can be useful when you're running SBCL noninteractively,\n\
-e.g. from a script, or if you have a strange system configuration, so\n\
-that SBCL can't by default find one of the files it needs. For\n\
-information on such options, see the sbcl(1) man page.\n\
+User options are not processed by SBCL. All runtime options must\n\
+appear before toplevel options, and all toplevel options must\n\
+appear before user options.\n\
\n\
-More information on SBCL can be found on its man page, or at\n\
-<http://sbcl.sf.net/>.\n");
+For more information please refer to the SBCL User Manual, which\n\
+should be installed along with SBCL, and is also available from the\n\
+website <http://www.sbcl.org/>.\n");
}
void
setlocale(LC_ALL, "");
- /* KLUDGE: os_vm_page_size is set by os_init(), and on some
- * systems (e.g. Alpha) arch_init() needs need os_vm_page_size, so
- * it must follow os_init(). -- WHN 2000-01-26 */
- os_init(argv, envp);
- arch_init();
- gc_init();
- validate();
-
/* Parse our part of the command line (aka "runtime options"),
* stripping out those options that we handle. */
{
/* As in "--help" case, I think this is expected. */
print_version();
exit(0);
+ } else if (0 == strcmp(arg, "--dynamic-space-size")) {
+ ++argi;
+ if (argi >= argc)
+ lose("missing argument for --dynamic-space-size");
+ errno = 0;
+ dynamic_space_size = strtol(argv[argi++], 0, 0) << 20;
+ if (errno)
+ lose("argument to --dynamic-space-size is not a number");
} else if (0 == strcmp(arg, "--debug-environment")) {
int n = 0;
printf("; Commandline arguments:\n");
}
}
+ /* Align down to multiple of page_table page size */
+ dynamic_space_size = (dynamic_space_size/PAGE_BYTES) * PAGE_BYTES;
+
+ /* KLUDGE: os_vm_page_size is set by os_init(), and on some
+ * systems (e.g. Alpha) arch_init() needs need os_vm_page_size, so
+ * it must follow os_init(). -- WHN 2000-01-26 */
+ os_init(argv, envp);
+ arch_init();
+ gc_init();
+ validate();
+
/* If no core file was specified, look for one. */
if (!core) {
char *runtime_path = os_get_runtime_executable_path();
if ((pc < READ_ONLY_SPACE_START ||
pc >= READ_ONLY_SPACE_START+READ_ONLY_SPACE_SIZE) &&
(pc < current_dynamic_space ||
- pc >= current_dynamic_space + DYNAMIC_SPACE_SIZE)) {
+ pc >= current_dynamic_space + dynamic_space_size)) {
return NULL;
}
if(in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE) ||
in_range_p(addr, STATIC_SPACE_START , STATIC_SPACE_SIZE) ||
#ifdef LISP_FEATURE_GENCGC
- in_range_p(addr, DYNAMIC_SPACE_START, DYNAMIC_SPACE_SIZE)
+ in_range_p(addr, DYNAMIC_SPACE_START , dynamic_space_size)
#else
- in_range_p(addr, DYNAMIC_0_SPACE_START, DYNAMIC_SPACE_SIZE) ||
- in_range_p(addr, DYNAMIC_1_SPACE_START, DYNAMIC_SPACE_SIZE)
+ in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size) ||
+ in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
#endif
)
return 1;
ensure_space( (lispobj *)READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE);
ensure_space( (lispobj *)STATIC_SPACE_START , STATIC_SPACE_SIZE);
#ifdef LISP_FEATURE_GENCGC
- ensure_space( (lispobj *)DYNAMIC_SPACE_START , DYNAMIC_SPACE_SIZE);
+ ensure_space( (lispobj *)DYNAMIC_SPACE_START , dynamic_space_size);
#else
- ensure_space( (lispobj *)DYNAMIC_0_SPACE_START , DYNAMIC_SPACE_SIZE);
- ensure_space( (lispobj *)DYNAMIC_1_SPACE_START , DYNAMIC_SPACE_SIZE);
+ ensure_space( (lispobj *)DYNAMIC_0_SPACE_START, dynamic_space_size);
+ ensure_space( (lispobj *)DYNAMIC_1_SPACE_START, dynamic_space_size);
#endif
#ifdef LISP_FEATURE_LINKAGE_TABLE
/* constants derived from the fundamental constants in passed by GENESIS */
#ifdef LISP_FEATURE_GENCGC
-#define DYNAMIC_SPACE_SIZE (DYNAMIC_SPACE_END - DYNAMIC_SPACE_START)
+#define DEFAULT_DYNAMIC_SPACE_SIZE (DYNAMIC_SPACE_END - DYNAMIC_SPACE_START)
#else
-#define DYNAMIC_SPACE_SIZE (DYNAMIC_0_SPACE_END - DYNAMIC_0_SPACE_START)
+#define DEFAULT_DYNAMIC_SPACE_SIZE (DYNAMIC_0_SPACE_END - DYNAMIC_0_SPACE_START)
#endif
#define READ_ONLY_SPACE_SIZE (READ_ONLY_SPACE_END - READ_ONLY_SPACE_START)
#define STATIC_SPACE_SIZE (STATIC_SPACE_END - STATIC_SPACE_START)
struct thread *th;
if(in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE) ||
in_range_p(addr, STATIC_SPACE_START , STATIC_SPACE_SIZE) ||
- in_range_p(addr, DYNAMIC_SPACE_START , DYNAMIC_SPACE_SIZE))
+ in_range_p(addr, DYNAMIC_SPACE_START , dynamic_space_size))
return 1;
for_each_thread(th) {
if(((os_vm_address_t)th->control_stack_start <= addr) && (addr < (os_vm_address_t)th->control_stack_end))
;;; 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".)
-"0.9.18.28"
+"0.9.18.29"