Fix attach_thread to allocate a TLS index for *gc-inhibit* if needed
[sbcl.git] / src / runtime / runtime.c
index f127933..49c007b 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <stdio.h>
 #include <string.h>
 
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 #ifndef LISP_FEATURE_WIN32
 #include <libgen.h>
 #endif
 #ifndef LISP_FEATURE_WIN32
 #include <libgen.h>
 #endif
@@ -29,7 +30,7 @@
 #include <sys/file.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/file.h>
 #include <sys/param.h>
 #include <sys/stat.h>
-#include <signal.h>
+#include "runtime.h"
 #ifndef LISP_FEATURE_WIN32
 #include <sched.h>
 #endif
 #ifndef LISP_FEATURE_WIN32
 #include <sched.h>
 #endif
@@ -41,7 +42,9 @@
 #include <time.h>
 #endif
 
 #include <time.h>
 #endif
 
+#if !(defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD))
 #include "signal.h"
 #include "signal.h"
+#endif
 
 #include "runtime.h"
 #include "vars.h"
 
 #include "runtime.h"
 #include "vars.h"
@@ -92,7 +95,7 @@ void
 sigint_init(void)
 {
     SHOW("entering sigint_init()");
 sigint_init(void)
 {
     SHOW("entering sigint_init()");
-    install_handler(SIGINT, sigint_handler);
+    install_handler(SIGINT, sigint_handler, 1);
     SHOW("leaving sigint_init()");
 }
 \f
     SHOW("leaving sigint_init()");
 }
 \f
@@ -179,6 +182,14 @@ Common toplevel options:\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\
   --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\
+  --disable-debugger         Invoke sb-ext:disable-debugger.\n\
+  --noprint                  Run a Read-Eval Loop without printing results.\n\
+  --script [<filename>]      Skip #! line, disable debugger, avoid verbosity.\n\
+  --quit                     Exit with code 0 after option processing.\n\
+  --non-interactive          Sets both --quit and --disable-debugger.\n\
+Common toplevel options that are processed in order:\n\
+  --eval <form>              Form to eval when processing this option.\n\
+  --load <filename>          File to load when processing this option.\n\
 \n\
 User options are not processed by SBCL. All runtime options must\n\
 appear before toplevel options, and all toplevel options must\n\
 \n\
 User options are not processed by SBCL. All runtime options must\n\
 appear before toplevel options, and all toplevel options must\n\
@@ -283,12 +294,103 @@ search_for_executable(const char *argv0)
 }
 #endif /* LISP_FEATURE_WIN32 */
 
 }
 #endif /* LISP_FEATURE_WIN32 */
 
+size_t
+parse_size_arg(char *arg, char *arg_name)
+{
+  char *tail, *power_name;
+  size_t power, res;
+
+  res = strtoul(arg, &tail, 0);
+
+  if (arg == tail) {
+    lose("%s argument is not a number: %s", arg_name, arg);
+  } else if (tail[0]) {
+    int i, size;
+    power_name = copied_string(tail);
+    size = strlen(power_name);
+    for (i=0; i<size; i++)
+      power_name[i] = toupper(power_name[i]);
+  } else {
+    power = 20;
+    power_name = NULL;
+  }
+  if (power_name) {
+    if ((0==strcmp("KB", power_name)) ||
+        (0==strcmp("KIB", power_name))) {
+      power = 10;
+    } else if ((0==strcmp("MB", power_name)) ||
+               (0==strcmp("MIB", power_name))) {
+      power = 20;
+    } else if ((0==strcmp("GB", power_name)) ||
+               (0==strcmp("GIB", power_name))) {
+      power = 30;
+    } else {
+      lose("%s argument has an unknown suffix: %s", arg_name, tail);
+    }
+    free(power_name);
+  }
+  if ((res <= 0) ||
+      (res >= (SIZE_MAX >> power))) {
+    lose("%s argument is out of range: %s", arg_name, arg);
+  }
+  res <<= power;
+  return res;
+}
+
 char **posix_argv;
 char *core_string;
 
 struct runtime_options *runtime_options;
 
 char *saved_runtime_path = NULL;
 char **posix_argv;
 char *core_string;
 
 struct runtime_options *runtime_options;
 
 char *saved_runtime_path = NULL;
+#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
+void pthreads_win32_init();
+#endif
+
+void print_locale_variable(const char *name)
+{
+  char *value = getenv(name);
+
+  if (value) {
+    fprintf(stderr, "\n  %s=%s", name, value);
+  }
+}
+
+void setup_locale()
+{
+  if(setlocale(LC_ALL, "") == NULL) {
+#ifndef LISP_FEATURE_WIN32
+
+    fprintf(stderr, "WARNING: Setting locale failed.\n");
+    fprintf(stderr, "  Check the following variables for correct values:");
+
+    if (setlocale(LC_CTYPE, "") == NULL) {
+      print_locale_variable("LC_ALL");
+      print_locale_variable("LC_CTYPE");
+      print_locale_variable("LANG");
+    }
+
+    if (setlocale(LC_MESSAGES, "") == NULL) {
+      print_locale_variable("LC_MESSAGES");
+    }
+    if (setlocale(LC_COLLATE, "") == NULL) {
+      print_locale_variable("LC_COLLATE");
+    }
+    if (setlocale(LC_MONETARY, "") == NULL) {
+      print_locale_variable("LC_MONETARY");
+    }
+    if (setlocale(LC_NUMERIC, "") == NULL) {
+      print_locale_variable("LC_NUMERIC");
+    }
+    if (setlocale(LC_TIME, "") == NULL) {
+      print_locale_variable("LC_TIME");
+    }
+    fprintf(stderr, "\n");
+
+#endif
+  }
+}
+
 \f
 int
 main(int argc, char *argv[], char *envp[])
 \f
 int
 main(int argc, char *argv[], char *envp[])
@@ -313,11 +415,14 @@ main(int argc, char *argv[], char *envp[])
     lispobj initial_function;
     const char *sbcl_home = getenv("SBCL_HOME");
 
     lispobj initial_function;
     const char *sbcl_home = getenv("SBCL_HOME");
 
+#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
+    os_preinit();
+    pthreads_win32_init();
+#endif
+
     interrupt_init();
     block_blockable_signals(0, 0);
 
     interrupt_init();
     block_blockable_signals(0, 0);
 
-    setlocale(LC_ALL, "");
-
     runtime_options = NULL;
 
     /* Save the argv[0] derived runtime path in case
     runtime_options = NULL;
 
     /* Save the argv[0] derived runtime path in case
@@ -394,32 +499,21 @@ main(int argc, char *argv[], char *envp[])
                 ++argi;
                 if (argi >= argc)
                     lose("missing argument for --dynamic-space-size");
                 ++argi;
                 if (argi >= argc)
                     lose("missing argument for --dynamic-space-size");
-                {
-                  char *tail;
-                  long tmp = strtol(argv[argi++], &tail, 0);
-                  if (tail[0])
-                    lose("--dynamic-space-size argument is not a number");
-                  if ((tmp <= 0) ||
-                      (tmp >= (LONG_MAX >> 20))) {
-                    lose("--dynamic-space-size argument is out of range");
-                  }
-                  dynamic_space_size = tmp << 20;
-                }
+                  dynamic_space_size = parse_size_arg(argv[argi++], "--dynamic-space-size");
 #               ifdef MAX_DYNAMIC_SPACE_END
                 if (!((DYNAMIC_SPACE_START <
                        DYNAMIC_SPACE_START+dynamic_space_size) &&
                       (DYNAMIC_SPACE_START+dynamic_space_size <=
                        MAX_DYNAMIC_SPACE_END)))
 #               ifdef MAX_DYNAMIC_SPACE_END
                 if (!((DYNAMIC_SPACE_START <
                        DYNAMIC_SPACE_START+dynamic_space_size) &&
                       (DYNAMIC_SPACE_START+dynamic_space_size <=
                        MAX_DYNAMIC_SPACE_END)))
-                    lose("--dynamic-space-size argument is too large");
+                  lose("--dynamic-space-size argument %s is too large, max %lu",
+                       argv[argi-1], MAX_DYNAMIC_SPACE_END-DYNAMIC_SPACE_START);
 #               endif
             } else if (0 == strcmp(arg, "--control-stack-size")) {
                 ++argi;
                 if (argi >= argc)
                     lose("missing argument for --control-stack-size");
                 errno = 0;
 #               endif
             } else if (0 == strcmp(arg, "--control-stack-size")) {
                 ++argi;
                 if (argi >= argc)
                     lose("missing argument for --control-stack-size");
                 errno = 0;
-                thread_control_stack_size = strtol(argv[argi++], 0, 0) << 20;
-                if (errno)
-                    lose("argument to --control-stack-size is not a number");
+                thread_control_stack_size = parse_size_arg(argv[argi++], "--control-stack-size");
             } else if (0 == strcmp(arg, "--debug-environment")) {
                 int n = 0;
                 printf("; Commandline arguments:\n");
             } else if (0 == strcmp(arg, "--debug-environment")) {
                 int n = 0;
                 printf("; Commandline arguments:\n");
@@ -444,6 +538,15 @@ main(int argc, char *argv[], char *envp[])
                 end_runtime_options = 1;
                 ++argi;
                 break;
                 end_runtime_options = 1;
                 ++argi;
                 break;
+            } else if (0 == strcmp(arg, "--merge-core-pages")) {
+                ++argi;
+                merge_core_pages = 1;
+            } else if (0 == strcmp(arg, "--no-merge-core-pages")) {
+                ++argi;
+                merge_core_pages = 0;
+            } else if (0 == strcmp(arg, "--default-merge-core-pages")) {
+                ++argi;
+                merge_core_pages = -1;
             } else {
                 /* This option was unrecognized as a runtime option,
                  * so it must be a toplevel option or a user option,
             } else {
                 /* This option was unrecognized as a runtime option,
                  * so it must be a toplevel option or a user option,
@@ -481,11 +584,11 @@ main(int argc, char *argv[], char *envp[])
 
     /* Align down to multiple of page_table page size, and to the appropriate
      * stack alignment. */
 
     /* Align down to multiple of page_table page size, and to the appropriate
      * stack alignment. */
-    dynamic_space_size &= ~(PAGE_BYTES-1);
+    dynamic_space_size &= ~(sword_t)(PAGE_BYTES-1);
 #ifdef LISP_FEATURE_GENCGC
 #ifdef LISP_FEATURE_GENCGC
-    dynamic_space_size &= ~(GENCGC_CARD_BYTES-1);
+    dynamic_space_size &= ~(sword_t)(GENCGC_CARD_BYTES-1);
 #endif
 #endif
-    thread_control_stack_size &= ~(CONTROL_STACK_ALIGNMENT_BYTES-1);
+    thread_control_stack_size &= ~(sword_t)(CONTROL_STACK_ALIGNMENT_BYTES-1);
 
     /* Preserve the runtime options for possible future core saving */
     runtime_options->dynamic_space_size = dynamic_space_size;
 
     /* Preserve the runtime options for possible future core saving */
     runtime_options->dynamic_space_size = dynamic_space_size;
@@ -495,10 +598,13 @@ main(int argc, char *argv[], char *envp[])
      * 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);
      * 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);
+    dyndebug_init(); /* after os_init: do not print output before execve */
     arch_init();
     gc_init();
     validate();
 
     arch_init();
     gc_init();
     validate();
 
+    setup_locale();
+
     /* If no core file was specified, look for one. */
     if (!core) {
         core = search_for_core();
     /* If no core file was specified, look for one. */
     if (!core) {
         core = search_for_core();
@@ -525,6 +631,19 @@ main(int argc, char *argv[], char *envp[])
         fflush(stdout);
     }
 
         fflush(stdout);
     }
 
+    if (embedded_core_offset == 0) {
+        /* Here we make a last attempt at recognizing an embedded core,
+         * so that a file with an embedded core is a valid argument to
+         * --core.  We take care that any decisions on special behaviour
+         * (suppressed banner, embedded options) have already been made
+         * before we reach this block, so that there is no observable
+         * difference between "embedded" and "bare" images given to
+         * --core. */
+        os_vm_offset_t offset = search_for_embedded_core(core);
+        if (offset != -1)
+            embedded_core_offset = offset;
+    }
+
 #if defined(SVR4) || defined(__linux__) || defined(__NetBSD__)
     tzset();
 #endif
 #if defined(SVR4) || defined(__linux__) || defined(__NetBSD__)
     tzset();
 #endif
@@ -541,6 +660,9 @@ main(int argc, char *argv[], char *envp[])
     if (initial_function == NIL) {
         lose("couldn't find initial function\n");
     }
     if (initial_function == NIL) {
         lose("couldn't find initial function\n");
     }
+#ifdef LISP_FEATURE_SB_DYNAMIC_CORE
+    os_link_runtime();
+#endif
 #ifdef LISP_FEATURE_HPUX
     /* -1 = CLOSURE_FUN_OFFSET, 23 = SIMPLE_FUN_CODE_OFFSET, we are
      * not in LANGUAGE_ASSEMBLY so we cant reach them. */
 #ifdef LISP_FEATURE_HPUX
     /* -1 = CLOSURE_FUN_OFFSET, 23 = SIMPLE_FUN_CODE_OFFSET, we are
      * not in LANGUAGE_ASSEMBLY so we cant reach them. */