PageRenderTime 33ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/erts/emulator/beam/erl_init.c

https://github.com/bsmr-erlang/otp
C | 2479 lines | 2120 code | 210 blank | 149 comment | 464 complexity | 409dd6c2fc57fab6b67f1b279b711971 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. /*
  2. * %CopyrightBegin%
  3. *
  4. * Copyright Ericsson AB 1997-2018. All Rights Reserved.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * %CopyrightEnd%
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. # include "config.h"
  22. #endif
  23. #include "sys.h"
  24. #include <ctype.h>
  25. #include "erl_vm.h"
  26. #include "global.h"
  27. #include "erl_process.h"
  28. #include "error.h"
  29. #include "erl_version.h"
  30. #include "erl_db.h"
  31. #include "beam_bp.h"
  32. #include "erl_bits.h"
  33. #include "erl_binary.h"
  34. #include "dist.h"
  35. #include "erl_mseg.h"
  36. #include "erl_threads.h"
  37. #include "erl_hl_timer.h"
  38. #include "erl_mtrace.h"
  39. #include "erl_printf_term.h"
  40. #include "erl_misc_utils.h"
  41. #include "packet_parser.h"
  42. #include "erl_cpu_topology.h"
  43. #include "erl_thr_progress.h"
  44. #include "erl_thr_queue.h"
  45. #include "erl_async.h"
  46. #include "erl_ptab.h"
  47. #include "erl_bif_unique.h"
  48. #define ERTS_WANT_TIMER_WHEEL_API
  49. #include "erl_time.h"
  50. #include "erl_check_io.h"
  51. #include "erl_osenv.h"
  52. #include "erl_proc_sig_queue.h"
  53. #ifdef HIPE
  54. #include "hipe_mode_switch.h" /* for hipe_mode_switch_init() */
  55. #include "hipe_signal.h" /* for hipe_signal_init() */
  56. #endif
  57. #ifdef HAVE_SYS_RESOURCE_H
  58. # include <sys/resource.h>
  59. #endif
  60. #define ERTS_DEFAULT_NO_ASYNC_THREADS 1
  61. #define ERTS_DEFAULT_SCHED_STACK_SIZE 128
  62. #define ERTS_DEFAULT_DCPU_SCHED_STACK_SIZE 40
  63. #define ERTS_DEFAULT_DIO_SCHED_STACK_SIZE 40
  64. /*
  65. * The variables below (prefixed with etp_) are for erts/etc/unix/etp-commands
  66. * only. Do not remove even though they aren't used elsewhere in the emulator!
  67. */
  68. const int etp_smp_compiled = 1;
  69. const int etp_thread_compiled = 1;
  70. const char etp_erts_version[] = ERLANG_VERSION;
  71. const char etp_otp_release[] = ERLANG_OTP_RELEASE;
  72. const char etp_compile_date[] = ERLANG_COMPILE_DATE;
  73. const char etp_arch[] = ERLANG_ARCHITECTURE;
  74. #if ERTS_ENABLE_KERNEL_POLL
  75. const int erts_use_kernel_poll = 1;
  76. const int etp_kernel_poll_support = 1;
  77. #else
  78. const int erts_use_kernel_poll = 0;
  79. const int etp_kernel_poll_support = 0;
  80. #endif
  81. #if defined(ARCH_64)
  82. const int etp_arch_bits = 64;
  83. #elif defined(ARCH_32)
  84. const int etp_arch_bits = 32;
  85. #else
  86. # error "Not 64-bit, nor 32-bit arch"
  87. #endif
  88. #ifdef HIPE
  89. const int etp_hipe = 1;
  90. #else
  91. const int etp_hipe = 0;
  92. #endif
  93. #ifdef DEBUG
  94. const int etp_debug_compiled = 1;
  95. #else
  96. const int etp_debug_compiled = 0;
  97. #endif
  98. #ifdef ERTS_ENABLE_LOCK_COUNT
  99. const int etp_lock_count = 1;
  100. #else
  101. const int etp_lock_count = 0;
  102. #endif
  103. #ifdef ERTS_ENABLE_LOCK_CHECK
  104. const int etp_lock_check = 1;
  105. #else
  106. const int etp_lock_check = 0;
  107. #endif
  108. const int etp_endianness = ERTS_ENDIANNESS;
  109. const Eterm etp_ref_header = ERTS_REF_THING_HEADER;
  110. #ifdef ERTS_MAGIC_REF_THING_HEADER
  111. const Eterm etp_magic_ref_header = ERTS_MAGIC_REF_THING_HEADER;
  112. #else
  113. const Eterm etp_magic_ref_header = ERTS_REF_THING_HEADER;
  114. #endif
  115. const Eterm etp_the_non_value = THE_NON_VALUE;
  116. #ifdef ERTS_HOLE_MARKER
  117. const Eterm etp_hole_marker = ERTS_HOLE_MARKER;
  118. #else
  119. const Eterm etp_hole_marker = 0;
  120. #endif
  121. static int modified_sched_thread_suggested_stack_size = 0;
  122. Eterm erts_init_process_id = ERTS_INVALID_PID;
  123. /*
  124. * Note about VxWorks: All variables must be initialized by executable code,
  125. * not by an initializer. Otherwise a new instance of the emulator will
  126. * inherit previous values.
  127. */
  128. extern void erl_crash_dump_v(char *, int, char *, va_list);
  129. #ifdef __WIN32__
  130. extern void ConNormalExit(void);
  131. extern void ConWaitForExit(void);
  132. #endif
  133. static void erl_init(int ncpu,
  134. int proc_tab_sz,
  135. int legacy_proc_tab,
  136. int port_tab_sz,
  137. int port_tab_sz_ignore_files,
  138. int legacy_port_tab,
  139. int time_correction,
  140. ErtsTimeWarpMode time_warp_mode,
  141. int node_tab_delete_delay,
  142. ErtsDbSpinCount db_spin_count);
  143. static erts_atomic_t exiting;
  144. erts_atomic32_t erts_writing_erl_crash_dump;
  145. erts_tsd_key_t erts_is_crash_dumping_key;
  146. int erts_initialized = 0;
  147. /*
  148. * Configurable parameters.
  149. */
  150. int H_MIN_SIZE; /* The minimum heap grain */
  151. int BIN_VH_MIN_SIZE; /* The minimum binary virtual*/
  152. int H_MAX_SIZE; /* The maximum heap size */
  153. int H_MAX_FLAGS; /* The maximum heap flags */
  154. Uint32 erts_debug_flags; /* Debug flags. */
  155. int erts_backtrace_depth; /* How many functions to show in a backtrace
  156. * in error codes.
  157. */
  158. erts_atomic32_t erts_max_gen_gcs;
  159. Eterm erts_error_logger_warnings; /* What to map warning logs to, am_error,
  160. am_info or am_warning, am_error is
  161. the default for BC */
  162. int erts_compat_rel;
  163. static int no_schedulers;
  164. static int no_schedulers_online;
  165. static int no_dirty_cpu_schedulers;
  166. static int no_dirty_cpu_schedulers_online;
  167. static int no_dirty_io_schedulers;
  168. #ifdef DEBUG
  169. Uint32 verbose; /* See erl_debug.h for information about verbose */
  170. #endif
  171. int erts_atom_table_size = ATOM_LIMIT; /* Maximum number of atoms */
  172. int erts_pd_initial_size = 8; /* must be power of 2 */
  173. int erts_modified_timing_level;
  174. int erts_no_crash_dump = 0; /* Use -d to suppress crash dump. */
  175. int erts_no_line_info = 0; /* -L: Don't load line information */
  176. /*
  177. * Other global variables.
  178. */
  179. ErtsModifiedTimings erts_modified_timings[] = {
  180. /* 0 */ {make_small(0), CONTEXT_REDS},
  181. /* 1 */ {make_small(0), (3*CONTEXT_REDS)/4},
  182. /* 2 */ {make_small(0), CONTEXT_REDS/2},
  183. /* 3 */ {make_small(0), (7*CONTEXT_REDS)/8},
  184. /* 4 */ {make_small(0), CONTEXT_REDS/3},
  185. /* 5 */ {make_small(0), (10*CONTEXT_REDS)/11},
  186. /* 6 */ {make_small(1), CONTEXT_REDS/4},
  187. /* 7 */ {make_small(1), (5*CONTEXT_REDS)/7},
  188. /* 8 */ {make_small(10), CONTEXT_REDS/5},
  189. /* 9 */ {make_small(10), (6*CONTEXT_REDS)/7}
  190. };
  191. #define ERTS_MODIFIED_TIMING_LEVELS \
  192. (sizeof(erts_modified_timings)/sizeof(ErtsModifiedTimings))
  193. Export *erts_delay_trap = NULL;
  194. int ignore_break;
  195. int replace_intr;
  196. static ERTS_INLINE int
  197. has_prefix(const char *prefix, const char *string)
  198. {
  199. int i;
  200. for (i = 0; prefix[i]; i++)
  201. if (prefix[i] != string[i])
  202. return 0;
  203. return 1;
  204. }
  205. static char*
  206. progname(char *fullname)
  207. {
  208. int i;
  209. i = sys_strlen(fullname);
  210. while (i >= 0) {
  211. if ((fullname[i] != '/') && (fullname[i] != '\\'))
  212. i--;
  213. else
  214. break;
  215. }
  216. return fullname+i+1;
  217. }
  218. static int
  219. this_rel_num(void)
  220. {
  221. static int this_rel = -1;
  222. if (this_rel < 1) {
  223. int i;
  224. char this_rel_str[] = ERLANG_OTP_RELEASE;
  225. i = 0;
  226. while (this_rel_str[i] && !isdigit((int) this_rel_str[i]))
  227. i++;
  228. this_rel = atoi(&this_rel_str[i]);
  229. if (this_rel < 1)
  230. erts_exit(1, "Unexpected ERLANG_OTP_RELEASE format\n");
  231. }
  232. return this_rel;
  233. }
  234. static ERTS_INLINE void
  235. set_default_time_adj(int *time_correction_p, ErtsTimeWarpMode *time_warp_mode_p)
  236. {
  237. *time_correction_p = 1;
  238. *time_warp_mode_p = ERTS_NO_TIME_WARP_MODE;
  239. if (!erts_check_time_adj_support(*time_correction_p,
  240. *time_warp_mode_p)) {
  241. *time_correction_p = 0;
  242. ASSERT(erts_check_time_adj_support(*time_correction_p,
  243. *time_warp_mode_p));
  244. }
  245. }
  246. /*
  247. * Common error printout function, all error messages
  248. * that don't go to the error logger go through here.
  249. */
  250. void erl_error(char *fmt, va_list args)
  251. {
  252. erts_vfprintf(stderr, fmt, args);
  253. }
  254. static int early_init(int *argc, char **argv);
  255. static void
  256. erl_init(int ncpu,
  257. int proc_tab_sz,
  258. int legacy_proc_tab,
  259. int port_tab_sz,
  260. int port_tab_sz_ignore_files,
  261. int legacy_port_tab,
  262. int time_correction,
  263. ErtsTimeWarpMode time_warp_mode,
  264. int node_tab_delete_delay,
  265. ErtsDbSpinCount db_spin_count)
  266. {
  267. erts_monitor_link_init();
  268. erts_proc_sig_queue_init();
  269. erts_bif_unique_init();
  270. erts_init_time(time_correction, time_warp_mode);
  271. erts_init_sys_common_misc();
  272. erts_init_process(ncpu, proc_tab_sz, legacy_proc_tab);
  273. erts_init_scheduling(no_schedulers,
  274. no_schedulers_online,
  275. erts_no_poll_threads,
  276. no_dirty_cpu_schedulers,
  277. no_dirty_cpu_schedulers_online,
  278. no_dirty_io_schedulers
  279. );
  280. erts_late_init_time_sup();
  281. erts_init_cpu_topology(); /* Must be after init_scheduling */
  282. erts_init_gc(); /* Must be after init_scheduling */
  283. erts_alloc_late_init();
  284. H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0);
  285. BIN_VH_MIN_SIZE = erts_next_heap_size(BIN_VH_MIN_SIZE, 0);
  286. erts_init_trace();
  287. erts_init_bits();
  288. erts_code_ix_init();
  289. erts_init_fun_table();
  290. init_atom_table();
  291. init_export_table();
  292. init_module_table();
  293. init_register_table();
  294. init_message();
  295. erts_bif_info_init();
  296. erts_ddll_init();
  297. init_emulator();
  298. erts_ptab_init(); /* Must be after init_emulator() */
  299. erts_init_binary(); /* Must be after init_emulator() */
  300. erts_bp_init();
  301. init_db(db_spin_count); /* Must be after init_emulator */
  302. erts_init_node_tables(node_tab_delete_delay);
  303. init_dist();
  304. erl_drv_thr_init();
  305. erts_init_async();
  306. erts_init_io(port_tab_sz, port_tab_sz_ignore_files, legacy_port_tab);
  307. init_load();
  308. erts_init_bif();
  309. erts_init_bif_chksum();
  310. erts_init_bif_binary();
  311. erts_init_bif_guard();
  312. erts_init_bif_persistent_term();
  313. erts_init_bif_re();
  314. erts_init_unicode(); /* after RE to get access to PCRE unicode */
  315. erts_init_external();
  316. erts_init_map();
  317. erts_beam_bif_load_init();
  318. erts_delay_trap = erts_export_put(am_erlang, am_delay_trap, 2);
  319. erts_late_init_process();
  320. #if HAVE_ERTS_MSEG
  321. erts_mseg_late_init(); /* Must be after timer (erts_init_time()) and thread
  322. initializations */
  323. #endif
  324. erl_sys_late_init();
  325. #ifdef HIPE
  326. hipe_mode_switch_init(); /* Must be after init_load/beam_catches/init */
  327. #endif
  328. packet_parser_init();
  329. erl_nif_init();
  330. erts_msacc_init();
  331. }
  332. static Eterm
  333. erl_spawn_system_process(Process* parent, Eterm mod, Eterm func, Eterm args,
  334. ErlSpawnOpts *so)
  335. {
  336. Eterm res;
  337. int arity;
  338. ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(parent));
  339. arity = erts_list_length(args);
  340. if (erts_find_function(mod, func, arity, erts_active_code_ix()) == NULL) {
  341. erts_exit(ERTS_ERROR_EXIT, "No function %T:%T/%i\n", mod, func, arity);
  342. }
  343. so->flags |= SPO_SYSTEM_PROC;
  344. res = erl_create_process(parent, mod, func, args, so);
  345. return res;
  346. }
  347. static Eterm
  348. erl_first_process_otp(char* mod_name, int argc, char** argv)
  349. {
  350. int i;
  351. Eterm args;
  352. Eterm res;
  353. Eterm* hp;
  354. Process parent;
  355. ErlSpawnOpts so;
  356. Eterm boot_mod;
  357. /*
  358. * We need a dummy parent process to be able to call erl_create_process().
  359. */
  360. erts_init_empty_process(&parent);
  361. erts_proc_lock(&parent, ERTS_PROC_LOCK_MAIN);
  362. hp = HAlloc(&parent, argc*2 + 4);
  363. args = NIL;
  364. for (i = argc-1; i >= 0; i--) {
  365. int len = sys_strlen(argv[i]);
  366. args = CONS(hp, new_binary(&parent, (byte*)argv[i], len), args);
  367. hp += 2;
  368. }
  369. boot_mod = erts_atom_put((byte *) mod_name, sys_strlen(mod_name),
  370. ERTS_ATOM_ENC_LATIN1, 1);
  371. args = CONS(hp, args, NIL);
  372. hp += 2;
  373. args = CONS(hp, boot_mod, args);
  374. so.flags = erts_default_spo_flags;
  375. res = erl_spawn_system_process(&parent, am_erl_init, am_start, args, &so);
  376. ASSERT(is_internal_pid(res));
  377. erts_proc_unlock(&parent, ERTS_PROC_LOCK_MAIN);
  378. erts_cleanup_empty_process(&parent);
  379. return res;
  380. }
  381. static Eterm
  382. erl_system_process_otp(Eterm parent_pid, char* modname, int off_heap_msgq, int prio)
  383. {
  384. Process *parent;
  385. ErlSpawnOpts so;
  386. Eterm mod, res;
  387. parent = erts_pid2proc(NULL, 0, parent_pid, ERTS_PROC_LOCK_MAIN);
  388. mod = erts_atom_put((byte *) modname, sys_strlen(modname),
  389. ERTS_ATOM_ENC_LATIN1, 1);
  390. so.flags = erts_default_spo_flags|SPO_USE_ARGS;
  391. if (off_heap_msgq) {
  392. so.flags |= SPO_OFF_HEAP_MSGQ;
  393. }
  394. so.min_heap_size = H_MIN_SIZE;
  395. so.min_vheap_size = BIN_VH_MIN_SIZE;
  396. so.max_heap_size = H_MAX_SIZE;
  397. so.max_heap_flags = H_MAX_FLAGS;
  398. so.priority = prio;
  399. so.max_gen_gcs = (Uint16) erts_atomic32_read_nob(&erts_max_gen_gcs);
  400. so.scheduler = 0;
  401. res = erl_spawn_system_process(parent, mod, am_start, NIL, &so);
  402. ASSERT(is_internal_pid(res));
  403. erts_proc_unlock(parent, ERTS_PROC_LOCK_MAIN);
  404. return res;
  405. }
  406. Eterm erts_internal_spawn_system_process_3(BIF_ALIST_3) {
  407. Eterm mod, func, args, res;
  408. ErlSpawnOpts so;
  409. mod = BIF_ARG_1;
  410. func = BIF_ARG_2;
  411. args = BIF_ARG_3;
  412. ASSERT(is_atom(mod));
  413. ASSERT(is_atom(func));
  414. ASSERT(erts_list_length(args) >= 0);
  415. so.flags = erts_default_spo_flags;
  416. res = erl_spawn_system_process(BIF_P, mod, func, args, &so);
  417. if (is_non_value(res)) {
  418. BIF_ERROR(BIF_P, so.error_code);
  419. }
  420. BIF_RET(res);
  421. }
  422. Eterm
  423. erts_preloaded(Process* p)
  424. {
  425. Eterm previous;
  426. int j;
  427. int need;
  428. Eterm mod;
  429. Eterm* hp;
  430. char* name;
  431. const Preload *preload = sys_preloaded();
  432. j = 0;
  433. while (preload[j].name != NULL) {
  434. j++;
  435. }
  436. previous = NIL;
  437. need = 2*j;
  438. hp = HAlloc(p, need);
  439. j = 0;
  440. while ((name = preload[j].name) != NULL) {
  441. mod = am_atom_put(name, sys_strlen(name));
  442. previous = CONS(hp, mod, previous);
  443. hp += 2;
  444. j++;
  445. }
  446. return previous;
  447. }
  448. /* static variables that must not change (use same values at restart) */
  449. static char* program;
  450. static char* init = "init";
  451. static int boot_argc;
  452. static char** boot_argv;
  453. static char *
  454. get_arg(char* rest, char* next, int* ip)
  455. {
  456. if (*rest == '\0') {
  457. if (next == NULL) {
  458. erts_fprintf(stderr, "too few arguments\n");
  459. erts_usage();
  460. }
  461. (*ip)++;
  462. return next;
  463. }
  464. return rest;
  465. }
  466. static void
  467. load_preloaded(void)
  468. {
  469. int i;
  470. Eterm res;
  471. Preload* preload_p;
  472. Eterm module_name;
  473. byte* code;
  474. char* name;
  475. int length;
  476. if ((preload_p = sys_preloaded()) == NULL) {
  477. return;
  478. }
  479. i = 0;
  480. while ((name = preload_p[i].name) != NULL) {
  481. length = preload_p[i].size;
  482. module_name = erts_atom_put((byte *) name, sys_strlen(name), ERTS_ATOM_ENC_LATIN1, 1);
  483. if ((code = sys_preload_begin(&preload_p[i])) == 0)
  484. erts_exit(ERTS_ERROR_EXIT, "Failed to find preloaded code for module %s\n",
  485. name);
  486. res = erts_preload_module(NULL, 0, NIL, &module_name, code, length);
  487. sys_preload_end(&preload_p[i]);
  488. if (res != NIL)
  489. erts_exit(ERTS_ERROR_EXIT,"Failed loading preloaded module %s (%T)\n",
  490. name, res);
  491. i++;
  492. }
  493. }
  494. /* be helpful (or maybe downright rude:-) */
  495. void erts_usage(void)
  496. {
  497. int this_rel = this_rel_num();
  498. erts_fprintf(stderr, "Usage: %s [flags] [ -- [init_args] ]\n", progname(program));
  499. erts_fprintf(stderr, "The flags are:\n\n");
  500. erts_fprintf(stderr, "-a size suggested stack size in kilo words for threads\n");
  501. erts_fprintf(stderr, " in the async-thread pool, valid range is [%d-%d]\n",
  502. ERTS_ASYNC_THREAD_MIN_STACK_SIZE,
  503. ERTS_ASYNC_THREAD_MAX_STACK_SIZE);
  504. erts_fprintf(stderr, "-A number set number of threads in async thread pool,\n");
  505. erts_fprintf(stderr, " valid range is [0-%d]\n",
  506. ERTS_MAX_NO_OF_ASYNC_THREADS);
  507. erts_fprintf(stderr, "-B[c|d|i] c to have Ctrl-c interrupt the Erlang shell,\n");
  508. erts_fprintf(stderr, " d (or no extra option) to disable the break\n");
  509. erts_fprintf(stderr, " handler, i to ignore break signals\n");
  510. erts_fprintf(stderr, "-c bool enable or disable time correction\n");
  511. erts_fprintf(stderr, "-C mode set time warp mode; valid modes are:\n");
  512. erts_fprintf(stderr, " no_time_warp|single_time_warp|multi_time_warp\n");
  513. erts_fprintf(stderr, "-d don't write a crash dump for internally detected errors\n");
  514. erts_fprintf(stderr, " (halt(String) will still produce a crash dump)\n");
  515. erts_fprintf(stderr, "-dcg set the limit for the number of decentralized counter groups\n");
  516. erts_fprintf(stderr, "-fn[u|a|l] Control how filenames are interpreted\n");
  517. erts_fprintf(stderr, "-hms size set minimum heap size in words (default %d)\n",
  518. H_DEFAULT_SIZE);
  519. erts_fprintf(stderr, "-hmbs size set minimum binary virtual heap size in words (default %d)\n",
  520. VH_DEFAULT_SIZE);
  521. erts_fprintf(stderr, "-hmax size set maximum heap size in words (default %d)\n",
  522. H_DEFAULT_MAX_SIZE);
  523. erts_fprintf(stderr, "-hmaxk bool enable or disable kill at max heap size (default true)\n");
  524. erts_fprintf(stderr, "-hmaxel bool enable or disable error_logger report at max heap size (default true)\n");
  525. erts_fprintf(stderr, "-hpds size initial process dictionary size (default %d)\n",
  526. erts_pd_initial_size);
  527. erts_fprintf(stderr, "-hmqd val set default message queue data flag for processes,\n");
  528. erts_fprintf(stderr, " valid values are: off_heap | on_heap\n");
  529. erts_fprintf(stderr, "-IOp number set number of pollsets to be used to poll for I/O,\n");
  530. erts_fprintf(stderr, " This value has to be equal or smaller than the\n");
  531. erts_fprintf(stderr, " number of poll threads. If the current platform\n");
  532. erts_fprintf(stderr, " does not support concurrent update of pollsets\n");
  533. erts_fprintf(stderr, " this value is ignored.\n");
  534. erts_fprintf(stderr, "-IOt number set number of threads to be used to poll for I/O\n");
  535. erts_fprintf(stderr, "-IOPp number set number of pollsets as a percentage of the\n");
  536. erts_fprintf(stderr, " number of poll threads.");
  537. erts_fprintf(stderr, "-IOPt number set number of threads to be used to poll for I/O\n");
  538. erts_fprintf(stderr, " as a percentage of the number of schedulers.");
  539. erts_fprintf(stderr, "-i module set the boot module (default init)\n");
  540. erts_fprintf(stderr, "-n[s|a|d] Control behavior of signals to ports\n");
  541. erts_fprintf(stderr, " Note that this flag is deprecated!\n");
  542. erts_fprintf(stderr, "-M<X> <Y> memory allocator switches,\n");
  543. erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n");
  544. erts_fprintf(stderr, "-pc <set> Control what characters are considered printable (default latin1)\n");
  545. erts_fprintf(stderr, "-P number set maximum number of processes on this node,\n");
  546. erts_fprintf(stderr, " valid range is [%d-%d]\n",
  547. ERTS_MIN_PROCESSES, ERTS_MAX_PROCESSES);
  548. erts_fprintf(stderr, "-Q number set maximum number of ports on this node,\n");
  549. erts_fprintf(stderr, " valid range is [%d-%d]\n",
  550. ERTS_MIN_PORTS, ERTS_MAX_PORTS);
  551. erts_fprintf(stderr, "-R number set compatibility release number,\n");
  552. erts_fprintf(stderr, " valid range [%d-%d]\n",
  553. this_rel-2, this_rel);
  554. erts_fprintf(stderr, "-r force ets memory block to be moved on realloc\n");
  555. erts_fprintf(stderr, "-rg amount set reader groups limit\n");
  556. erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n");
  557. erts_fprintf(stderr, "-stbt type u|ns|ts|ps|s|nnts|nnps|tnnps|db\n");
  558. erts_fprintf(stderr, "-sbwt val set scheduler busy wait threshold, valid values are:\n");
  559. erts_fprintf(stderr, " none|very_short|short|medium|long|very_long.\n");
  560. erts_fprintf(stderr, "-sbwtdcpu val set dirty CPU scheduler busy wait threshold, valid values are:\n");
  561. erts_fprintf(stderr, " none|very_short|short|medium|long|very_long.\n");
  562. erts_fprintf(stderr, "-sbwtdio val set dirty IO scheduler busy wait threshold, valid values are:\n");
  563. erts_fprintf(stderr, " none|very_short|short|medium|long|very_long.\n");
  564. erts_fprintf(stderr, "-scl bool enable/disable compaction of scheduler load,\n");
  565. erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
  566. erts_fprintf(stderr, "-sct cput set cpu topology,\n");
  567. erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
  568. erts_fprintf(stderr, "-secio bool enable/disable eager check I/O scheduling,\n");
  569. erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
  570. #if ERTS_HAVE_SCHED_UTIL_BALANCING_SUPPORT_OPT
  571. erts_fprintf(stderr, "-sub bool enable/disable scheduler utilization balancing,\n");
  572. #else
  573. erts_fprintf(stderr, "-sub false disable scheduler utilization balancing,\n");
  574. #endif
  575. erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
  576. erts_fprintf(stderr, "-sws val set scheduler wakeup strategy, valid values are:\n");
  577. erts_fprintf(stderr, " default|legacy.\n");
  578. erts_fprintf(stderr, "-swct val set scheduler wake cleanup threshold, valid values are:\n");
  579. erts_fprintf(stderr, " very_lazy|lazy|medium|eager|very_eager.\n");
  580. erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n");
  581. erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n");
  582. erts_fprintf(stderr, "-swtdcpu val set dirty CPU scheduler wakeup threshold, valid values are:\n");
  583. erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n");
  584. erts_fprintf(stderr, "-swtdio val set dirty IO scheduler wakeup threshold, valid values are:\n");
  585. erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n");
  586. erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n");
  587. erts_fprintf(stderr, " valid range is [%d-%d] (default %d)\n",
  588. ERTS_SCHED_THREAD_MIN_STACK_SIZE,
  589. ERTS_SCHED_THREAD_MAX_STACK_SIZE,
  590. ERTS_DEFAULT_SCHED_STACK_SIZE);
  591. erts_fprintf(stderr, "-sssdcpu size suggested stack size in kilo words for dirty CPU scheduler\n");
  592. erts_fprintf(stderr, " threads, valid range is [%d-%d] (default %d)\n",
  593. ERTS_SCHED_THREAD_MIN_STACK_SIZE,
  594. ERTS_SCHED_THREAD_MAX_STACK_SIZE,
  595. ERTS_DEFAULT_DCPU_SCHED_STACK_SIZE);
  596. erts_fprintf(stderr, "-sssdio size suggested stack size in kilo words for dirty IO scheduler\n");
  597. erts_fprintf(stderr, " threads, valid range is [%d-%d] (default %d)\n",
  598. ERTS_SCHED_THREAD_MIN_STACK_SIZE,
  599. ERTS_SCHED_THREAD_MAX_STACK_SIZE,
  600. ERTS_DEFAULT_DIO_SCHED_STACK_SIZE);
  601. erts_fprintf(stderr, "-spp Bool set port parallelism scheduling hint\n");
  602. erts_fprintf(stderr, "-S n1:n2 set number of schedulers (n1), and number of\n");
  603. erts_fprintf(stderr, " schedulers online (n2), maximum for both\n");
  604. erts_fprintf(stderr, " numbers is %d\n",
  605. ERTS_MAX_NO_OF_SCHEDULERS);
  606. erts_fprintf(stderr, "-SP p1:p2 specify schedulers (p1) and schedulers online (p2)\n");
  607. erts_fprintf(stderr, " as percentages of logical processors configured and logical\n");
  608. erts_fprintf(stderr, " processors available, respectively\n");
  609. erts_fprintf(stderr, "-SDcpu n1:n2 set number of dirty CPU schedulers (n1), and number of\n");
  610. erts_fprintf(stderr, " dirty CPU schedulers online (n2), valid range for both\n");
  611. erts_fprintf(stderr, " numbers is [1-%d], and n2 must be less than or equal to n1\n",
  612. ERTS_MAX_NO_OF_DIRTY_CPU_SCHEDULERS);
  613. erts_fprintf(stderr, "-SDPcpu p1:p2 specify dirty CPU schedulers (p1) and dirty CPU schedulers\n");
  614. erts_fprintf(stderr, " online (p2) as percentages of logical processors configured\n");
  615. erts_fprintf(stderr, " and logical processors available, respectively\n");
  616. erts_fprintf(stderr, "-SDio n set number of dirty I/O schedulers, valid range is [0-%d]\n",
  617. ERTS_MAX_NO_OF_DIRTY_IO_SCHEDULERS);
  618. erts_fprintf(stderr, "-t size set the maximum number of atoms the emulator can handle\n");
  619. erts_fprintf(stderr, " valid range is [%d-%d]\n",
  620. MIN_ATOM_TABLE_SIZE, MAX_ATOM_TABLE_SIZE);
  621. erts_fprintf(stderr, "-T number set modified timing level, valid range is [0-%d]\n",
  622. ERTS_MODIFIED_TIMING_LEVELS-1);
  623. erts_fprintf(stderr, "-V print Erlang version\n");
  624. erts_fprintf(stderr, "-v turn on chatty mode (GCs will be reported etc)\n");
  625. erts_fprintf(stderr, "-W<i|w|e> set error logger warnings mapping,\n");
  626. erts_fprintf(stderr, " see error_logger documentation for details\n");
  627. erts_fprintf(stderr, "-zdbbl size set the distribution buffer busy limit in kilobytes\n");
  628. erts_fprintf(stderr, " valid range is [1-%d]\n", INT_MAX/1024);
  629. erts_fprintf(stderr, "-zdntgc time set delayed node table gc in seconds\n");
  630. erts_fprintf(stderr, " valid values are infinity or intergers in the range [0-%d]\n",
  631. ERTS_NODE_TAB_DELAY_GC_MAX);
  632. #if 0
  633. erts_fprintf(stderr, "-zebwt val set ets busy wait threshold, valid values are:\n");
  634. erts_fprintf(stderr, " none|very_short|short|medium|long|very_long|extremely_long\n");
  635. #endif
  636. erts_fprintf(stderr, "\n");
  637. erts_fprintf(stderr, "Note that if the emulator is started with erlexec (typically\n");
  638. erts_fprintf(stderr, "from the erl script), these flags should be specified with +.\n");
  639. erts_fprintf(stderr, "\n\n");
  640. erts_exit(1, "");
  641. }
  642. /*
  643. * allocators for thread lib
  644. */
  645. static void *ethr_std_alloc(size_t size)
  646. {
  647. return erts_alloc_fnf(ERTS_ALC_T_ETHR_STD, (Uint) size);
  648. }
  649. static void *ethr_std_realloc(void *ptr, size_t size)
  650. {
  651. return erts_realloc_fnf(ERTS_ALC_T_ETHR_STD, ptr, (Uint) size);
  652. }
  653. static void ethr_std_free(void *ptr)
  654. {
  655. erts_free(ERTS_ALC_T_ETHR_STD, ptr);
  656. }
  657. static void *ethr_sl_alloc(size_t size)
  658. {
  659. return erts_alloc_fnf(ERTS_ALC_T_ETHR_SL, (Uint) size);
  660. }
  661. static void *ethr_sl_realloc(void *ptr, size_t size)
  662. {
  663. return erts_realloc_fnf(ERTS_ALC_T_ETHR_SL, ptr, (Uint) size);
  664. }
  665. static void ethr_sl_free(void *ptr)
  666. {
  667. erts_free(ERTS_ALC_T_ETHR_SL, ptr);
  668. }
  669. static void *ethr_ll_alloc(size_t size)
  670. {
  671. return erts_alloc_fnf(ERTS_ALC_T_ETHR_LL, (Uint) size);
  672. }
  673. static void *ethr_ll_realloc(void *ptr, size_t size)
  674. {
  675. return erts_realloc_fnf(ERTS_ALC_T_ETHR_LL, ptr, (Uint) size);
  676. }
  677. static void ethr_ll_free(void *ptr)
  678. {
  679. erts_free(ERTS_ALC_T_ETHR_LL, ptr);
  680. }
  681. static int
  682. early_init(int *argc, char **argv) /*
  683. * Only put things here which are
  684. * really important initialize
  685. * early!
  686. */
  687. {
  688. ErtsAllocInitOpts alloc_opts = ERTS_ALLOC_INIT_DEF_OPTS_INITER;
  689. int ncpu;
  690. int ncpuonln;
  691. int ncpuavail;
  692. int schdlrs;
  693. int schdlrs_onln;
  694. int schdlrs_percentage = 100;
  695. int schdlrs_onln_percentage = 100;
  696. int max_main_threads;
  697. int dirty_cpu_scheds;
  698. int dirty_cpu_scheds_online;
  699. int dirty_cpu_scheds_pctg = 100;
  700. int dirty_cpu_scheds_onln_pctg = 100;
  701. int dirty_io_scheds;
  702. int max_reader_groups;
  703. int reader_groups;
  704. int max_decentralized_counter_groups;
  705. int decentralized_counter_groups;
  706. char envbuf[21]; /* enough for any 64-bit integer */
  707. size_t envbufsz;
  708. erts_save_emu_args(*argc, argv);
  709. erts_sched_compact_load = 1;
  710. erts_printf_eterm_func = erts_printf_term;
  711. erts_backtrace_depth = DEFAULT_BACKTRACE_SIZE;
  712. erts_async_max_threads = ERTS_DEFAULT_NO_ASYNC_THREADS;
  713. erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE;
  714. H_MIN_SIZE = H_DEFAULT_SIZE;
  715. BIN_VH_MIN_SIZE = VH_DEFAULT_SIZE;
  716. H_MAX_SIZE = H_DEFAULT_MAX_SIZE;
  717. H_MAX_FLAGS = MAX_HEAP_SIZE_KILL|MAX_HEAP_SIZE_LOG;
  718. erts_term_init();
  719. erts_initialized = 0;
  720. erts_pre_early_init_cpu_topology(&max_decentralized_counter_groups,
  721. &max_reader_groups,
  722. &ncpu,
  723. &ncpuonln,
  724. &ncpuavail);
  725. ignore_break = 0;
  726. replace_intr = 0;
  727. program = argv[0];
  728. erts_modified_timing_level = -1;
  729. erts_compat_rel = this_rel_num();
  730. erts_sys_pre_init();
  731. erts_atomic_init_nob(&exiting, 0);
  732. erts_thr_progress_pre_init();
  733. erts_atomic32_init_nob(&erts_writing_erl_crash_dump, 0L);
  734. erts_tsd_key_create(&erts_is_crash_dumping_key,"erts_is_crash_dumping_key");
  735. erts_atomic32_init_nob(&erts_max_gen_gcs,
  736. (erts_aint32_t) ((Uint16) -1));
  737. erts_pre_init_process();
  738. /*
  739. * We need to know the number of schedulers to use before we
  740. * can initialize the allocators.
  741. */
  742. no_schedulers = (Uint) (ncpu > 0 ? ncpu : 1);
  743. no_schedulers_online = (ncpuavail > 0
  744. ? ncpuavail
  745. : (ncpuonln > 0 ? ncpuonln : no_schedulers));
  746. schdlrs = no_schedulers;
  747. schdlrs_onln = no_schedulers_online;
  748. dirty_cpu_scheds = no_schedulers;
  749. dirty_cpu_scheds_online = no_schedulers_online;
  750. dirty_io_scheds = 10;
  751. envbufsz = sizeof(envbuf);
  752. /* erts_osenv hasn't been initialized yet, so we need to fall back to
  753. * erts_sys_explicit_host_getenv() */
  754. if (erts_sys_explicit_host_getenv("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 1)
  755. erts_async_max_threads = atoi(envbuf);
  756. else
  757. erts_async_max_threads = ERTS_DEFAULT_NO_ASYNC_THREADS;
  758. if (erts_async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)
  759. erts_async_max_threads = ERTS_MAX_NO_OF_ASYNC_THREADS;
  760. if (argc && argv) {
  761. int i = 1;
  762. while (i < *argc) {
  763. if (sys_strcmp(argv[i], "--") == 0) { /* end of emulator options */
  764. i++;
  765. break;
  766. }
  767. if (argv[i][0] == '-') {
  768. switch (argv[i][1]) {
  769. case 'd': {
  770. char *sub_param = argv[i]+2;
  771. if (has_prefix("cg", sub_param)) {
  772. char *arg = get_arg(sub_param+2, argv[i+1], &i);
  773. if (sscanf(arg, "%d", &max_decentralized_counter_groups) != 1) {
  774. erts_fprintf(stderr,
  775. "bad decentralized counter groups limit: %s\n", arg);
  776. erts_usage();
  777. }
  778. if (max_decentralized_counter_groups < 0) {
  779. erts_fprintf(stderr,
  780. "bad decentralized counter groups limit: %d\n",
  781. max_decentralized_counter_groups);
  782. erts_usage();
  783. }
  784. }
  785. break;
  786. }
  787. case 'r': {
  788. char *sub_param = argv[i]+2;
  789. if (has_prefix("g", sub_param)) {
  790. char *arg = get_arg(sub_param+1, argv[i+1], &i);
  791. if (sscanf(arg, "%d", &max_reader_groups) != 1) {
  792. erts_fprintf(stderr,
  793. "bad reader groups limit: %s\n", arg);
  794. erts_usage();
  795. }
  796. if (max_reader_groups < 0) {
  797. erts_fprintf(stderr,
  798. "bad reader groups limit: %d\n",
  799. max_reader_groups);
  800. erts_usage();
  801. }
  802. }
  803. break;
  804. }
  805. case 'A': {
  806. /* set number of threads in thread pool */
  807. char *arg = get_arg(argv[i]+2, argv[i+1], &i);
  808. if (((erts_async_max_threads = atoi(arg)) < ERTS_MIN_NO_OF_ASYNC_THREADS) ||
  809. (erts_async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)) {
  810. erts_fprintf(stderr,
  811. "bad number of async threads %s\n",
  812. arg);
  813. erts_usage();
  814. VERBOSE(DEBUG_SYSTEM, ("using %d async-threads\n",
  815. erts_async_max_threads));
  816. }
  817. break;
  818. }
  819. case 'S' :
  820. if (argv[i][2] == 'P') {
  821. int ptot, ponln;
  822. char *arg = get_arg(argv[i]+3, argv[i+1], &i);
  823. switch (sscanf(arg, "%d:%d", &ptot, &ponln)) {
  824. case 0:
  825. switch (sscanf(arg, ":%d", &ponln)) {
  826. case 1:
  827. if (ponln < 0)
  828. goto bad_SP;
  829. ptot = 100;
  830. goto chk_SP;
  831. default:
  832. goto bad_SP;
  833. }
  834. case 1:
  835. if (ptot < 0)
  836. goto bad_SP;
  837. ponln = ptot < 100 ? ptot : 100;
  838. goto chk_SP;
  839. case 2:
  840. if (ptot < 0 || ponln < 0)
  841. goto bad_SP;
  842. chk_SP:
  843. schdlrs_percentage = ptot;
  844. schdlrs_onln_percentage = ponln;
  845. break;
  846. default:
  847. bad_SP:
  848. erts_fprintf(stderr,
  849. "bad schedulers percentage specifier %s\n",
  850. arg);
  851. erts_usage();
  852. break;
  853. }
  854. VERBOSE(DEBUG_SYSTEM,
  855. ("using %d:%d scheduler percentages\n",
  856. schdlrs_percentage, schdlrs_onln_percentage));
  857. }
  858. else if (argv[i][2] == 'D') {
  859. char *arg;
  860. char *type = argv[i]+3;
  861. if (sys_strncmp(type, "Pcpu", 4) == 0) {
  862. int ptot, ponln;
  863. arg = get_arg(argv[i]+7, argv[i+1], &i);
  864. switch (sscanf(arg, "%d:%d", &ptot, &ponln)) {
  865. case 0:
  866. switch (sscanf(arg, ":%d", &ponln)) {
  867. case 1:
  868. if (ponln < 0)
  869. goto bad_SDPcpu;
  870. ptot = 100;
  871. goto chk_SDPcpu;
  872. default:
  873. goto bad_SDPcpu;
  874. }
  875. case 1:
  876. if (ptot < 0)
  877. goto bad_SDPcpu;
  878. ponln = ptot < 100 ? ptot : 100;
  879. goto chk_SDPcpu;
  880. case 2:
  881. if (ptot < 0 || ponln < 0)
  882. goto bad_SDPcpu;
  883. chk_SDPcpu:
  884. dirty_cpu_scheds_pctg = ptot;
  885. dirty_cpu_scheds_onln_pctg = ponln;
  886. break;
  887. default:
  888. bad_SDPcpu:
  889. erts_fprintf(stderr,
  890. "bad dirty CPU schedulers percentage specifier %s\n",
  891. arg);
  892. erts_usage();
  893. break;
  894. }
  895. VERBOSE(DEBUG_SYSTEM,
  896. ("using %d:%d dirty CPU scheduler percentages\n",
  897. dirty_cpu_scheds_pctg, dirty_cpu_scheds_onln_pctg));
  898. } else if (sys_strncmp(type, "cpu", 3) == 0) {
  899. int tot, onln;
  900. arg = get_arg(argv[i]+6, argv[i+1], &i);
  901. switch (sscanf(arg, "%d:%d", &tot, &onln)) {
  902. case 0:
  903. switch (sscanf(arg, ":%d", &onln)) {
  904. case 1:
  905. tot = no_schedulers;
  906. goto chk_SDcpu;
  907. default:
  908. goto bad_SDcpu;
  909. }
  910. case 1:
  911. onln = tot < dirty_cpu_scheds_online ?
  912. tot : dirty_cpu_scheds_online;
  913. case 2:
  914. chk_SDcpu:
  915. if (tot > 0)
  916. dirty_cpu_scheds = tot;
  917. else
  918. dirty_cpu_scheds = no_schedulers + tot;
  919. if (onln > 0)
  920. dirty_cpu_scheds_online = onln;
  921. else
  922. dirty_cpu_scheds_online = no_schedulers_online + onln;
  923. if (dirty_cpu_scheds < 1 ||
  924. ERTS_MAX_NO_OF_DIRTY_CPU_SCHEDULERS < dirty_cpu_scheds) {
  925. erts_fprintf(stderr,
  926. "bad amount of dirty CPU schedulers %d\n",
  927. tot);
  928. erts_usage();
  929. }
  930. if (dirty_cpu_scheds_online < 1 ||
  931. dirty_cpu_scheds < dirty_cpu_scheds_online) {
  932. erts_fprintf(stderr,
  933. "bad amount of dirty CPU schedulers online %d "
  934. "(total amount of dirty CPU schedulers %d)\n",
  935. dirty_cpu_scheds_online, dirty_cpu_scheds);
  936. erts_usage();
  937. }
  938. break;
  939. default:
  940. bad_SDcpu:
  941. erts_fprintf(stderr,
  942. "bad amount of dirty CPU schedulers %s\n",
  943. arg);
  944. erts_usage();
  945. break;
  946. }
  947. VERBOSE(DEBUG_SYSTEM,
  948. ("using %d:%d dirty CPU scheduler(s)\n", tot, onln));
  949. } else if (sys_strncmp(type, "io", 2) == 0) {
  950. arg = get_arg(argv[i]+5, argv[i+1], &i);
  951. dirty_io_scheds = atoi(arg);
  952. if (dirty_io_scheds < 0 ||
  953. dirty_io_scheds > ERTS_MAX_NO_OF_DIRTY_IO_SCHEDULERS) {
  954. erts_fprintf(stderr,
  955. "bad number of dirty I/O schedulers %s\n",
  956. arg);
  957. erts_usage();
  958. }
  959. VERBOSE(DEBUG_SYSTEM,
  960. ("using %d dirty I/O scheduler(s)\n", dirty_io_scheds));
  961. } else {
  962. erts_fprintf(stderr,
  963. "bad or missing dirty scheduler specifier: %s\n",
  964. argv[i]);
  965. erts_usage();
  966. break;
  967. }
  968. }
  969. else {
  970. int tot, onln;
  971. char *arg = get_arg(argv[i]+2, argv[i+1], &i);
  972. switch (sscanf(arg, "%d:%d", &tot, &onln)) {
  973. case 0:
  974. switch (sscanf(arg, ":%d", &onln)) {
  975. case 1:
  976. tot = no_schedulers;
  977. goto chk_S;
  978. default:
  979. goto bad_S;
  980. }
  981. case 1:
  982. onln = tot < schdlrs_onln ? tot : schdlrs_onln;
  983. case 2:
  984. chk_S:
  985. if (tot > 0)
  986. schdlrs = tot;
  987. else
  988. schdlrs = no_schedulers + tot;
  989. if (onln > 0)
  990. schdlrs_onln = onln;
  991. else
  992. schdlrs_onln = no_schedulers_online + onln;
  993. if (schdlrs < 1 || ERTS_MAX_NO_OF_SCHEDULERS < schdlrs) {
  994. erts_fprintf(stderr,
  995. "bad amount of schedulers %d\n",
  996. tot);
  997. erts_usage();
  998. }
  999. if (schdlrs_onln < 1 || schdlrs < schdlrs_onln) {
  1000. erts_fprintf(stderr,
  1001. "bad amount of schedulers online %d "
  1002. "(total amount of schedulers %d)\n",
  1003. schdlrs_onln, schdlrs);
  1004. erts_usage();
  1005. }
  1006. break;
  1007. default:
  1008. bad_S:
  1009. erts_fprintf(stderr,
  1010. "bad amount of schedulers %s\n",
  1011. arg);
  1012. erts_usage();
  1013. break;
  1014. }
  1015. VERBOSE(DEBUG_SYSTEM,
  1016. ("using %d:%d scheduler(s)\n", tot, onln));
  1017. }
  1018. break;
  1019. default:
  1020. break;
  1021. }
  1022. }
  1023. i++;
  1024. }
  1025. /* apply any scheduler percentages */
  1026. if (schdlrs_percentage != 100 || schdlrs_onln_percentage != 100) {
  1027. schdlrs = schdlrs * schdlrs_percentage / 100;
  1028. schdlrs_onln = schdlrs_onln * schdlrs_onln_percentage / 100;
  1029. if (schdlrs < 1)
  1030. schdlrs = 1;
  1031. if (ERTS_MAX_NO_OF_SCHEDULERS < schdlrs) {
  1032. erts_fprintf(stderr,
  1033. "bad schedulers percentage %d "
  1034. "(total amount of schedulers %d)\n",
  1035. schdlrs_percentage, schdlrs);
  1036. erts_usage();
  1037. }
  1038. if (schdlrs_onln < 1)
  1039. schdlrs_onln = 1;
  1040. if (schdlrs < schdlrs_onln) {
  1041. erts_fprintf(stderr,
  1042. "bad schedulers online percentage %d "
  1043. "(total amount of schedulers %d, online %d)\n",
  1044. schdlrs_onln_percentage, schdlrs, schdlrs_onln);
  1045. erts_usage();
  1046. }
  1047. }
  1048. /* apply any dirty scheduler precentages */
  1049. if (dirty_cpu_scheds_pctg != 100 || dirty_cpu_scheds_onln_pctg != 100) {
  1050. dirty_cpu_scheds = dirty_cpu_scheds * dirty_cpu_scheds_pctg / 100;
  1051. dirty_cpu_scheds_online = dirty_cpu_scheds_online * dirty_cpu_scheds_onln_pctg / 100;
  1052. }
  1053. if (dirty_cpu_scheds > schdlrs)
  1054. dirty_cpu_scheds = schdlrs;
  1055. if (dirty_cpu_scheds < 1)
  1056. dirty_cpu_scheds = 1;
  1057. if (dirty_cpu_scheds_online > schdlrs_onln)
  1058. dirty_cpu_scheds_online = schdlrs_onln;
  1059. if (dirty_cpu_scheds_online < 1)
  1060. dirty_cpu_scheds_online = 1;
  1061. }
  1062. no_schedulers = schdlrs;
  1063. no_schedulers_online = schdlrs_onln;
  1064. erts_no_schedulers = (Uint) no_schedulers;
  1065. erts_no_dirty_cpu_schedulers = no_dirty_cpu_schedulers = dirty_cpu_scheds;
  1066. no_dirty_cpu_schedulers_online = dirty_cpu_scheds_online;
  1067. erts_no_dirty_io_schedulers = no_dirty_io_schedulers = dirty_io_scheds;
  1068. erts_early_init_scheduling(no_schedulers);
  1069. alloc_opts.ncpu = ncpu;
  1070. erts_alloc_init(argc, argv, &alloc_opts); /* Handles (and removes)
  1071. -M flags. */
  1072. /* Require allocators */
  1073. erts_init_check_io(argc, argv);
  1074. /*
  1075. * Thread progress management:
  1076. *
  1077. * * Managed threads:
  1078. * ** Scheduler threads (see erl_process.c)
  1079. * ** Aux thread (see erl_process.c)
  1080. * ** Sys message dispatcher thread (see erl_trace.c)
  1081. * ** IO Poll threads (see erl_check_io.c)
  1082. *
  1083. * * Unmanaged threads that need to register:
  1084. * ** Async threads (see erl_async.c)
  1085. * ** Dirty scheduler threads
  1086. */
  1087. erts_thr_progress_init(no_schedulers,
  1088. no_schedulers+2+erts_no_poll_threads,
  1089. erts_async_max_threads +
  1090. erts_no_dirty_cpu_schedulers +
  1091. erts_no_dirty_io_schedulers
  1092. );
  1093. erts_thr_q_init();
  1094. erts_init_utils();
  1095. erts_early_init_cpu_topology(no_schedulers,
  1096. &max_main_threads,
  1097. max_reader_groups,
  1098. &reader_groups,
  1099. max_decentralized_counter_groups,
  1100. &decentralized_counter_groups);
  1101. erts_flxctr_setup(decentralized_counter_groups);
  1102. {
  1103. erts_thr_late_init_data_t elid = ERTS_THR_LATE_INIT_DATA_DEF_INITER;
  1104. elid.mem.std.alloc = ethr_std_alloc;
  1105. elid.mem.std.realloc = ethr_std_realloc;
  1106. elid.mem.std.free = ethr_std_free;
  1107. elid.mem.sl.alloc = ethr_sl_alloc;
  1108. elid.mem.sl.realloc = ethr_sl_realloc;
  1109. elid.mem.sl.free = ethr_sl_free;
  1110. elid.mem.ll.alloc = ethr_ll_alloc;
  1111. elid.mem.ll.realloc = ethr_ll_realloc;
  1112. elid.mem.ll.free = ethr_ll_free;
  1113. elid.main_threads = max_main_threads;
  1114. elid.reader_groups = reader_groups;
  1115. erts_thr_late_init(&elid);
  1116. }
  1117. erts_msacc_early_init();
  1118. #ifdef ERTS_ENABLE_LOCK_CHECK
  1119. erts_lc_late_init();
  1120. #endif
  1121. #ifdef ERTS_ENABLE_LOCK_COUNT
  1122. erts_lcnt_late_init();
  1123. #endif
  1124. #if defined(HIPE)
  1125. hipe_signal_init(); /* must be done very early */
  1126. #endif
  1127. erl_sys_args(argc, argv);
  1128. /* Creates threads on Windows that depend on the arguments, so has to be after erl_sys_args */
  1129. erl_sys_init();
  1130. erts_ets_realloc_always_moves = 0;
  1131. erts_ets_always_compress = 0;
  1132. erts_dist_buf_busy_limit = ERTS_DE_BUSY_LIMIT;
  1133. return ncpu;
  1134. }
  1135. void
  1136. erl_start(int argc, char **argv)
  1137. {
  1138. int i = 1;
  1139. char* arg=NULL;
  1140. int have_break_handler = 1;
  1141. char envbuf[21]; /* enough for any 64-bit integer */
  1142. size_t envbufsz;
  1143. int ncpu = early_init(&argc, argv);
  1144. int proc_tab_sz = ERTS_DEFAULT_MAX_PROCESSES;
  1145. int port_tab_sz = ERTS_DEFAULT_MAX_PORTS;
  1146. int port_tab_sz_ignore_files = 0;
  1147. int legacy_proc_tab = 0;
  1148. int legacy_port_tab = 0;
  1149. int time_correction;
  1150. ErtsTimeWarpMode time_warp_mode;
  1151. int node_tab_delete_delay = ERTS_NODE_TAB_DELAY_GC_DEFAULT;
  1152. ErtsDbSpinCount db_spin_count = ERTS_DB_SPNCNT_NORMAL;
  1153. set_default_time_adj(&time_correction,
  1154. &time_warp_mode);
  1155. envbufsz = sizeof(envbuf);
  1156. if (erts_sys_explicit_8bit_getenv(ERL_MAX_ETS_TABLES_ENV, envbuf, &envbufsz) == 1)
  1157. user_requested_db_max_tabs = atoi(envbuf);
  1158. else
  1159. user_requested_db_max_tabs = 0;
  1160. envbufsz = sizeof(envbuf);
  1161. if (erts_sys_explicit_8bit_getenv("ERL_FULLSWEEP_AFTER", envbuf, &envbufsz) == 1) {
  1162. Uint16 max_gen_gcs = atoi(envbuf);
  1163. erts_atomic32_set_nob(&erts_max_gen_gcs,
  1164. (erts_aint32_t) max_gen_gcs);
  1165. }
  1166. envbufsz = sizeof(envbuf);
  1167. if (erts_sys_explicit_8bit_getenv("ERL_MAX_PORTS", envbuf, &envbufsz) == 1) {
  1168. port_tab_sz = atoi(envbuf);
  1169. port_tab_sz_ignore_files = 1;
  1170. }
  1171. /*
  1172. * A default stack size suitable for pcre which might use quite
  1173. * a lot of stack.
  1174. */
  1175. erts_sched_thread_suggested_stack_size = ERTS_DEFAULT_SCHED_STACK_SIZE;
  1176. erts_dcpu_sched_thread_suggested_stack_size = ERTS_DEFAULT_DCPU_SCHED_STACK_SIZE;
  1177. erts_dio_sched_thread_suggested_stack_size = ERTS_DEFAULT_DIO_SCHED_STACK_SIZE;
  1178. #ifdef DEBUG
  1179. verbose = DEBUG_DEFAULT;
  1180. #endif
  1181. erts_error_logger_warnings = am_warning;
  1182. while (i < argc) {
  1183. if (argv[i][0] != '-') {
  1184. erts_usage();
  1185. }
  1186. if (sys_strcmp(argv[i], "--") == 0) { /* end of emulator options */
  1187. i++;
  1188. break;
  1189. }
  1190. switch (argv[i][1]) {
  1191. /*
  1192. * NOTE: -M flags are handled (and removed from argv) by
  1193. * erts_alloc_init().
  1194. */
  1195. case 'p':
  1196. if (!sys_strncmp(argv[i],"-pc",3)) {
  1197. int printable_chars = ERL_PRINTABLE_CHARACTERS_LATIN1;
  1198. arg = get_arg(argv[i]+3, argv[i+1], &i);
  1199. if (!sys_strcmp(arg,"unicode")) {
  1200. printable_chars = ERL_PRINTABLE_CHARACTERS_UNICODE;
  1201. } else if (sys_strcmp(arg,"latin1")) {
  1202. erts_fprintf(stderr, "bad range of printable "
  1203. "characters: %s\n", arg);
  1204. erts_usage();
  1205. }
  1206. erts_set_printable_characters(printable_chars);
  1207. break;
  1208. } else {
  1209. erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
  1210. erts_usage();
  1211. }
  1212. case 'f':
  1213. if (!sys_strncmp(argv[i],"-fn",3)) {
  1214. int warning_type = ERL_FILENAME_WARNING_WARNING;
  1215. arg = get_arg(argv[i]+3, argv[i+1], &i);
  1216. switch (*arg) {
  1217. case 'u':
  1218. switch (*(arg+1)) {
  1219. case 'w':
  1220. case 0:
  1221. break;
  1222. case 'i':
  1223. warning_type = ERL_FILENAME_WARNING_IGNORE;
  1224. break;
  1225. case 'e':
  1226. warning_type = ERL_FILENAME_WARNING_ERROR;
  1227. break;
  1228. default:
  1229. erts_fprintf(stderr, "bad type of warnings for "
  1230. "wrongly coded filename: %s\n", arg+1);
  1231. erts_usage();
  1232. }
  1233. erts_set_user_requested_filename_encoding
  1234. (
  1235. ERL_FILENAME_UTF8,
  1236. warning_type
  1237. );
  1238. break;
  1239. case 'l':
  1240. erts_set_user_requested_filename_encoding
  1241. (
  1242. ERL_FILENAME_LATIN1,
  1243. warning_type
  1244. );
  1245. break;
  1246. case 'a':
  1247. switch (*(arg+1)) {
  1248. case 'w':
  1249. case 0:
  1250. break;
  1251. case 'i':
  1252. warning_type = ERL_FILENAME_WARNING_IGNORE;
  1253. break;
  1254. case 'e':
  1255. warning_type = ERL_FILENAME_WARNING_ERROR;
  1256. break;
  1257. default:
  1258. erts_fprintf(stderr, "bad type of warnings for "
  1259. "wrongly coded filename: %s\n", arg+1);
  1260. erts_usage();
  1261. }
  1262. erts_set_user_requested_filename_encoding
  1263. (
  1264. ERL_FILENAME_UNKNOWN,
  1265. warning_type
  1266. );
  1267. break;
  1268. default:
  1269. erts_fprintf(stderr, "bad filename encoding %s, can be "
  1270. "(l,u or a, optionally followed by w, "
  1271. "i or e)\n", arg);
  1272. erts_usage();
  1273. }
  1274. break;
  1275. } else {
  1276. erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
  1277. erts_usage();
  1278. }
  1279. case 'L':
  1280. erts_no_line_info = 1;
  1281. break;
  1282. case 'v':
  1283. #ifdef DEBUG
  1284. if (argv[i][2] == '\0') {
  1285. verbose |= DEBUG_SYSTEM;
  1286. } else {
  1287. char *ch;
  1288. for (ch = argv[i]+2; *ch != '\0'; ch++) {
  1289. switch (*ch) {
  1290. case 's': verbose |= DEBUG_SYSTEM; break;
  1291. case 'g': verbose |= DEBUG_PRIVATE_GC; break;
  1292. case 'M': verbose |= DEBUG_MEMORY; break;
  1293. case 'a': verbose |= DEBUG_ALLOCATION; break;
  1294. case 't': verbose |= DEBUG_THREADS; break;
  1295. case 'p': verbose |= DEBUG_PROCESSES; break;
  1296. case 'm': verbose |= DEBUG_MESSAGES; break;
  1297. case 'c': verbose |= DEBUG_SHCOPY; break;
  1298. default : erts_fprintf(stderr,"Unknown verbose option: %c\n",*ch);
  1299. }
  1300. }
  1301. }
  1302. erts_printf("Verbose level: ");
  1303. if (verbose & DEBUG_SYSTEM) erts_printf("SYSTEM ");
  1304. if (verbose & DEBUG_PRIVATE_GC) erts_printf("PRIVATE_GC ");
  1305. if (verbose & DEBUG_MEMORY) erts_printf("PARANOID_MEMORY ");
  1306. if (verbose & DEBUG_ALLOCATION) erts_printf("ALLOCATION ");
  1307. if (verbose & DEBUG_THREADS) erts_printf("THREADS ");
  1308. if (verbose & DEBUG_PROCESSES) erts_printf("PROCESSES ");
  1309. if (verbose & DEBUG_MESSAGES) erts_printf("MESSAGES ");
  1310. if (verbose & DEBUG_SHCOPY) erts_printf("SHCOPY ");
  1311. erts_printf("\n");
  1312. #else
  1313. erts_fprintf(stderr, "warning: -v (only in debug compiled code)\n");
  1314. #endif
  1315. break;
  1316. case 'V' :
  1317. {
  1318. char tmp[256];
  1319. tmp[0] = tmp[1] = '\0';
  1320. #ifdef DEBUG
  1321. strcat(tmp, ",DEBUG");
  1322. #endif
  1323. strcat(tmp, ",SMP");
  1324. strcat(tmp, ",ASYNC_THREADS");
  1325. #ifdef HIPE
  1326. strcat(tmp, ",HIPE");
  1327. #endif
  1328. erts_fprintf(stderr, "Erlang ");
  1329. if (tmp[1]) {
  1330. erts_fprintf(stderr, "(%s) ", tmp+1);
  1331. }
  1332. erts_fprintf(stderr, "(" EMULATOR ") emulator version "
  1333. ERLANG_VERSION "\n");
  1334. erts_exit(0, "");
  1335. }
  1336. break;
  1337. case 'H': /* undocumented */
  1338. fprintf(stderr, "The undocumented +H option has been removed (R10B-6).\n\n");
  1339. break;
  1340. case 'h': {
  1341. char *sub_param = argv[i]+2;
  1342. /* set default heap size
  1343. *
  1344. * h|ms - min_heap_size
  1345. * h|mbs - min_bin_vheap_size
  1346. * h|pds - erts_pd_initial_size
  1347. * h|mqd - message_queue_data
  1348. * h|max - max_heap_size
  1349. * h|maxk - max_heap_kill
  1350. * h|maxel - max_heap_error_logger
  1351. *
  1352. */
  1353. if (has_prefix("mbs", sub_param)) {
  1354. arg = get_arg(sub_param+3, argv[i+1], &i);
  1355. if ((BIN_VH_MIN_SIZE = atoi(arg)) <= 0) {
  1356. erts_fprintf(stderr, "bad heap size %s\n", arg);
  1357. erts_usage();
  1358. }
  1359. VERBOSE(DEBUG_SYSTEM, ("using minimum binary virtual heap size %d\n", BIN_VH_MIN_SIZE));
  1360. } else if (has_prefix("ms", sub_param)) {
  1361. arg = get_arg(sub_param+2, argv[i+1], &i);
  1362. if ((H_MIN_SIZE = atoi(arg)) <= 0) {
  1363. erts_fprintf(stderr, "bad heap size %s\n", arg);
  1364. erts_usage();
  1365. }
  1366. VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE));
  1367. } else if (has_prefix("pds", sub_param)) {
  1368. arg = get_arg(sub_param+3, argv[i+1], &i);
  1369. if (!erts_pd_set_initial_size(atoi(arg))) {
  1370. erts_fprintf(stderr, "bad initial process dictionary size %s\n", arg);
  1371. erts_usage();
  1372. }
  1373. VERBOSE(DEBUG_SYSTEM, ("using initial process dictionary size %d\n",
  1374. erts_pd_initial_size));
  1375. } else if (has_prefix("mqd", sub_param)) {
  1376. arg = get_arg(sub_param+3, argv[i+1], &i);
  1377. if (sys_strcmp(arg, "on_heap") == 0) {
  1378. erts_default_spo_flags &= ~SPO_OFF_HEAP_MSGQ;
  1379. erts_default_spo_flags |= SPO_ON_HEAP_MSGQ;
  1380. }
  1381. else if (sys_strcmp(arg, "off_heap") == 0) {
  1382. erts_default_spo_flags &= ~SPO_ON_HEAP_MSGQ;
  1383. erts_default_spo_flags |= SPO_OFF_HEAP_MSGQ;
  1384. }
  1385. else {
  1386. erts_fprintf(stderr,
  1387. "Invalid message_queue_data flag: %s\n", arg);
  1388. erts_usage();
  1389. }
  1390. } else if (has_prefix("maxk", sub_param)) {
  1391. arg = get_arg(sub_param+4, argv[i+1], &i);
  1392. if (sys_strcmp(arg,"true") == 0) {
  1393. H_MAX_FLAGS |= MAX_HEAP_SIZE_KILL;
  1394. } else if (sys_strcmp(arg,"false") == 0) {
  1395. H_MAX_FLAGS &= ~MAX_HEAP_SIZE_KILL;
  1396. } else {
  1397. erts_fprintf(stderr, "bad max heap kill %s\n", arg);
  1398. erts_usage();
  1399. }
  1400. VERBOSE(DEBUG_SYSTEM, ("using max heap kill %d\n", H_MAX_FLAGS));
  1401. } else if (has_prefix("maxel", sub_param)) {
  1402. arg = get_arg(sub_param+5, argv[i+1], &i);
  1403. if (sys_strcmp(arg,"true") == 0) {
  1404. H_MAX_FLAGS |= MAX_HEAP_SIZE_LOG;
  1405. } else if (sys_strcmp(arg,"false") == 0) {
  1406. H_MAX_FLAGS &= ~MAX_HEAP_SIZE_LOG;
  1407. } else {
  1408. erts_fprintf(stderr, "bad max heap error logger %s\n", arg);
  1409. erts_usage();
  1410. }
  1411. VERBOSE(DEBUG_SYSTEM, ("using max heap log %d\n", H_MAX_FLAGS));
  1412. } else if (has_prefix("max", sub_param)) {
  1413. arg = get_arg(sub_param+3, argv[i+1], &i);
  1414. if ((H_MAX_SIZE = atoi(arg)) < 0) {
  1415. erts_fprintf(stderr, "bad max heap size %s\n", arg);
  1416. erts_usage();
  1417. }
  1418. if (H_MAX_SIZE < H_MIN_SIZE && H_MAX_SIZE) {
  1419. erts_fprintf(stderr, "max heap size (%s) is not allowed to be "
  1420. "smaller than min heap size (%d)\n",
  1421. arg, H_MIN_SIZE);
  1422. erts_usage();
  1423. }
  1424. VERBOSE(DEBUG_SYSTEM, ("using max heap size %d\n", H_MAX_SIZE));
  1425. } else {
  1426. /* backward compatibility */
  1427. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1428. if ((H_MIN_SIZE = atoi(arg)) <= 0) {
  1429. erts_fprintf(stderr, "bad heap size %s\n", arg);
  1430. erts_usage();
  1431. }
  1432. VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE));
  1433. }
  1434. break;
  1435. }
  1436. case 'd':
  1437. /*
  1438. * Never produce crash dumps for internally detected
  1439. * errors; only produce a core dump. (Generation of
  1440. * crash dumps is destructive and makes it impossible
  1441. * to inspect the contents of process heaps in the
  1442. * core dump.)
  1443. */
  1444. erts_no_crash_dump = 1;
  1445. break;
  1446. case 'e':
  1447. if (sys_strcmp("c", argv[i]+2) == 0) {
  1448. erts_ets_always_compress = 1;
  1449. }
  1450. else {
  1451. /* set maximum number of ets tables */
  1452. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1453. if (( user_requested_db_max_tabs = atoi(arg) ) < 0) {
  1454. erts_fprintf(stderr, "bad maximum number of ets tables %s\n", arg);
  1455. erts_usage();
  1456. }
  1457. VERBOSE(DEBUG_SYSTEM,
  1458. ("using maximum number of ets tables %d\n",
  1459. user_requested_db_max_tabs));
  1460. }
  1461. break;
  1462. case 'i':
  1463. /* define name of module for initial function */
  1464. init = get_arg(argv[i]+2, argv[i+1], &i);
  1465. break;
  1466. case 'B':
  1467. if (argv[i][2] == 'i') /* +Bi */
  1468. ignore_break = 1;
  1469. else if (argv[i][2] == 'c') /* +Bc */
  1470. replace_intr = 1;
  1471. else if (argv[i][2] == 'd') /* +Bd */
  1472. have_break_handler = 0;
  1473. else if (argv[i+1][0] == 'i') { /* +B i */
  1474. get_arg(argv[i]+2, argv[i+1], &i);
  1475. ignore_break = 1;
  1476. }
  1477. else if (argv[i+1][0] == 'c') { /* +B c */
  1478. get_arg(argv[i]+2, argv[i+1], &i);
  1479. replace_intr = 1;
  1480. }
  1481. else if (argv[i+1][0] == 'd') { /* +B d */
  1482. get_arg(argv[i]+2, argv[i+1], &i);
  1483. have_break_handler = 0;
  1484. }
  1485. else /* +B */
  1486. have_break_handler = 0;
  1487. break;
  1488. case 'n':
  1489. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1490. switch (arg[0]) {
  1491. case 's': /* synchronous */
  1492. erts_port_synchronous_ops = 1;
  1493. erts_port_schedule_all_ops = 0;
  1494. break;
  1495. case 'a': /* asynchronous */
  1496. erts_port_synchronous_ops = 0;
  1497. erts_port_schedule_all_ops = 1;
  1498. break;
  1499. case 'd': /* Default - schedule on conflict (asynchronous) */
  1500. erts_port_synchronous_ops = 0;
  1501. erts_port_schedule_all_ops = 0;
  1502. break;
  1503. default:
  1504. bad_n_option:
  1505. erts_fprintf(stderr, "bad -n option %s\n", arg);
  1506. erts_usage();
  1507. }
  1508. if (arg[1] != '\0')
  1509. goto bad_n_option;
  1510. break;
  1511. case 'P': /* set maximum number of processes */
  1512. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1513. if (sys_strcmp(arg, "legacy") == 0)
  1514. legacy_proc_tab = 1;
  1515. else {
  1516. errno = 0;
  1517. proc_tab_sz = strtol(arg, NULL, 10);
  1518. if (errno != 0
  1519. || proc_tab_sz < ERTS_MIN_PROCESSES
  1520. || ERTS_MAX_PROCESSES < proc_tab_sz) {
  1521. erts_fprintf(stderr, "bad number of processes %s\n", arg);
  1522. erts_usage();
  1523. }
  1524. }
  1525. break;
  1526. case 'Q': /* set maximum number of ports */
  1527. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1528. if (sys_strcmp(arg, "legacy") == 0)
  1529. legacy_port_tab = 1;
  1530. else {
  1531. errno = 0;
  1532. port_tab_sz = strtol(arg, NULL, 10);
  1533. if (errno != 0
  1534. || port_tab_sz < ERTS_MIN_PROCESSES
  1535. || ERTS_MAX_PROCESSES < port_tab_sz) {
  1536. erts_fprintf(stderr, "bad number of ports %s\n", arg);
  1537. erts_usage();
  1538. }
  1539. port_tab_sz_ignore_files = 1;
  1540. }
  1541. break;
  1542. case 'S' : /* Was handled in early_init() just read past it */
  1543. if (argv[i][2] == 'D') {
  1544. char* type = argv[i]+3;
  1545. if (sys_strcmp(type, "Pcpu") == 0)
  1546. (void) get_arg(argv[i]+7, argv[i+1], &i);
  1547. if (sys_strcmp(type, "cpu") == 0)
  1548. (void) get_arg(argv[i]+6, argv[i+1], &i);
  1549. else if (sys_strcmp(type, "io") == 0)
  1550. (void) get_arg(argv[i]+5, argv[i+1], &i);
  1551. } else if (argv[i][2] == 'P')
  1552. (void) get_arg(argv[i]+3, argv[i+1], &i);
  1553. else
  1554. (void) get_arg(argv[i]+2, argv[i+1], &i);
  1555. break;
  1556. case 's' : {
  1557. char *estr;
  1558. int res;
  1559. char *sub_param = argv[i]+2;
  1560. if (has_prefix("bt", sub_param)) {
  1561. arg = get_arg(sub_param+2, argv[i+1], &i);
  1562. res = erts_init_scheduler_bind_type_string(arg);
  1563. if (res != ERTS_INIT_SCHED_BIND_TYPE_SUCCESS) {
  1564. switch (res) {
  1565. case ERTS_INIT_SCHED_BIND_TYPE_NOT_SUPPORTED:
  1566. estr = "not supported";
  1567. break;
  1568. case ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_CPU_TOPOLOGY:
  1569. estr = "no cpu topology available";
  1570. break;
  1571. case ERTS_INIT_SCHED_BIND_TYPE_ERROR_BAD_TYPE:
  1572. estr = "invalid type";
  1573. break;
  1574. default:
  1575. estr = "undefined error";
  1576. break;
  1577. }
  1578. erts_fprintf(stderr,
  1579. "setting scheduler bind type '%s' failed: %s\n",
  1580. arg,
  1581. estr);
  1582. erts_usage();
  1583. }
  1584. }
  1585. else if (has_prefix("bwtdcpu", sub_param)) {
  1586. arg = get_arg(sub_param + 7, argv[i+1], &i);
  1587. if (erts_sched_set_busy_wait_threshold(ERTS_SCHED_DIRTY_CPU, arg) != 0) {
  1588. erts_fprintf(stderr, "bad dirty CPU scheduler busy wait threshold: %s\n",
  1589. arg);
  1590. erts_usage();
  1591. }
  1592. VERBOSE(DEBUG_SYSTEM,
  1593. ("dirty CPU scheduler wakeup threshold: %s\n", arg));
  1594. }
  1595. else if (has_prefix("bwtdio", sub_param)) {
  1596. arg = get_arg(sub_param + 6, argv[i+1], &i);
  1597. if (erts_sched_set_busy_wait_threshold(ERTS_SCHED_DIRTY_IO, arg) != 0) {
  1598. erts_fprintf(stderr, "bad dirty IO scheduler busy wait threshold: %s\n",
  1599. arg);
  1600. erts_usage();
  1601. }
  1602. VERBOSE(DEBUG_SYSTEM,
  1603. ("dirty IO scheduler wakeup threshold: %s\n", arg));
  1604. }
  1605. else if (has_prefix("bwt", sub_param)) {
  1606. arg = get_arg(sub_param + 3, argv[i+1], &i);
  1607. if (erts_sched_set_busy_wait_threshold(ERTS_SCHED_NORMAL, arg) != 0) {
  1608. erts_fprintf(stderr, "bad scheduler busy wait threshold: %s\n",
  1609. arg);
  1610. erts_usage();
  1611. }
  1612. VERBOSE(DEBUG_SYSTEM,
  1613. ("scheduler wakeup threshold: %s\n", arg));
  1614. }
  1615. else if (has_prefix("cl", sub_param)) {
  1616. arg = get_arg(sub_param+2, argv[i+1], &i);
  1617. if (sys_strcmp("true", arg) == 0) {
  1618. erts_sched_compact_load = 1;
  1619. erts_sched_balance_util = 0;
  1620. }
  1621. else if (sys_strcmp("false", arg) == 0)
  1622. erts_sched_compact_load = 0;
  1623. else {
  1624. erts_fprintf(stderr,
  1625. "bad scheduler compact load value '%s'\n",
  1626. arg);
  1627. erts_usage();
  1628. }
  1629. }
  1630. else if (has_prefix("ct", sub_param)) {
  1631. arg = get_arg(sub_param+2, argv[i+1], &i);
  1632. res = erts_init_cpu_topology_string(arg);
  1633. if (res != ERTS_INIT_CPU_TOPOLOGY_OK) {
  1634. switch (res) {
  1635. case ERTS_INIT_CPU_TOPOLOGY_INVALID_ID:
  1636. estr = "invalid identifier";
  1637. break;
  1638. case ERTS_INIT_CPU_TOPOLOGY_INVALID_ID_RANGE:
  1639. estr = "invalid identifier range";
  1640. break;
  1641. case ERTS_INIT_CPU_TOPOLOGY_INVALID_HIERARCHY:
  1642. estr = "invalid hierarchy";
  1643. break;
  1644. case ERTS_INIT_CPU_TOPOLOGY_INVALID_ID_TYPE:
  1645. estr = "invalid identifier type";
  1646. break;
  1647. case ERTS_INIT_CPU_TOPOLOGY_INVALID_NODES:
  1648. estr = "invalid nodes declaration";
  1649. break;
  1650. case ERTS_INIT_CPU_TOPOLOGY_MISSING_LID:
  1651. estr = "missing logical identifier";
  1652. break;
  1653. case ERTS_INIT_CPU_TOPOLOGY_NOT_UNIQUE_LIDS:
  1654. estr = "not unique logical identifiers";
  1655. break;
  1656. case ERTS_INIT_CPU_TOPOLOGY_NOT_UNIQUE_ENTITIES:
  1657. estr = "not unique entities";
  1658. break;
  1659. case ERTS_INIT_CPU_TOPOLOGY_MISSING:
  1660. estr = "missing cpu topology";
  1661. break;
  1662. default:
  1663. estr = "undefined error";
  1664. break;
  1665. }
  1666. erts_fprintf(stderr,
  1667. "bad cpu topology '%s': %s\n",
  1668. arg,
  1669. estr);
  1670. erts_usage();
  1671. }
  1672. }
  1673. else if (has_prefix("ecio", sub_param)) {
  1674. /* ignore argument, eager check io no longer used */
  1675. arg = get_arg(sub_param+4, argv[i+1], &i);
  1676. }
  1677. else if (has_prefix("pp", sub_param)) {
  1678. arg = get_arg(sub_param+2, argv[i+1], &i);
  1679. if (sys_strcmp(arg, "true") == 0)
  1680. erts_port_parallelism = 1;
  1681. else if (sys_strcmp(arg, "false") == 0)
  1682. erts_port_parallelism = 0;
  1683. else {
  1684. erts_fprintf(stderr,
  1685. "bad port parallelism scheduling hint %s\n",
  1686. arg);
  1687. erts_usage();
  1688. }
  1689. }
  1690. else if (has_prefix("tbt", sub_param)) {
  1691. arg = get_arg(sub_param+3, argv[i+1], &i);
  1692. res = erts_init_scheduler_bind_type_string(arg);
  1693. if (res == ERTS_INIT_SCHED_BIND_TYPE_ERROR_BAD_TYPE) {
  1694. erts_fprintf(stderr,
  1695. "setting scheduler bind type '%s' failed: invalid type\n",
  1696. arg);
  1697. erts_usage();
  1698. }
  1699. }
  1700. else if (has_prefix("ub", sub_param)) {
  1701. arg = get_arg(sub_param+2, argv[i+1], &i);
  1702. if (sys_strcmp("true", arg) == 0) {
  1703. #if ERTS_HAVE_SCHED_UTIL_BALANCING_SUPPORT_OPT
  1704. erts_sched_balance_util = 1;
  1705. #else
  1706. erts_fprintf(stderr,
  1707. "scheduler utilization balancing not "
  1708. "supported on this system\n");
  1709. erts_usage();
  1710. #endif
  1711. }
  1712. else if (sys_strcmp("false", arg) == 0)
  1713. erts_sched_balance_util = 0;
  1714. else {
  1715. erts_fprintf(stderr, "bad scheduler utilization balancing "
  1716. " value '%s'\n", arg);
  1717. erts_usage();
  1718. }
  1719. }
  1720. else if (has_prefix("wct", sub_param)) {
  1721. arg = get_arg(sub_param+3, argv[i+1], &i);
  1722. if (erts_sched_set_wake_cleanup_threshold(arg) != 0) {
  1723. erts_fprintf(stderr, "scheduler wake cleanup threshold: %s\n",
  1724. arg);
  1725. erts_usage();
  1726. }
  1727. VERBOSE(DEBUG_SYSTEM,
  1728. ("scheduler wake cleanup threshold: %s\n", arg));
  1729. }
  1730. else if (has_prefix("wtdcpu", sub_param)) {
  1731. arg = get_arg(sub_param+6, argv[i+1], &i);
  1732. if (erts_sched_set_wakeup_other_threshold(ERTS_SCHED_DIRTY_CPU, arg) != 0) {
  1733. erts_fprintf(stderr, "dirty CPU scheduler wakeup threshold: %s\n",
  1734. arg);
  1735. erts_usage();
  1736. }
  1737. VERBOSE(DEBUG_SYSTEM,
  1738. ("dirty CPU scheduler wakeup threshold: %s\n", arg));
  1739. }
  1740. else if (has_prefix("wtdio", sub_param)) {
  1741. arg = get_arg(sub_param+5, argv[i+1], &i);
  1742. if (erts_sched_set_wakeup_other_threshold(ERTS_SCHED_DIRTY_IO, arg) != 0) {
  1743. erts_fprintf(stderr, "dirty IO scheduler wakeup threshold: %s\n",
  1744. arg);
  1745. erts_usage();
  1746. }
  1747. VERBOSE(DEBUG_SYSTEM,
  1748. ("dirty IO scheduler wakeup threshold: %s\n", arg));
  1749. }
  1750. else if (has_prefix("wt", sub_param)) {
  1751. arg = get_arg(sub_param+2, argv[i+1], &i);
  1752. if (erts_sched_set_wakeup_other_threshold(ERTS_SCHED_NORMAL, arg) != 0) {
  1753. erts_fprintf(stderr, "scheduler wakeup threshold: %s\n",
  1754. arg);
  1755. erts_usage();
  1756. }
  1757. VERBOSE(DEBUG_SYSTEM,
  1758. ("scheduler wakeup threshold: %s\n", arg));
  1759. }
  1760. else if (has_prefix("ws", sub_param)) {
  1761. arg = get_arg(sub_param+2, argv[i+1], &i);
  1762. if (erts_sched_set_wakeup_other_type(ERTS_SCHED_NORMAL, arg) != 0) {
  1763. erts_fprintf(stderr, "scheduler wakeup strategy: %s\n",
  1764. arg);
  1765. erts_usage();
  1766. }
  1767. VERBOSE(DEBUG_SYSTEM,
  1768. ("scheduler wakeup threshold: %s\n", arg));
  1769. }
  1770. else if (has_prefix("ssdcpu", sub_param)) {
  1771. /* suggested stack size (Kilo Words) for dirty CPU scheduler threads */
  1772. arg = get_arg(sub_param+6, argv[i+1], &i);
  1773. erts_dcpu_sched_thread_suggested_stack_size = atoi(arg);
  1774. if ((erts_dcpu_sched_thread_suggested_stack_size
  1775. < ERTS_SCHED_THREAD_MIN_STACK_SIZE)
  1776. || (erts_dcpu_sched_thread_suggested_stack_size >
  1777. ERTS_SCHED_THREAD_MAX_STACK_SIZE)) {
  1778. erts_fprintf(stderr, "bad stack size for dirty CPU scheduler threads %s\n",
  1779. arg);
  1780. erts_usage();
  1781. }
  1782. VERBOSE(DEBUG_SYSTEM,
  1783. ("suggested dirty CPU scheduler thread stack size %d kilo words\n",
  1784. erts_dcpu_sched_thread_suggested_stack_size));
  1785. }
  1786. else if (has_prefix("ssdio", sub_param)) {
  1787. /* suggested stack size (Kilo Words) for dirty IO scheduler threads */
  1788. arg = get_arg(sub_param+5, argv[i+1], &i);
  1789. erts_dio_sched_thread_suggested_stack_size = atoi(arg);
  1790. if ((erts_dio_sched_thread_suggested_stack_size
  1791. < ERTS_SCHED_THREAD_MIN_STACK_SIZE)
  1792. || (erts_dio_sched_thread_suggested_stack_size >
  1793. ERTS_SCHED_THREAD_MAX_STACK_SIZE)) {
  1794. erts_fprintf(stderr, "bad stack size for dirty IO scheduler threads %s\n",
  1795. arg);
  1796. erts_usage();
  1797. }
  1798. VERBOSE(DEBUG_SYSTEM,
  1799. ("suggested dirty IO scheduler thread stack size %d kilo words\n",
  1800. erts_dio_sched_thread_suggested_stack_size));
  1801. }
  1802. else if (has_prefix("ss", sub_param)) {
  1803. /* suggested stack size (Kilo Words) for scheduler threads */
  1804. arg = get_arg(sub_param+2, argv[i+1], &i);
  1805. erts_sched_thread_suggested_stack_size = atoi(arg);
  1806. modified_sched_thread_suggested_stack_size = 1;
  1807. if ((erts_sched_thread_suggested_stack_size
  1808. < ERTS_SCHED_THREAD_MIN_STACK_SIZE)
  1809. || (erts_sched_thread_suggested_stack_size >
  1810. ERTS_SCHED_THREAD_MAX_STACK_SIZE)) {
  1811. erts_fprintf(stderr, "bad stack size for scheduler threads %s\n",
  1812. arg);
  1813. erts_usage();
  1814. }
  1815. VERBOSE(DEBUG_SYSTEM,
  1816. ("suggested scheduler thread stack size %d kilo words\n",
  1817. erts_sched_thread_suggested_stack_size));
  1818. }
  1819. else if (has_prefix("fwi", sub_param)) {
  1820. long val;
  1821. arg = get_arg(sub_param+3, argv[i+1], &i);
  1822. errno = 0;
  1823. val = strtol(arg, NULL, 10);
  1824. if (errno != 0 || val < 0) {
  1825. erts_fprintf(stderr,
  1826. "bad scheduler forced wakeup "
  1827. "interval %s\n",
  1828. arg);
  1829. erts_usage();
  1830. }
  1831. erts_runq_supervision_interval = val;
  1832. }
  1833. else {
  1834. erts_fprintf(stderr, "bad scheduling option %s\n", argv[i]);
  1835. erts_usage();
  1836. }
  1837. break;
  1838. }
  1839. case 't':
  1840. /* set atom table size */
  1841. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1842. errno = 0;
  1843. erts_atom_table_size = strtol(arg, NULL, 10);
  1844. if (errno != 0 ||
  1845. erts_atom_table_size < MIN_ATOM_TABLE_SIZE ||
  1846. erts_atom_table_size > MAX_ATOM_TABLE_SIZE) {
  1847. erts_fprintf(stderr, "bad atom table size %s\n", arg);
  1848. erts_usage();
  1849. }
  1850. VERBOSE(DEBUG_SYSTEM,
  1851. ("setting maximum number of atoms to %d\n",
  1852. erts_atom_table_size));
  1853. break;
  1854. case 'T' :
  1855. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1856. errno = 0;
  1857. erts_modified_timing_level = atoi(arg);
  1858. if ((erts_modified_timing_level == 0 && errno != 0)
  1859. || erts_modified_timing_level < 0
  1860. || erts_modified_timing_level >= ERTS_MODIFIED_TIMING_LEVELS) {
  1861. erts_fprintf(stderr, "bad modified timing level %s\n", arg);
  1862. erts_usage();
  1863. }
  1864. else {
  1865. VERBOSE(DEBUG_SYSTEM,
  1866. ("using modified timing level %d\n",
  1867. erts_modified_timing_level));
  1868. }
  1869. break;
  1870. case 'R': {
  1871. /* set compatibility release */
  1872. int this_rel;
  1873. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1874. erts_compat_rel = atoi(arg);
  1875. this_rel = this_rel_num();
  1876. if (erts_compat_rel < this_rel - 2 || this_rel < erts_compat_rel) {
  1877. erts_fprintf(stderr, "bad compatibility release number %s\n", arg);
  1878. erts_usage();
  1879. }
  1880. switch (erts_compat_rel) {
  1881. /* Currently no compat features... */
  1882. default:
  1883. break;
  1884. }
  1885. break;
  1886. }
  1887. case 'A': /* Was handled in early init just read past it */
  1888. (void) get_arg(argv[i]+2, argv[i+1], &i);
  1889. break;
  1890. case 'a':
  1891. /* suggested stack size (Kilo Words) for threads in thread pool */
  1892. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1893. erts_async_thread_suggested_stack_size = atoi(arg);
  1894. if ((erts_async_thread_suggested_stack_size
  1895. < ERTS_ASYNC_THREAD_MIN_STACK_SIZE)
  1896. || (erts_async_thread_suggested_stack_size >
  1897. ERTS_ASYNC_THREAD_MAX_STACK_SIZE)) {
  1898. erts_fprintf(stderr, "bad stack size for async threads %s\n",
  1899. arg);
  1900. erts_usage();
  1901. }
  1902. VERBOSE(DEBUG_SYSTEM,
  1903. ("suggested async-thread stack size %d kilo words\n",
  1904. erts_async_thread_suggested_stack_size));
  1905. break;
  1906. case 'r': {
  1907. char *sub_param = argv[i]+2;
  1908. if (has_prefix("g", sub_param)) {
  1909. get_arg(sub_param+1, argv[i+1], &i);
  1910. /* already handled */
  1911. }
  1912. else {
  1913. erts_ets_realloc_always_moves = 1;
  1914. }
  1915. break;
  1916. }
  1917. case 'C':
  1918. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1919. if (sys_strcmp(arg, "no_time_warp") == 0)
  1920. time_warp_mode = ERTS_NO_TIME_WARP_MODE;
  1921. else if (sys_strcmp(arg, "single_time_warp") == 0)
  1922. time_warp_mode = ERTS_SINGLE_TIME_WARP_MODE;
  1923. else if (sys_strcmp(arg, "multi_time_warp") == 0)
  1924. time_warp_mode = ERTS_MULTI_TIME_WARP_MODE;
  1925. else {
  1926. erts_fprintf(stderr,
  1927. "Invalid time warp mode: %s\n", arg);
  1928. erts_usage();
  1929. }
  1930. break;
  1931. case 'c':
  1932. if (sys_strcmp(argv[i]+2, "false") == 0)
  1933. goto time_correction_false;
  1934. else if (sys_strcmp(argv[i]+2, "true") == 0)
  1935. goto time_correction_true;
  1936. else if (argv[i][2] == '\0') {
  1937. if (i + 1 >= argc)
  1938. goto time_correction_false;
  1939. else {
  1940. if (sys_strcmp(argv[i+1], "false") == 0) {
  1941. (void) get_arg(argv[i]+2, argv[i+1], &i);
  1942. goto time_correction_false;
  1943. }
  1944. else if (sys_strcmp(argv[i+1], "true") == 0) {
  1945. (void) get_arg(argv[i]+2, argv[i+1], &i);
  1946. time_correction_true:
  1947. time_correction = 1;
  1948. break;
  1949. }
  1950. else {
  1951. time_correction_false:
  1952. time_correction = 0;
  1953. break;
  1954. }
  1955. }
  1956. }
  1957. else {
  1958. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1959. erts_fprintf(stderr, "Invalid time correnction value: %s\n", arg);
  1960. erts_usage();
  1961. }
  1962. break;
  1963. case 'W':
  1964. arg = get_arg(argv[i]+2, argv[i+1], &i);
  1965. switch (arg[0]) {
  1966. case 'i':
  1967. erts_error_logger_warnings = am_info;
  1968. break;
  1969. case 'e':
  1970. erts_error_logger_warnings = am_error;
  1971. break;
  1972. case 'w':
  1973. erts_error_logger_warnings = am_warning;
  1974. break;
  1975. default:
  1976. erts_fprintf(stderr, "unrecognized warning_map option %s\n", arg);
  1977. erts_usage();
  1978. }
  1979. break;
  1980. case 'z': {
  1981. char *sub_param = argv[i]+2;
  1982. if (has_prefix("dbbl", sub_param)) {
  1983. int new_limit;
  1984. arg = get_arg(sub_param+4, argv[i+1], &i);
  1985. new_limit = atoi(arg);
  1986. if (new_limit < 1 || INT_MAX/1024 < new_limit) {
  1987. erts_fprintf(stderr, "Invalid dbbl limit: %d\n", new_limit);
  1988. erts_usage();
  1989. } else {
  1990. erts_dist_buf_busy_limit = new_limit*1024;
  1991. }
  1992. }
  1993. else if (has_prefix("dntgc", sub_param)) {
  1994. long secs;
  1995. arg = get_arg(sub_param+5, argv[i+1], &i);
  1996. if (sys_strcmp(arg, "infinity") == 0)
  1997. secs = ERTS_NODE_TAB_DELAY_GC_INFINITY;
  1998. else {
  1999. char *endptr;
  2000. errno = 0;
  2001. secs = strtol(arg, &endptr, 10);
  2002. if (errno != 0 || *arg == '\0' || *endptr != '\0'
  2003. || secs < 0 || ERTS_NODE_TAB_DELAY_GC_MAX < secs) {
  2004. erts_fprintf(stderr, "Invalid delayed node table gc: %s\n", arg);
  2005. erts_usage();
  2006. }
  2007. }
  2008. node_tab_delete_delay = (int) secs;
  2009. }
  2010. else if (has_prefix("ebwt", sub_param)) {
  2011. arg = get_arg(sub_param+4, argv[i+1], &i);
  2012. if (sys_strcmp(arg, "none") == 0)
  2013. db_spin_count = ERTS_DB_SPNCNT_NONE;
  2014. else if (sys_strcmp(arg, "very_short") == 0)
  2015. db_spin_count = ERTS_DB_SPNCNT_VERY_LOW;
  2016. else if (sys_strcmp(arg, "short") == 0)
  2017. db_spin_count = ERTS_DB_SPNCNT_LOW;
  2018. else if (sys_strcmp(arg, "medium") == 0)
  2019. db_spin_count = ERTS_DB_SPNCNT_NORMAL;
  2020. else if (sys_strcmp(arg, "long") == 0)
  2021. db_spin_count = ERTS_DB_SPNCNT_HIGH;
  2022. else if (sys_strcmp(arg, "very_long") == 0)
  2023. db_spin_count = ERTS_DB_SPNCNT_VERY_HIGH;
  2024. else if (sys_strcmp(arg, "extremely_long") == 0)
  2025. db_spin_count = ERTS_DB_SPNCNT_EXTREMELY_HIGH;
  2026. else {
  2027. erts_fprintf(stderr,
  2028. "Invalid ets busy wait threshold: %s\n", arg);
  2029. erts_usage();
  2030. }
  2031. }
  2032. else {
  2033. erts_fprintf(stderr, "bad -z option %s\n", argv[i]);
  2034. erts_usage();
  2035. }
  2036. break;
  2037. }
  2038. default:
  2039. erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
  2040. erts_usage();
  2041. }
  2042. i++;
  2043. }
  2044. if (!erts_check_time_adj_support(time_correction, time_warp_mode)) {
  2045. char *time_correction_str = time_correction ? "Enabled" : "Disabled";
  2046. char *time_warp_str = "undefined";
  2047. switch (time_warp_mode) {
  2048. case ERTS_NO_TIME_WARP_MODE:
  2049. time_warp_str = "no";
  2050. break;
  2051. case ERTS_SINGLE_TIME_WARP_MODE:
  2052. time_warp_str = "single";
  2053. break;
  2054. case ERTS_MULTI_TIME_WARP_MODE:
  2055. time_warp_str = "multi";
  2056. break;
  2057. default:
  2058. time_warp_str = "undefined";
  2059. break;
  2060. }
  2061. erts_fprintf(stderr, "%s time correction with %s time warp mode "
  2062. "is not supported on this platform\n",
  2063. time_correction_str,
  2064. time_warp_str);
  2065. erts_usage();
  2066. }
  2067. /* Output format on windows for sprintf defaults to three exponents.
  2068. * We use two-exponent to mimic normal sprintf behaviour.
  2069. */
  2070. #if defined(__WIN32__) && defined(_TWO_DIGIT_EXPONENT)
  2071. _set_output_format(_TWO_DIGIT_EXPONENT);
  2072. #endif
  2073. /* Restart will not reinstall the break handler */
  2074. #ifdef __WIN32__
  2075. if (ignore_break)
  2076. erts_set_ignore_break();
  2077. else if (replace_intr)
  2078. erts_replace_intr();
  2079. else
  2080. init_break_handler();
  2081. #else
  2082. if (ignore_break)
  2083. erts_set_ignore_break();
  2084. else if (have_break_handler)
  2085. init_break_handler();
  2086. if (replace_intr)
  2087. erts_replace_intr();
  2088. #endif
  2089. boot_argc = argc - i; /* Number of arguments to init */
  2090. boot_argv = &argv[i];
  2091. if (erts_sched_thread_suggested_stack_size < ERTS_SCHED_THREAD_MIN_STACK_SIZE)
  2092. erts_sched_thread_suggested_stack_size = ERTS_SCHED_THREAD_MIN_STACK_SIZE;
  2093. if (erts_dcpu_sched_thread_suggested_stack_size < ERTS_SCHED_THREAD_MIN_STACK_SIZE)
  2094. erts_dcpu_sched_thread_suggested_stack_size = ERTS_SCHED_THREAD_MIN_STACK_SIZE;
  2095. if (erts_dio_sched_thread_suggested_stack_size < ERTS_SCHED_THREAD_MIN_STACK_SIZE)
  2096. erts_dio_sched_thread_suggested_stack_size = ERTS_SCHED_THREAD_MIN_STACK_SIZE;
  2097. erl_init(ncpu,
  2098. proc_tab_sz,
  2099. legacy_proc_tab,
  2100. port_tab_sz,
  2101. port_tab_sz_ignore_files,
  2102. legacy_port_tab,
  2103. time_correction,
  2104. time_warp_mode,
  2105. node_tab_delete_delay,
  2106. db_spin_count);
  2107. load_preloaded();
  2108. erts_end_staging_code_ix();
  2109. erts_commit_staging_code_ix();
  2110. erts_initialized = 1;
  2111. erts_init_process_id = erl_first_process_otp(init, boot_argc, boot_argv);
  2112. ASSERT(erts_init_process_id != ERTS_INVALID_PID);
  2113. {
  2114. /*
  2115. * The erts_code_purger and the erts_literal_area_collector
  2116. * system processes are *always* alive. If they terminate
  2117. * they bring the whole VM down.
  2118. */
  2119. Eterm pid;
  2120. pid = erl_system_process_otp(erts_init_process_id,
  2121. "erts_code_purger", !0,
  2122. PRIORITY_NORMAL);
  2123. erts_code_purger
  2124. = (Process *) erts_ptab_pix2intptr_ddrb(&erts_proc,
  2125. internal_pid_index(pid));
  2126. ASSERT(erts_code_purger && erts_code_purger->common.id == pid);
  2127. erts_proc_inc_refc(erts_code_purger);
  2128. pid = erl_system_process_otp(erts_init_process_id,
  2129. "erts_literal_area_collector",
  2130. !0, PRIORITY_NORMAL);
  2131. erts_literal_area_collector
  2132. = (Process *) erts_ptab_pix2intptr_ddrb(&erts_proc,
  2133. internal_pid_index(pid));
  2134. ASSERT(erts_literal_area_collector
  2135. && erts_literal_area_collector->common.id == pid);
  2136. erts_proc_inc_refc(erts_literal_area_collector);
  2137. pid = erl_system_process_otp(erts_init_process_id,
  2138. "erts_dirty_process_signal_handler",
  2139. !0, PRIORITY_NORMAL);
  2140. erts_dirty_process_signal_handler
  2141. = (Process *) erts_ptab_pix2intptr_ddrb(&erts_proc,
  2142. internal_pid_index(pid));
  2143. ASSERT(erts_dirty_process_signal_handler
  2144. && erts_dirty_process_signal_handler->common.id == pid);
  2145. erts_proc_inc_refc(erts_dirty_process_signal_handler);
  2146. pid = erl_system_process_otp(erts_init_process_id,
  2147. "erts_dirty_process_signal_handler",
  2148. !0, PRIORITY_HIGH);
  2149. erts_dirty_process_signal_handler_high
  2150. = (Process *) erts_ptab_pix2intptr_ddrb(&erts_proc,
  2151. internal_pid_index(pid));
  2152. ASSERT(erts_dirty_process_signal_handler_high
  2153. && erts_dirty_process_signal_handler_high->common.id == pid);
  2154. erts_proc_inc_refc(erts_dirty_process_signal_handler_high);
  2155. pid = erl_system_process_otp(erts_init_process_id,
  2156. "erts_dirty_process_signal_handler",
  2157. !0, PRIORITY_MAX);
  2158. erts_dirty_process_signal_handler_max
  2159. = (Process *) erts_ptab_pix2intptr_ddrb(&erts_proc,
  2160. internal_pid_index(pid));
  2161. ASSERT(erts_dirty_process_signal_handler_max
  2162. && erts_dirty_process_signal_handler_max->common.id == pid);
  2163. erts_proc_inc_refc(erts_dirty_process_signal_handler_max);
  2164. }
  2165. erts_start_schedulers();
  2166. #ifdef ERTS_ENABLE_LOCK_COUNT
  2167. erts_lcnt_post_startup();
  2168. #endif
  2169. /* Let system specific code decide what to do with the main thread... */
  2170. erts_sys_main_thread(); /* May or may not return! */
  2171. }
  2172. __decl_noreturn void erts_thr_fatal_error(int err, char *what)
  2173. {
  2174. char *errstr = err ? strerror(err) : NULL;
  2175. erts_fprintf(stderr,
  2176. "Failed to %s: %s%s(%d)\n",
  2177. what,
  2178. errstr ? errstr : "",
  2179. errstr ? " " : "",
  2180. err);
  2181. abort();
  2182. }
  2183. static void
  2184. system_cleanup(int flush_async)
  2185. {
  2186. /*
  2187. * Make sure only one thread exits the runtime system.
  2188. */
  2189. if (erts_atomic_inc_read_nob(&exiting) != 1) {
  2190. /*
  2191. * Another thread is currently exiting the system;
  2192. * wait for it to do its job.
  2193. */
  2194. if (erts_thr_progress_is_managed_thread()) {
  2195. /*
  2196. * The exiting thread might be waiting for
  2197. * us to block; need to update status...
  2198. */
  2199. erts_thr_progress_active(erts_thr_prgr_data(NULL), 0);
  2200. erts_thr_progress_prepare_wait(erts_thr_prgr_data(NULL));
  2201. }
  2202. /* Wait forever... */
  2203. while (1)
  2204. erts_milli_sleep(10000000);
  2205. }
  2206. /* No cleanup wanted if ...
  2207. * 1. we are about to do an abnormal exit
  2208. * 2. we haven't finished initializing, or
  2209. * 3. another thread than the main thread is performing the exit
  2210. * (in threaded non smp case).
  2211. */
  2212. if (!flush_async
  2213. || !erts_initialized
  2214. )
  2215. return;
  2216. #ifdef ERTS_ENABLE_LOCK_CHECK
  2217. erts_lc_check_exact(NULL, 0);
  2218. #endif
  2219. erts_exit_flush_async();
  2220. }
  2221. static int erts_exit_code;
  2222. static __decl_noreturn void __noreturn
  2223. erts_exit_vv(int n, int flush_async, char *fmt, va_list args1, va_list args2)
  2224. {
  2225. system_cleanup(flush_async);
  2226. if (erts_mtrace_enabled)
  2227. erts_mtrace_exit((Uint32) n);
  2228. if (fmt != NULL && *fmt != '\0')
  2229. erl_error(fmt, args2); /* Print error message. */
  2230. erts_exit_code = n;
  2231. /* Produce an Erlang crash dump if error */
  2232. if (((n == ERTS_ERROR_EXIT && erts_no_crash_dump == 0) || n == ERTS_DUMP_EXIT)
  2233. && erts_initialized) {
  2234. erl_crash_dump_v((char*) NULL, 0, fmt, args1);
  2235. }
  2236. erts_exit_epilogue();
  2237. }
  2238. __decl_noreturn void __noreturn erts_exit_epilogue(void)
  2239. {
  2240. int n = erts_exit_code;
  2241. sys_tty_reset(n);
  2242. if (n == ERTS_INTR_EXIT)
  2243. exit(0);
  2244. else if (n == ERTS_DUMP_EXIT)
  2245. ERTS_EXIT_AFTER_DUMP(1);
  2246. else if (n == ERTS_ERROR_EXIT || n == ERTS_ABORT_EXIT)
  2247. abort();
  2248. exit(n);
  2249. }
  2250. /* Exit without flushing async threads */
  2251. __decl_noreturn void __noreturn erts_exit(int n, char *fmt, ...)
  2252. {
  2253. va_list args1, args2;
  2254. va_start(args1, fmt);
  2255. va_start(args2, fmt);
  2256. erts_exit_vv(n, 0, fmt, args1, args2);
  2257. va_end(args2);
  2258. va_end(args1);
  2259. }
  2260. /* Exit after flushing async threads */
  2261. __decl_noreturn void __noreturn erts_flush_async_exit(int n, char *fmt, ...)
  2262. {
  2263. va_list args1, args2;
  2264. va_start(args1, fmt);
  2265. va_start(args2, fmt);
  2266. erts_exit_vv(n, 1, fmt, args1, args2);
  2267. va_end(args2);
  2268. va_end(args1);
  2269. }