📄 erl_init.c
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "sys.h"#include <ctype.h>#include "erl_vm.h"#include "global.h"#include "erl_process.h"#include "error.h"#include "erl_version.h"#include "erl_db.h"#include "beam_bp.h"#include "erl_bits.h"#include "erl_binary.h"#include "dist.h"#include "erl_mseg.h"#include "erl_nmgc.h"#include "erl_threads.h"#include "erl_bif_timer.h"#include "erl_instrument.h"#include "erl_printf_term.h"#include "erl_misc_utils.h"#ifdef HIPE#include "hipe_mode_switch.h" /* for hipe_mode_switch_init() */#include "hipe_signal.h" /* for hipe_signal_init() */#endif/* * Note about VxWorks: All variables must be initialized by executable code, * not by an initializer. Otherwise a new instance of the emulator will * inherit previous values. */extern void erl_crash_dump_v(char *, int, char *, va_list);#ifdef __WIN32__extern void ConNormalExit(void);extern void ConWaitForExit(void);#endif#define ERTS_MIN_COMPAT_REL 7#ifdef ERTS_SMPerts_smp_atomic_t erts_writing_erl_crash_dump;#elsevolatile int erts_writing_erl_crash_dump = 0;#endifint erts_initialized = 0;#if defined(USE_THREADS) && !defined(ERTS_SMP)static erts_tid_t main_thread;#endif/* * Configurable parameters. */Uint display_items; /* no of items to display in traces etc */Uint display_loads; /* print info about loaded modules */int H_MIN_SIZE; /* The minimum heap grain */Uint32 erts_debug_flags; /* Debug flags. */#ifndef ERTS_SMP /* Not supported with smp emulator */int count_instructions;#endifint erts_backtrace_depth; /* How many functions to show in a backtrace * in error codes. */int erts_async_max_threads; /* number of threads for async support */int erts_async_thread_suggested_stack_size;erts_smp_atomic_t erts_max_gen_gcs;Eterm erts_error_logger_warnings; /* What to map warning logs to, am_error, am_info or am_warning, am_error is the default for BC */int erts_compat_rel;#ifdef DEBUGUint32 verbose; /* See erl_debug.h for information about verbose */#endifint erts_disable_tolerant_timeofday; /* Time correction can be disabled it is * not and/or it is too slow. */#ifdef ERTS_SMPUint no_of_schedulers;#endifint erts_modified_timing_level;/* * Other global variables. */ErtsModifiedTimings erts_modified_timings[] = { /* 0 */ {make_small(0), CONTEXT_REDS, INPUT_REDUCTIONS}, /* 1 */ {make_small(0), 2*CONTEXT_REDS, 2*INPUT_REDUCTIONS}, /* 2 */ {make_small(0), CONTEXT_REDS/2, INPUT_REDUCTIONS/2}, /* 3 */ {make_small(0), 3*CONTEXT_REDS, 3*INPUT_REDUCTIONS}, /* 4 */ {make_small(0), CONTEXT_REDS/3, 3*INPUT_REDUCTIONS}, /* 5 */ {make_small(0), 4*CONTEXT_REDS, INPUT_REDUCTIONS/2}, /* 6 */ {make_small(1), CONTEXT_REDS/4, 2*INPUT_REDUCTIONS}, /* 7 */ {make_small(1), 5*CONTEXT_REDS, INPUT_REDUCTIONS/3}, /* 8 */ {make_small(10), CONTEXT_REDS/5, 3*INPUT_REDUCTIONS}, /* 9 */ {make_small(10), 6*CONTEXT_REDS, INPUT_REDUCTIONS/4}};#define ERTS_MODIFIED_TIMING_LEVELS \ (sizeof(erts_modified_timings)/sizeof(ErtsModifiedTimings))Export *erts_delay_trap = NULL;int erts_use_r9_pids_ports;#ifdef HYBRIDEterm *global_heap;Eterm *global_hend;Eterm *global_htop;Eterm *global_saved_htop;Eterm *global_old_heap;Eterm *global_old_hend;ErlOffHeap erts_global_offheap;Uint global_heap_sz = SH_DEFAULT_SIZE;#ifndef INCREMENTALEterm *global_high_water;Eterm *global_old_htop;#endifUint16 global_gen_gcs;Uint16 global_max_gen_gcs;Uint global_gc_flags;Uint global_heap_min_sz = SH_DEFAULT_SIZE;#endifint ignore_break;int replace_intr;static char*progname(char *fullname) { int i; i = strlen(fullname); while (i >= 0) { if ((fullname[i] != '/') && (fullname[i] != '\\')) i--; else break; } return fullname+i+1;}static intthis_rel_num(void){ static int this_rel = -1; if (this_rel < 1) { int i; char this_rel_str[] = ERLANG_OTP_RELEASE; i = 0; while (this_rel_str[i] && !isdigit((int) this_rel_str[i])) i++; this_rel = atoi(&this_rel_str[i]); if (this_rel < 1) erl_exit(-1, "Unexpected ERLANG_OTP_RELEASE format\n"); } return this_rel;}/* * Common error printout function, all error messages * that don't go to the error logger go through here. */void erl_error(char *fmt, va_list args){ erts_vfprintf(stderr, fmt, args);}static void early_init(int *argc, char **argv);voiderts_short_init(void){ early_init(NULL, NULL); erl_init(); erts_initialized = 1;}voiderl_init(void){ init_benchmarking();#ifdef ERTS_SMP erts_system_block_init();#endif erts_init_monitors(); erts_init_gc(); erts_init_process(); H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0); erts_init_trace(); erts_init_binary(); erts_init_bits(); erts_init_fun_table(); init_atom_table(); init_export_table(); init_module_table(); init_register_table(); init_message(); erts_bif_info_init(); erts_ddll_init(); init_emulator(); erts_bp_init(); init_db(); /* Must be after init_emulator */ init_time(); erts_bif_timer_init(); erts_init_node_tables(); init_dist(); init_io(); init_copy(); init_load(); erts_init_bif(); erts_init_obsolete(); erts_delay_trap = erts_export_put(am_erlang, am_delay_trap, 2);#if HAVE_ERTS_MSEG erts_mseg_late_init(); /* Must be after timer (init_time()) and thread initializations */#endif#ifdef HIPE hipe_mode_switch_init(); /* Must be after init_load/beam_catches/init */#endif#ifdef _OSE_ erl_sys_init_final();#endif}static voidinit_shared_memory(int argc, char **argv){#ifdef HYBRID int arg_size = 0; global_heap_sz = erts_next_heap_size(global_heap_sz,0); /* Make sure arguments will fit on the heap, no one else will check! */ while (argc--) arg_size += 2 + strlen(argv[argc]); if (global_heap_sz < arg_size) global_heap_sz = erts_next_heap_size(arg_size,1);#ifndef INCREMENTAL global_heap = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm) * global_heap_sz); global_hend = global_heap + global_heap_sz; global_htop = global_heap; global_high_water = global_heap; global_old_hend = global_old_htop = global_old_heap = NULL;#endif global_gen_gcs = 0; global_max_gen_gcs = erts_smp_atomic_read(&erts_max_gen_gcs); global_gc_flags = erts_default_process_flags; erts_global_offheap.mso = NULL;#ifndef HYBRID /* FIND ME! */ erts_global_offheap.funs = NULL;#endif erts_global_offheap.overhead = 0;#endif#ifdef INCREMENTAL erts_init_incgc();#endif}/* * Create the very first process. */voiderts_first_process(Eterm modname, void* code, unsigned size, int argc, char** argv){ int i; Eterm args; Eterm pid; Eterm* hp; Process parent; Process* p; ErlSpawnOpts so; if (erts_find_function(modname, am_start, 1) == NULL) { char sbuf[256]; Atom* ap; ap = atom_tab(atom_val(modname)); memcpy(sbuf, ap->name, ap->len); sbuf[ap->len] = '\0'; erl_exit(5, "No function %s:start/1\n", sbuf); } /* * We need a dummy parent process to be able to call erl_create_process(). */ erts_init_empty_process(&parent); hp = HAlloc(&parent, argc*2 + 4); args = NIL; for (i = argc-1; i >= 0; i--) { int len = sys_strlen(argv[i]); args = CONS(hp, new_binary(&parent, (byte*)argv[i], len), args); hp += 2; } args = CONS(hp, new_binary(&parent, code, size), args); hp += 2; args = CONS(hp, args, NIL); so.flags = 0; pid = erl_create_process(&parent, modname, am_start, args, &so); p = process_tab[internal_pid_index(pid)]; p->group_leader = pid; erts_cleanup_empty_process(&parent);}/* * XXX Old way of starting. Hopefully soon obsolete. */static voiderl_first_process_otp(char* modname, void* code, unsigned size, int argc, char** argv){ int i; Eterm start_mod; Eterm args; Eterm* hp; Process parent; ErlSpawnOpts so; Eterm env; start_mod = am_atom_put(modname, sys_strlen(modname)); if (erts_find_function(start_mod, am_start, 2) == NULL) { erl_exit(5, "No function %s:start/2\n", modname); } /* * We need a dummy parent process to be able to call erl_create_process(). */ erts_init_empty_process(&parent); hp = HAlloc(&parent, argc*2 + 4); args = NIL; for (i = argc-1; i >= 0; i--) { int len = sys_strlen(argv[i]); args = CONS(hp, new_binary(&parent, (byte*)argv[i], len), args); hp += 2; } env = new_binary(&parent, code, size); args = CONS(hp, args, NIL); hp += 2; args = CONS(hp, env, args); so.flags = 0; (void) erl_create_process(&parent, start_mod, am_start, args, &so); erts_cleanup_empty_process(&parent);}Etermerts_preloaded(Process* p){ Eterm previous; int j; int need; Eterm mod; Eterm* hp; char* name; const Preload *preload = sys_preloaded(); j = 0; while (preload[j].name != NULL) { j++; } previous = NIL; need = 2*j; hp = HAlloc(p, need); j = 0; while ((name = preload[j].name) != NULL) { mod = am_atom_put(name, sys_strlen(name)); previous = CONS(hp, mod, previous); hp += 2; j++; } return previous;}/* static variables that must not change (use same values at restart) */static char* program;static char* init = "init";static char* boot = "boot";static int boot_argc;static char** boot_argv;static char *get_arg(char* rest, char* next, int* ip){ if (*rest == '\0') { if (next == NULL) { erts_fprintf(stderr, "too few arguments\n"); erts_usage(); } (*ip)++; return next; } return rest;}static void load_preloaded(void){ int i; int res; Preload* preload_p; Eterm module_name; byte* code; char* name; int length; if ((preload_p = sys_preloaded()) == NULL) { return; } i = 0; while ((name = preload_p[i].name) != NULL) { length = preload_p[i].size; module_name = am_atom_put(name, sys_strlen(name)); if ((code = sys_preload_begin(&preload_p[i])) == 0) erl_exit(1, "Failed to find preloaded code for module %s\n", name); res = erts_load_module(NULL, 0, NIL, &module_name, code, length); sys_preload_end(&preload_p[i]); if (res < 0) erl_exit(1,"Failed loading preloaded module %s\n", name); i++; }}/* be helpful (or maybe downright rude:-) */void erts_usage(void){ erts_fprintf(stderr, "Usage: %s [flags] [ -- [init_args] ]\n", progname(program)); erts_fprintf(stderr, "The flags are:\n\n"); /* erts_fprintf(stderr, "-# number set the number of items to be used in traces etc\n"); */ erts_fprintf(stderr, "-a size suggested stack size in kilo words for threads\n"); erts_fprintf(stderr, " in the async-thread pool, valid range is [%d-%d]\n", ERTS_ASYNC_THREAD_MIN_STACK_SIZE, ERTS_ASYNC_THREAD_MAX_STACK_SIZE); erts_fprintf(stderr, "-A number set number of threads in async thread pool,\n"); erts_fprintf(stderr, " valid range is [0-%d]\n", ERTS_MAX_NO_OF_ASYNC_THREADS); erts_fprintf(stderr, "-B[c|d|i] c to have Ctrl-c interrupt the Erlang shell,\n"); erts_fprintf(stderr, " d (or no extra option) to disable the break\n"); erts_fprintf(stderr, " handler, i to ignore break signals\n"); /* erts_fprintf(stderr, "-b func set the boot function (default boot)\n"); */ erts_fprintf(stderr, "-c disable continuous date/time correction with\n"); erts_fprintf(stderr, " respect to uptime\n"); erts_fprintf(stderr, "-h number set minimum heap size in words (default %d)\n", H_DEFAULT_SIZE); /* erts_fprintf(stderr, "-i module set the boot module (default init)\n"); */ erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n"); erts_fprintf(stderr, "-l turn on auto load tracing\n"); erts_fprintf(stderr, "-M<X> <Y> memory allocator switches,\n"); erts_fprintf(stderr, " see the erts_alloc(3) man page for more info.\n"); erts_fprintf(stderr, "-P number set maximum number of processes on this node,\n"); erts_fprintf(stderr, " valid range is [%d-%d]\n", ERTS_MIN_PROCESSES, ERTS_MAX_PROCESSES); erts_fprintf(stderr, "-R number set compatibility release number,\n"); erts_fprintf(stderr, " valid range [%d-%d]\n", ERTS_MIN_COMPAT_REL, this_rel_num()); erts_fprintf(stderr, "-r force ets memory block to be moved on realloc\n"); erts_fprintf(stderr, "-S number set number of schedulers on this node,\n"); erts_fprintf(stderr, " valid range is [1-%d]\n", ERTS_MAX_NO_OF_SCHEDULERS); erts_fprintf(stderr, "-T number set modified timing level,\n"); erts_fprintf(stderr, " valid range is [0-%d]\n", ERTS_MODIFIED_TIMING_LEVELS-1); erts_fprintf(stderr, "-V print Erlang version\n"); erts_fprintf(stderr, "-v turn on chatty mode (GCs will be reported etc)\n"); erts_fprintf(stderr, "-W<i|w> set error logger warnings mapping,\n"); erts_fprintf(stderr, " see error_logger documentation for details\n"); erts_fprintf(stderr, "\n"); erts_fprintf(stderr, "Note that if the emulator is started with erlexec (typically\n"); erts_fprintf(stderr, "from the erl script), these flags should be specified with +.\n"); erts_fprintf(stderr, "\n\n"); erl_exit(-1, "");}static voidearly_init(int *argc, char **argv) /* * Only put things here which are * really important initialize * early! */{ erts_printf_eterm_func = erts_printf_term; erts_disable_tolerant_timeofday = 0; display_items = 200; display_loads = 0; erts_backtrace_depth = DEFAULT_BACKTRACE_SIZE; erts_async_max_threads = 0; erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE; H_MIN_SIZE = H_DEFAULT_SIZE; erts_initialized = 0; ignore_break = 0; replace_intr = 0; program = argv[0]; erts_modified_timing_level = -1; erts_compat_rel = this_rel_num(); erts_use_r9_pids_ports = 0; erts_sys_pre_init();#ifdef ERTS_ENABLE_LOCK_CHECK erts_lc_init();#endif#ifdef ERTS_SMP erts_smp_atomic_init(&erts_writing_erl_crash_dump, 0L);#else erts_writing_erl_crash_dump = 0;#endif erts_smp_atomic_init(&erts_max_gen_gcs, (long)((Uint16) -1)); erts_pre_init_process();#if defined(USE_THREADS) && !defined(ERTS_SMP) main_thread = erts_thr_self();#endif erts_init_utils(); erts_alloc_init(argc, argv); /* Handles (and removes) -M flags */#ifdef ERTS_ENABLE_LOCK_CHECK erts_lc_late_init();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -