PageRenderTime 94ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/erts/emulator/beam/erl_alloc.c

http://github.com/erlang/otp
C | 4119 lines | 3549 code | 457 blank | 113 comment | 601 complexity | b24d5370c4eb8ca1a3d6f0838fc7007e MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, Unlicense, LGPL-2.1, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * %CopyrightBegin%
  3. *
  4. * Copyright Ericsson AB 2002-2020. 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. /*
  21. * Description: Management of memory allocators.
  22. *
  23. * Author: Rickard Green
  24. */
  25. #ifdef HAVE_CONFIG_H
  26. # include "config.h"
  27. #endif
  28. #define ERTS_ALLOC_C__
  29. #define ERTS_ALC_INTERNAL__
  30. #define ERTS_WANT_MEM_MAPPERS
  31. #include "sys.h"
  32. #define ERL_THREADS_EMU_INTERNAL__
  33. #include "erl_threads.h"
  34. #include "global.h"
  35. #include "erl_db.h"
  36. #include "erl_binary.h"
  37. #include "erl_bits.h"
  38. #include "erl_mtrace.h"
  39. #include "erl_mseg.h"
  40. #include "erl_monitor_link.h"
  41. #include "erl_hl_timer.h"
  42. #include "erl_cpu_topology.h"
  43. #include "erl_thr_queue.h"
  44. #include "erl_nfunc_sched.h"
  45. #if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)
  46. #include "erl_check_io.h"
  47. #endif
  48. #include "erl_bif_unique.h"
  49. #define GET_ERL_GF_ALLOC_IMPL
  50. #include "erl_goodfit_alloc.h"
  51. #define GET_ERL_BF_ALLOC_IMPL
  52. #include "erl_bestfit_alloc.h"
  53. #define GET_ERL_AF_ALLOC_IMPL
  54. #include "erl_afit_alloc.h"
  55. #define GET_ERL_AOFF_ALLOC_IMPL
  56. #include "erl_ao_firstfit_alloc.h"
  57. #if ERTS_MAX_NO_OF_SCHEDULERS > ERTS_AU_MAX_PREF_ALLOC_INSTANCES
  58. # error "Too many schedulers; cannot create that many pref alloc instances"
  59. #endif
  60. #define ERTS_ALC_DEFAULT_MAX_THR_PREF ERTS_MAX_NO_OF_SCHEDULERS
  61. #if defined(SMALL_MEMORY) || defined(PURIFY) || defined(VALGRIND)
  62. #define AU_ALLOC_DEFAULT_ENABLE(X) 0
  63. #else
  64. #define AU_ALLOC_DEFAULT_ENABLE(X) (X)
  65. #endif
  66. #define ERTS_ALC_DEFAULT_ENABLED_ACUL 60
  67. #define ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC 45
  68. #define ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC 85
  69. #define ERTS_ALC_DEFAULT_ACUL ERTS_ALC_DEFAULT_ENABLED_ACUL
  70. #define ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC
  71. #define ERTS_ALC_DEFAULT_ACUL_LL_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC
  72. #ifdef DEBUG
  73. static Uint install_debug_functions(void);
  74. #if 0
  75. #define HARD_DEBUG
  76. #ifdef __GNUC__
  77. #warning "* * * * * * * * * * * * * *"
  78. #warning "* HARD DEBUG IS ENABLED! *"
  79. #warning "* * * * * * * * * * * * * *"
  80. #endif
  81. #endif
  82. #endif
  83. static int lock_all_physical_memory = 0;
  84. ErtsAllocatorFunctions_t ERTS_WRITE_UNLIKELY(erts_allctrs[ERTS_ALC_A_MAX+1]);
  85. ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
  86. ErtsAllocatorThrSpec_t ERTS_WRITE_UNLIKELY(erts_allctr_thr_spec[ERTS_ALC_A_MAX+1]);
  87. #define ERTS_MIN(A, B) ((A) < (B) ? (A) : (B))
  88. #define ERTS_MAX(A, B) ((A) > (B) ? (A) : (B))
  89. typedef union {
  90. GFAllctr_t gfa;
  91. char align_gfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(GFAllctr_t))];
  92. BFAllctr_t bfa;
  93. char align_bfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(BFAllctr_t))];
  94. AFAllctr_t afa;
  95. char align_afa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AFAllctr_t))];
  96. AOFFAllctr_t aoffa;
  97. char align_aoffa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AOFFAllctr_t))];
  98. } ErtsAllocatorState_t erts_align_attribute(ERTS_CACHE_LINE_SIZE);
  99. static ErtsAllocatorState_t std_alloc_state;
  100. static ErtsAllocatorState_t ll_alloc_state;
  101. static ErtsAllocatorState_t sl_alloc_state;
  102. static ErtsAllocatorState_t temp_alloc_state;
  103. static ErtsAllocatorState_t eheap_alloc_state;
  104. static ErtsAllocatorState_t binary_alloc_state;
  105. static ErtsAllocatorState_t ets_alloc_state;
  106. static ErtsAllocatorState_t driver_alloc_state;
  107. static ErtsAllocatorState_t fix_alloc_state;
  108. static ErtsAllocatorState_t literal_alloc_state;
  109. #ifdef ERTS_ALC_A_EXEC
  110. static ErtsAllocatorState_t exec_alloc_state;
  111. #endif
  112. static ErtsAllocatorState_t test_alloc_state;
  113. enum {
  114. ERTS_ALC_INFO_A_ALLOC_UTIL = ERTS_ALC_A_MAX + 1,
  115. ERTS_ALC_INFO_A_MSEG_ALLOC,
  116. ERTS_ALC_INFO_A_ERTS_MMAP,
  117. ERTS_ALC_INFO_A_DISABLED_EXEC, /* fake a disabled "exec_alloc" */
  118. ERTS_ALC_INFO_A_END
  119. };
  120. typedef struct {
  121. erts_atomic32_t refc;
  122. int only_sz;
  123. int internal;
  124. Uint req_sched;
  125. Process *proc;
  126. ErtsIRefStorage iref;
  127. int allocs[ERTS_ALC_INFO_A_END - ERTS_ALC_A_MIN + 1];
  128. } ErtsAllocInfoReq;
  129. ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(aireq,
  130. ErtsAllocInfoReq,
  131. 5,
  132. ERTS_ALC_T_AINFO_REQ)
  133. ErtsAlcType_t erts_fix_core_allocator_ix;
  134. struct au_init {
  135. int enable;
  136. int thr_spec;
  137. int disable_allowed;
  138. int thr_spec_allowed;
  139. int carrier_migration_allowed;
  140. ErtsAlcStrat_t astrat;
  141. struct {
  142. AllctrInit_t util;
  143. GFAllctrInit_t gf;
  144. BFAllctrInit_t bf;
  145. AFAllctrInit_t af;
  146. AOFFAllctrInit_t aoff;
  147. } init;
  148. struct {
  149. int mmbcs;
  150. int lmbcs;
  151. int smbcs;
  152. int mmmbc;
  153. } default_;
  154. };
  155. #define DEFAULT_ALLCTR_INIT { \
  156. ERTS_DEFAULT_ALLCTR_INIT, \
  157. ERTS_DEFAULT_GF_ALLCTR_INIT, \
  158. ERTS_DEFAULT_BF_ALLCTR_INIT, \
  159. ERTS_DEFAULT_AF_ALLCTR_INIT, \
  160. ERTS_DEFAULT_AOFF_ALLCTR_INIT \
  161. }
  162. typedef struct {
  163. int erts_alloc_config;
  164. #if HAVE_ERTS_MSEG
  165. ErtsMsegInit_t mseg;
  166. #endif
  167. int trim_threshold;
  168. int top_pad;
  169. AlcUInit_t alloc_util;
  170. struct {
  171. char *mtrace;
  172. char *nodename;
  173. } instr;
  174. struct au_init sl_alloc;
  175. struct au_init std_alloc;
  176. struct au_init ll_alloc;
  177. struct au_init temp_alloc;
  178. struct au_init eheap_alloc;
  179. struct au_init binary_alloc;
  180. struct au_init ets_alloc;
  181. struct au_init driver_alloc;
  182. struct au_init fix_alloc;
  183. struct au_init literal_alloc;
  184. struct au_init exec_alloc;
  185. struct au_init test_alloc;
  186. } erts_alc_hndl_args_init_t;
  187. #define ERTS_AU_INIT__ {0, 0, 1, 1, 1, \
  188. ERTS_ALC_S_GOODFIT, DEFAULT_ALLCTR_INIT, \
  189. {1,1,1,1}}
  190. #define SET_DEFAULT_ALLOC_OPTS(IP) \
  191. do { \
  192. struct au_init aui__ = ERTS_AU_INIT__; \
  193. sys_memcpy((void *) (IP), (void *) &aui__, sizeof(struct au_init)); \
  194. } while (0)
  195. static void
  196. set_default_sl_alloc_opts(struct au_init *ip)
  197. {
  198. SET_DEFAULT_ALLOC_OPTS(ip);
  199. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  200. ip->thr_spec = 1;
  201. ip->astrat = ERTS_ALC_S_GOODFIT;
  202. ip->init.util.name_prefix = "sl_";
  203. ip->init.util.alloc_no = ERTS_ALC_A_SHORT_LIVED;
  204. #ifndef SMALL_MEMORY
  205. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  206. #else
  207. ip->init.util.mmbcs = 32*1024; /* Main carrier size */
  208. #endif
  209. ip->init.util.ts = ERTS_ALC_MTA_SHORT_LIVED;
  210. ip->init.util.rsbcst = 80;
  211. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
  212. }
  213. static void
  214. set_default_std_alloc_opts(struct au_init *ip)
  215. {
  216. SET_DEFAULT_ALLOC_OPTS(ip);
  217. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  218. ip->thr_spec = 1;
  219. ip->astrat = ERTS_ALC_S_BESTFIT;
  220. ip->init.util.name_prefix = "std_";
  221. ip->init.util.alloc_no = ERTS_ALC_A_STANDARD;
  222. #ifndef SMALL_MEMORY
  223. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  224. #else
  225. ip->init.util.mmbcs = 32*1024; /* Main carrier size */
  226. #endif
  227. ip->init.util.ts = ERTS_ALC_MTA_STANDARD;
  228. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
  229. }
  230. static void
  231. set_default_ll_alloc_opts(struct au_init *ip)
  232. {
  233. SET_DEFAULT_ALLOC_OPTS(ip);
  234. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  235. ip->thr_spec = 0;
  236. ip->astrat = ERTS_ALC_S_BESTFIT;
  237. ip->init.bf.ao = 1;
  238. ip->init.util.ramv = 0;
  239. ip->init.util.mmsbc = 0;
  240. ip->init.util.sbct = ~((UWord) 0);
  241. ip->init.util.name_prefix = "ll_";
  242. ip->init.util.alloc_no = ERTS_ALC_A_LONG_LIVED;
  243. #ifndef SMALL_MEMORY
  244. ip->init.util.mmbcs = 2*1024*1024; /* Main carrier size */
  245. #else
  246. ip->init.util.mmbcs = 1*1024*1024; /* Main carrier size */
  247. #endif
  248. ip->init.util.ts = ERTS_ALC_MTA_LONG_LIVED;
  249. ip->init.util.asbcst = 0;
  250. ip->init.util.rsbcst = 0;
  251. ip->init.util.rsbcmt = 0;
  252. ip->init.util.rmbcmt = 0;
  253. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL_LL_ALLOC;
  254. }
  255. static void
  256. set_default_literal_alloc_opts(struct au_init *ip)
  257. {
  258. SET_DEFAULT_ALLOC_OPTS(ip);
  259. ip->enable = 1;
  260. ip->thr_spec = 0;
  261. ip->disable_allowed = 0;
  262. ip->thr_spec_allowed = 0;
  263. ip->carrier_migration_allowed = 0;
  264. ip->astrat = ERTS_ALC_S_BESTFIT;
  265. ip->init.bf.ao = 1;
  266. ip->init.util.ramv = 0;
  267. ip->init.util.mmsbc = 0;
  268. ip->init.util.sbct = ~((UWord) 0);
  269. ip->init.util.name_prefix = "literal_";
  270. ip->init.util.alloc_no = ERTS_ALC_A_LITERAL;
  271. #ifndef SMALL_MEMORY
  272. ip->init.util.mmbcs = 1024*1024; /* Main carrier size */
  273. #else
  274. ip->init.util.mmbcs = 256*1024; /* Main carrier size */
  275. #endif
  276. ip->init.util.ts = ERTS_ALC_MTA_LITERAL;
  277. ip->init.util.asbcst = 0;
  278. ip->init.util.rsbcst = 0;
  279. ip->init.util.rsbcmt = 0;
  280. ip->init.util.rmbcmt = 0;
  281. ip->init.util.acul = 0;
  282. #if defined(ARCH_32)
  283. # if HAVE_ERTS_MSEG
  284. ip->init.util.mseg_alloc = &erts_alcu_literal_32_mseg_alloc;
  285. ip->init.util.mseg_realloc = &erts_alcu_literal_32_mseg_realloc;
  286. ip->init.util.mseg_dealloc = &erts_alcu_literal_32_mseg_dealloc;
  287. # endif
  288. ip->init.util.sys_alloc = &erts_alcu_literal_32_sys_alloc;
  289. ip->init.util.sys_realloc = &erts_alcu_literal_32_sys_realloc;
  290. ip->init.util.sys_dealloc = &erts_alcu_literal_32_sys_dealloc;
  291. #elif defined(ARCH_64)
  292. # ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
  293. ip->init.util.mseg_alloc = &erts_alcu_mmapper_mseg_alloc;
  294. ip->init.util.mseg_realloc = &erts_alcu_mmapper_mseg_realloc;
  295. ip->init.util.mseg_dealloc = &erts_alcu_mmapper_mseg_dealloc;
  296. ip->init.util.mseg_mmapper = &erts_literal_mmapper;
  297. # endif
  298. #else
  299. # error Unknown architecture
  300. #endif
  301. }
  302. #ifdef ERTS_ALC_A_EXEC
  303. static void
  304. set_default_exec_alloc_opts(struct au_init *ip)
  305. {
  306. SET_DEFAULT_ALLOC_OPTS(ip);
  307. ip->enable = 1;
  308. ip->thr_spec = 0;
  309. ip->disable_allowed = 0;
  310. ip->thr_spec_allowed = 0;
  311. ip->carrier_migration_allowed = 0;
  312. ip->astrat = ERTS_ALC_S_BESTFIT;
  313. ip->init.bf.ao = 1;
  314. ip->init.util.ramv = 0;
  315. ip->init.util.mmsbc = 0;
  316. ip->init.util.sbct = ~((UWord) 0);
  317. ip->init.util.name_prefix = "exec_";
  318. ip->init.util.alloc_no = ERTS_ALC_A_EXEC;
  319. ip->init.util.mmbcs = 0; /* No main carrier */
  320. ip->init.util.ts = ERTS_ALC_MTA_EXEC;
  321. ip->init.util.asbcst = 0;
  322. ip->init.util.rsbcst = 0;
  323. ip->init.util.rsbcmt = 0;
  324. ip->init.util.rmbcmt = 0;
  325. ip->init.util.acul = 0;
  326. ip->init.util.mseg_alloc = &erts_alcu_exec_mseg_alloc;
  327. ip->init.util.mseg_realloc = &erts_alcu_exec_mseg_realloc;
  328. ip->init.util.mseg_dealloc = &erts_alcu_exec_mseg_dealloc;
  329. }
  330. #endif /* ERTS_ALC_A_EXEC */
  331. static void
  332. set_default_temp_alloc_opts(struct au_init *ip)
  333. {
  334. SET_DEFAULT_ALLOC_OPTS(ip);
  335. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  336. ip->thr_spec = 1;
  337. ip->disable_allowed = 0;
  338. ip->carrier_migration_allowed = 0;
  339. ip->astrat = ERTS_ALC_S_AFIT;
  340. ip->init.util.name_prefix = "temp_";
  341. ip->init.util.alloc_no = ERTS_ALC_A_TEMPORARY;
  342. #ifndef SMALL_MEMORY
  343. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  344. #else
  345. ip->init.util.mmbcs = 32*1024; /* Main carrier size */
  346. #endif
  347. ip->init.util.ts = ERTS_ALC_MTA_TEMPORARY;
  348. ip->init.util.rsbcst = 90;
  349. ip->init.util.rmbcmt = 100;
  350. }
  351. static void
  352. set_default_eheap_alloc_opts(struct au_init *ip)
  353. {
  354. SET_DEFAULT_ALLOC_OPTS(ip);
  355. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  356. ip->thr_spec = 1;
  357. ip->astrat = ERTS_ALC_S_GOODFIT;
  358. ip->init.util.name_prefix = "eheap_";
  359. ip->init.util.alloc_no = ERTS_ALC_A_EHEAP;
  360. #ifndef SMALL_MEMORY
  361. ip->init.util.mmbcs = 512*1024; /* Main carrier size */
  362. #else
  363. ip->init.util.mmbcs = 256*1024; /* Main carrier size */
  364. #endif
  365. ip->init.util.ts = ERTS_ALC_MTA_EHEAP;
  366. ip->init.util.rsbcst = 50;
  367. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC;
  368. }
  369. static void
  370. set_default_binary_alloc_opts(struct au_init *ip)
  371. {
  372. SET_DEFAULT_ALLOC_OPTS(ip);
  373. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  374. ip->thr_spec = 1;
  375. ip->astrat = ERTS_ALC_S_BESTFIT;
  376. ip->init.util.name_prefix = "binary_";
  377. ip->init.util.alloc_no = ERTS_ALC_A_BINARY;
  378. #ifndef SMALL_MEMORY
  379. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  380. #else
  381. ip->init.util.mmbcs = 32*1024; /* Main carrier size */
  382. #endif
  383. ip->init.util.ts = ERTS_ALC_MTA_BINARY;
  384. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
  385. ip->init.util.atags = 1;
  386. }
  387. static void
  388. set_default_ets_alloc_opts(struct au_init *ip)
  389. {
  390. SET_DEFAULT_ALLOC_OPTS(ip);
  391. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  392. ip->thr_spec = 1;
  393. ip->astrat = ERTS_ALC_S_BESTFIT;
  394. ip->init.util.name_prefix = "ets_";
  395. ip->init.util.alloc_no = ERTS_ALC_A_ETS;
  396. #ifndef SMALL_MEMORY
  397. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  398. #else
  399. ip->init.util.mmbcs = 32*1024; /* Main carrier size */
  400. #endif
  401. ip->init.util.ts = ERTS_ALC_MTA_ETS;
  402. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
  403. }
  404. static void
  405. set_default_driver_alloc_opts(struct au_init *ip)
  406. {
  407. SET_DEFAULT_ALLOC_OPTS(ip);
  408. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  409. ip->thr_spec = 1;
  410. ip->astrat = ERTS_ALC_S_BESTFIT;
  411. ip->init.util.name_prefix = "driver_";
  412. ip->init.util.alloc_no = ERTS_ALC_A_DRIVER;
  413. #ifndef SMALL_MEMORY
  414. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  415. #else
  416. ip->init.util.mmbcs = 32*1024; /* Main carrier size */
  417. #endif
  418. ip->init.util.ts = ERTS_ALC_MTA_DRIVER;
  419. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
  420. ip->init.util.atags = 1;
  421. }
  422. static void
  423. set_default_fix_alloc_opts(struct au_init *ip,
  424. size_t *fix_type_sizes)
  425. {
  426. SET_DEFAULT_ALLOC_OPTS(ip);
  427. ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
  428. ip->thr_spec = 1;
  429. ip->astrat = ERTS_ALC_S_BESTFIT;
  430. ip->init.bf.ao = 1;
  431. ip->init.util.name_prefix = "fix_";
  432. ip->init.util.fix_type_size = fix_type_sizes;
  433. ip->init.util.alloc_no = ERTS_ALC_A_FIXED_SIZE;
  434. #ifndef SMALL_MEMORY
  435. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  436. #else
  437. ip->init.util.mmbcs = 128*1024; /* Main carrier size */
  438. #endif
  439. ip->init.util.ts = ERTS_ALC_MTA_FIXED_SIZE;
  440. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
  441. }
  442. static void
  443. set_default_test_alloc_opts(struct au_init *ip)
  444. {
  445. SET_DEFAULT_ALLOC_OPTS(ip);
  446. ip->enable = 0; /* Disabled by default */
  447. ip->thr_spec = -1 * erts_no_schedulers;
  448. ip->astrat = ERTS_ALC_S_FIRSTFIT;
  449. ip->init.aoff.crr_order = FF_AOFF;
  450. ip->init.aoff.blk_order = FF_BF;
  451. ip->init.util.name_prefix = "test_";
  452. ip->init.util.alloc_no = ERTS_ALC_A_TEST;
  453. ip->init.util.mmbcs = 0; /* Main carrier size */
  454. ip->init.util.ts = ERTS_ALC_MTA_TEST;
  455. ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
  456. ip->init.util.atags = 1;
  457. /* Use a constant minimal MBC size */
  458. #if ERTS_SA_MB_CARRIERS
  459. ip->init.util.smbcs = ERTS_SACRR_UNIT_SZ;
  460. ip->init.util.lmbcs = ERTS_SACRR_UNIT_SZ;
  461. ip->init.util.sbct = ERTS_SACRR_UNIT_SZ;
  462. #else
  463. ip->init.util.smbcs = 1 << 12;
  464. ip->init.util.lmbcs = 1 << 12;
  465. ip->init.util.sbct = 1 << 12;
  466. #endif
  467. }
  468. static void
  469. adjust_tpref(struct au_init *ip, int no_sched)
  470. {
  471. if (ip->thr_spec) {
  472. ip->thr_spec = no_sched;
  473. ip->thr_spec *= -1; /* thread preferred */
  474. /* If default ... */
  475. /* ... shrink main multi-block carrier size */
  476. if (ip->default_.mmbcs)
  477. ip->init.util.mmbcs /= ERTS_MIN(4, no_sched);
  478. /* ... shrink largest multi-block carrier size */
  479. if (ip->default_.lmbcs)
  480. ip->init.util.lmbcs /= ERTS_MIN(2, no_sched);
  481. /* ... shrink smallest multi-block carrier size */
  482. if (ip->default_.smbcs)
  483. ip->init.util.smbcs /= ERTS_MIN(4, no_sched);
  484. }
  485. }
  486. static void handle_args(int *, char **, erts_alc_hndl_args_init_t *);
  487. static void
  488. set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu);
  489. static void
  490. start_au_allocator(ErtsAlcType_t alctr_n,
  491. struct au_init *init,
  492. ErtsAllocatorState_t *state);
  493. static void
  494. refuse_af_strategy(struct au_init *init)
  495. {
  496. if (init->astrat == ERTS_ALC_S_AFIT)
  497. init->astrat = ERTS_ALC_S_GOODFIT;
  498. }
  499. #ifdef HARD_DEBUG
  500. static void hdbg_init(void);
  501. #endif
  502. static void adjust_fix_alloc_sizes(UWord extra_block_size)
  503. {
  504. if (extra_block_size && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled) {
  505. int j;
  506. if (erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].thr_spec) {
  507. int i;
  508. ErtsAllocatorThrSpec_t* tspec;
  509. tspec = &erts_allctr_thr_spec[ERTS_ALC_A_FIXED_SIZE];
  510. ASSERT(tspec->enabled);
  511. for (i=0; i < tspec->size; i++) {
  512. Allctr_t* allctr = tspec->allctr[i];
  513. for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
  514. size_t size = allctr->fix[j].type_size;
  515. size = MAX(size + extra_block_size,
  516. sizeof(ErtsAllctrDDBlock_t));
  517. allctr->fix[j].type_size = size;
  518. }
  519. }
  520. }
  521. else
  522. {
  523. Allctr_t* allctr = erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra;
  524. for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
  525. size_t size = allctr->fix[j].type_size;
  526. size = MAX(size + extra_block_size,
  527. sizeof(ErtsAllctrDDBlock_t));
  528. allctr->fix[j].type_size = size;
  529. }
  530. }
  531. }
  532. }
  533. static ERTS_INLINE int
  534. strategy_support_carrier_migration(struct au_init *auip)
  535. {
  536. /*
  537. * Currently only aoff* and ageff* support carrier
  538. * migration, i.e, type AOFIRSTFIT.
  539. */
  540. return auip->astrat == ERTS_ALC_S_FIRSTFIT;
  541. }
  542. static ERTS_INLINE void
  543. adjust_carrier_migration_support(struct au_init *auip)
  544. {
  545. if (auip->init.util.acul) {
  546. auip->thr_spec = -1; /* Need thread preferred */
  547. /*
  548. * If strategy cannot handle carrier migration,
  549. * default to a strategy that can...
  550. */
  551. if (!strategy_support_carrier_migration(auip)) {
  552. /* Default to aoffcbf */
  553. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  554. auip->init.aoff.crr_order = FF_AOFF;
  555. auip->init.aoff.blk_order = FF_BF;
  556. }
  557. }
  558. }
  559. void
  560. erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
  561. {
  562. UWord extra_block_size = 0;
  563. int i, ncpu;
  564. erts_alc_hndl_args_init_t init = {
  565. 0,
  566. #if HAVE_ERTS_MSEG
  567. ERTS_MSEG_INIT_DEFAULT_INITIALIZER,
  568. #endif
  569. ERTS_DEFAULT_TRIM_THRESHOLD,
  570. ERTS_DEFAULT_TOP_PAD,
  571. ERTS_DEFAULT_ALCU_INIT,
  572. };
  573. size_t fix_type_sizes[ERTS_ALC_NO_FIXED_SIZES] = {0};
  574. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_PROC)]
  575. = sizeof(Process);
  576. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR)]
  577. = sizeof(ErtsMonitorDataHeap);
  578. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_LINK)]
  579. = sizeof(ErtsLinkData);
  580. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_SEL_D_STATE)]
  581. = sizeof(ErtsDrvSelectDataState);
  582. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NIF_SEL_D_STATE)]
  583. = sizeof(ErtsNifSelectDataState);
  584. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MSG_REF)]
  585. = sizeof(ErtsMessageRef);
  586. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_THR_Q_EL_SL)]
  587. = sizeof(ErtsThrQElement_t);
  588. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_LL_PTIMER)]
  589. = erts_timer_type_size(ERTS_ALC_T_LL_PTIMER);
  590. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_HL_PTIMER)]
  591. = erts_timer_type_size(ERTS_ALC_T_HL_PTIMER);
  592. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_BIF_TIMER)]
  593. = erts_timer_type_size(ERTS_ALC_T_BIF_TIMER);
  594. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MREF_NSCHED_ENT)]
  595. = sizeof(ErtsNSchedMagicRefTableEntry);
  596. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MINDIRECTION)]
  597. = ERTS_MAGIC_BIN_UNALIGNED_SIZE(sizeof(ErtsMagicIndirectionWord));
  598. #ifdef HARD_DEBUG
  599. hdbg_init();
  600. #endif
  601. lock_all_physical_memory = 0;
  602. ncpu = eaiop->ncpu;
  603. if (ncpu < 1)
  604. ncpu = 1;
  605. erts_tsd_key_create(&erts_allctr_prelock_tsd_key,
  606. "erts_allctr_prelock_tsd_key");
  607. erts_sys_alloc_init();
  608. erts_init_utils_mem();
  609. set_default_sl_alloc_opts(&init.sl_alloc);
  610. set_default_std_alloc_opts(&init.std_alloc);
  611. set_default_ll_alloc_opts(&init.ll_alloc);
  612. set_default_temp_alloc_opts(&init.temp_alloc);
  613. set_default_eheap_alloc_opts(&init.eheap_alloc);
  614. set_default_binary_alloc_opts(&init.binary_alloc);
  615. set_default_ets_alloc_opts(&init.ets_alloc);
  616. set_default_driver_alloc_opts(&init.driver_alloc);
  617. set_default_fix_alloc_opts(&init.fix_alloc,
  618. fix_type_sizes);
  619. set_default_literal_alloc_opts(&init.literal_alloc);
  620. #ifdef ERTS_ALC_A_EXEC
  621. set_default_exec_alloc_opts(&init.exec_alloc);
  622. #endif
  623. set_default_test_alloc_opts(&init.test_alloc);
  624. if (argc && argv)
  625. handle_args(argc, argv, &init);
  626. if (lock_all_physical_memory) {
  627. #ifdef HAVE_MLOCKALL
  628. errno = 0;
  629. if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) {
  630. int err = errno;
  631. char *errstr = err ? strerror(err) : "unknown";
  632. erts_exit(1, "Failed to lock physical memory: %s (%d)\n",
  633. errstr, err);
  634. }
  635. #else
  636. erts_exit(1, "Failed to lock physical memory: Not supported\n");
  637. #endif
  638. }
  639. /* Make adjustments for carrier migration support */
  640. init.temp_alloc.init.util.acul = 0;
  641. adjust_carrier_migration_support(&init.sl_alloc);
  642. adjust_carrier_migration_support(&init.std_alloc);
  643. adjust_carrier_migration_support(&init.ll_alloc);
  644. adjust_carrier_migration_support(&init.eheap_alloc);
  645. adjust_carrier_migration_support(&init.binary_alloc);
  646. adjust_carrier_migration_support(&init.ets_alloc);
  647. adjust_carrier_migration_support(&init.driver_alloc);
  648. adjust_carrier_migration_support(&init.fix_alloc);
  649. adjust_carrier_migration_support(&init.literal_alloc);
  650. #ifdef ERTS_ALC_A_EXEC
  651. adjust_carrier_migration_support(&init.exec_alloc);
  652. #endif
  653. if (init.erts_alloc_config) {
  654. /* Adjust flags that erts_alloc_config won't like */
  655. /* No thread specific instances */
  656. init.temp_alloc.thr_spec = 0;
  657. init.sl_alloc.thr_spec = 0;
  658. init.std_alloc.thr_spec = 0;
  659. init.ll_alloc.thr_spec = 0;
  660. init.eheap_alloc.thr_spec = 0;
  661. init.binary_alloc.thr_spec = 0;
  662. init.ets_alloc.thr_spec = 0;
  663. init.driver_alloc.thr_spec = 0;
  664. init.fix_alloc.thr_spec = 0;
  665. init.literal_alloc.thr_spec = 0;
  666. #ifdef ERTS_ALC_A_EXEC
  667. init.exec_alloc.thr_spec = 0;
  668. #endif
  669. /* No carrier migration */
  670. init.temp_alloc.init.util.acul = 0;
  671. init.sl_alloc.init.util.acul = 0;
  672. init.std_alloc.init.util.acul = 0;
  673. init.ll_alloc.init.util.acul = 0;
  674. init.eheap_alloc.init.util.acul = 0;
  675. init.binary_alloc.init.util.acul = 0;
  676. init.ets_alloc.init.util.acul = 0;
  677. init.driver_alloc.init.util.acul = 0;
  678. init.fix_alloc.init.util.acul = 0;
  679. init.literal_alloc.init.util.acul = 0;
  680. #ifdef ERTS_ALC_A_EXEC
  681. init.exec_alloc.init.util.acul = 0;
  682. #endif
  683. }
  684. /* Only temp_alloc can use thread specific interface */
  685. if (init.temp_alloc.thr_spec)
  686. init.temp_alloc.thr_spec = erts_no_schedulers;
  687. /* Others must use thread preferred interface */
  688. adjust_tpref(&init.sl_alloc, erts_no_schedulers);
  689. adjust_tpref(&init.std_alloc, erts_no_schedulers);
  690. adjust_tpref(&init.ll_alloc, erts_no_schedulers);
  691. adjust_tpref(&init.eheap_alloc, erts_no_schedulers);
  692. adjust_tpref(&init.binary_alloc, erts_no_schedulers);
  693. adjust_tpref(&init.ets_alloc, erts_no_schedulers);
  694. adjust_tpref(&init.driver_alloc, erts_no_schedulers);
  695. adjust_tpref(&init.fix_alloc, erts_no_schedulers);
  696. adjust_tpref(&init.literal_alloc, erts_no_schedulers);
  697. #ifdef ERTS_ALC_A_EXEC
  698. adjust_tpref(&init.exec_alloc, erts_no_schedulers);
  699. #endif
  700. /*
  701. * The following allocators cannot be run with afit strategy.
  702. * Make sure they don't...
  703. */
  704. refuse_af_strategy(&init.sl_alloc);
  705. refuse_af_strategy(&init.std_alloc);
  706. refuse_af_strategy(&init.ll_alloc);
  707. refuse_af_strategy(&init.eheap_alloc);
  708. refuse_af_strategy(&init.binary_alloc);
  709. refuse_af_strategy(&init.ets_alloc);
  710. refuse_af_strategy(&init.driver_alloc);
  711. refuse_af_strategy(&init.fix_alloc);
  712. refuse_af_strategy(&init.literal_alloc);
  713. #ifdef ERTS_ALC_A_EXEC
  714. refuse_af_strategy(&init.exec_alloc);
  715. #endif
  716. if (!init.temp_alloc.thr_spec)
  717. refuse_af_strategy(&init.temp_alloc);
  718. erts_mtrace_pre_init();
  719. #if HAVE_ERTS_MSEG
  720. init.mseg.nos = erts_no_schedulers;
  721. erts_mseg_init(&init.mseg);
  722. #endif
  723. erts_alcu_init(&init.alloc_util);
  724. erts_afalc_init();
  725. erts_bfalc_init();
  726. erts_gfalc_init();
  727. erts_aoffalc_init();
  728. for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
  729. erts_allctrs[i].alloc = NULL;
  730. erts_allctrs[i].realloc = NULL;
  731. erts_allctrs[i].free = NULL;
  732. erts_allctrs[i].extra = NULL;
  733. erts_allctrs_info[i].alloc_util = 0;
  734. erts_allctrs_info[i].enabled = 0;
  735. erts_allctrs_info[i].thr_spec = 0;
  736. erts_allctrs_info[i].extra = NULL;
  737. }
  738. erts_allctrs[ERTS_ALC_A_SYSTEM].alloc = erts_sys_alloc;
  739. erts_allctrs[ERTS_ALC_A_SYSTEM].realloc = erts_sys_realloc;
  740. erts_allctrs[ERTS_ALC_A_SYSTEM].free = erts_sys_free;
  741. erts_allctrs_info[ERTS_ALC_A_SYSTEM].enabled = 1;
  742. set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, ncpu);
  743. set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc, ncpu);
  744. set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc, ncpu);
  745. set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc, ncpu);
  746. set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc, ncpu);
  747. set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc, ncpu);
  748. set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
  749. set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
  750. set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
  751. set_au_allocator(ERTS_ALC_A_LITERAL, &init.literal_alloc, ncpu);
  752. #ifdef ERTS_ALC_A_EXEC
  753. set_au_allocator(ERTS_ALC_A_EXEC, &init.exec_alloc, ncpu);
  754. #endif
  755. set_au_allocator(ERTS_ALC_A_TEST, &init.test_alloc, ncpu);
  756. for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
  757. if (!erts_allctrs[i].alloc)
  758. erts_exit(ERTS_ABORT_EXIT,
  759. "Missing alloc function for %s\n", ERTS_ALC_A2AD(i));
  760. if (!erts_allctrs[i].realloc)
  761. erts_exit(ERTS_ABORT_EXIT,
  762. "Missing realloc function for %s\n", ERTS_ALC_A2AD(i));
  763. if (!erts_allctrs[i].free)
  764. erts_exit(ERTS_ABORT_EXIT,
  765. "Missing free function for %s\n", ERTS_ALC_A2AD(i));
  766. }
  767. sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);
  768. sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);
  769. erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
  770. start_au_allocator(ERTS_ALC_A_TEMPORARY,
  771. &init.temp_alloc,
  772. &temp_alloc_state);
  773. start_au_allocator(ERTS_ALC_A_SHORT_LIVED,
  774. &init.sl_alloc,
  775. &sl_alloc_state);
  776. start_au_allocator(ERTS_ALC_A_STANDARD,
  777. &init.std_alloc,
  778. &std_alloc_state);
  779. start_au_allocator(ERTS_ALC_A_LONG_LIVED,
  780. &init.ll_alloc,
  781. &ll_alloc_state);
  782. start_au_allocator(ERTS_ALC_A_EHEAP,
  783. &init.eheap_alloc,
  784. &eheap_alloc_state);
  785. start_au_allocator(ERTS_ALC_A_BINARY,
  786. &init.binary_alloc,
  787. &binary_alloc_state);
  788. start_au_allocator(ERTS_ALC_A_ETS,
  789. &init.ets_alloc,
  790. &ets_alloc_state);
  791. start_au_allocator(ERTS_ALC_A_DRIVER,
  792. &init.driver_alloc,
  793. &driver_alloc_state);
  794. start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
  795. &init.fix_alloc,
  796. &fix_alloc_state);
  797. start_au_allocator(ERTS_ALC_A_LITERAL,
  798. &init.literal_alloc,
  799. &literal_alloc_state);
  800. #ifdef ERTS_ALC_A_EXEC
  801. start_au_allocator(ERTS_ALC_A_EXEC,
  802. &init.exec_alloc,
  803. &exec_alloc_state);
  804. #endif
  805. start_au_allocator(ERTS_ALC_A_TEST,
  806. &init.test_alloc,
  807. &test_alloc_state);
  808. erts_mtrace_install_wrapper_functions();
  809. init_aireq_alloc();
  810. #ifdef DEBUG
  811. extra_block_size += install_debug_functions();
  812. #endif
  813. adjust_fix_alloc_sizes(extra_block_size);
  814. }
  815. void
  816. erts_alloc_late_init(void)
  817. {
  818. }
  819. static void *
  820. erts_realloc_fixed_size(ErtsAlcType_t type, void *extra, void *p, Uint size)
  821. {
  822. erts_exit(ERTS_ABORT_EXIT,
  823. "Attempt to reallocate a block of the fixed size type %s\n",
  824. ERTS_ALC_T2TD(type));
  825. }
  826. static void
  827. set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
  828. {
  829. ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
  830. ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
  831. ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
  832. /*
  833. * Some allocators are forced on if halfword heap is used.
  834. */
  835. if (init->init.util.force)
  836. init->enable = 1;
  837. tspec->enabled = 0;
  838. tspec->dd = 0;
  839. tspec->aix = alctr_n;
  840. tspec->size = 0;
  841. ai->thr_spec = 0;
  842. if (!init->enable) {
  843. af->alloc = erts_sys_alloc;
  844. af->realloc = erts_sys_realloc;
  845. af->free = erts_sys_free;
  846. af->extra = NULL;
  847. ai->alloc_util = 0;
  848. ai->enabled = 0;
  849. ai->extra = NULL;
  850. return;
  851. }
  852. if (init->thr_spec) {
  853. if (init->thr_spec > 0) {
  854. af->alloc = erts_alcu_alloc_thr_spec;
  855. if (init->init.util.fix_type_size)
  856. af->realloc = erts_realloc_fixed_size;
  857. else if (init->init.util.ramv)
  858. af->realloc = erts_alcu_realloc_mv_thr_spec;
  859. else
  860. af->realloc = erts_alcu_realloc_thr_spec;
  861. af->free = erts_alcu_free_thr_spec;
  862. }
  863. else {
  864. af->alloc = erts_alcu_alloc_thr_pref;
  865. if (init->init.util.fix_type_size)
  866. af->realloc = erts_realloc_fixed_size;
  867. else if (init->init.util.ramv)
  868. af->realloc = erts_alcu_realloc_mv_thr_pref;
  869. else
  870. af->realloc = erts_alcu_realloc_thr_pref;
  871. af->free = erts_alcu_free_thr_pref;
  872. tspec->dd = 1;
  873. }
  874. tspec->enabled = 1;
  875. tspec->size = abs(init->thr_spec) + 1;
  876. ai->thr_spec = tspec->size;
  877. }
  878. else
  879. if (init->init.util.ts) {
  880. af->alloc = erts_alcu_alloc_ts;
  881. if (init->init.util.fix_type_size)
  882. af->realloc = erts_realloc_fixed_size;
  883. else if (init->init.util.ramv)
  884. af->realloc = erts_alcu_realloc_mv_ts;
  885. else
  886. af->realloc = erts_alcu_realloc_ts;
  887. af->free = erts_alcu_free_ts;
  888. }
  889. else
  890. {
  891. erts_exit(ERTS_ABORT_EXIT, "%salloc is not thread safe\n",
  892. init->init.util.name_prefix);
  893. }
  894. af->extra = NULL;
  895. ai->alloc_util = 1;
  896. ai->enabled = 1;
  897. }
  898. static void
  899. start_au_allocator(ErtsAlcType_t alctr_n,
  900. struct au_init *init,
  901. ErtsAllocatorState_t *state)
  902. {
  903. int i;
  904. int size = 1;
  905. void *as0;
  906. ErtsAlcStrat_t astrat;
  907. ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
  908. ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
  909. ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
  910. ErtsAlcFixList_t *fix_lists = NULL;
  911. size_t fix_list_size = 0;
  912. if (!init->enable)
  913. return;
  914. if (init->thr_spec) {
  915. char *states = erts_sys_alloc(0,
  916. NULL,
  917. ((sizeof(Allctr_t *)
  918. * (tspec->size + 1))
  919. + (sizeof(ErtsAllocatorState_t)
  920. * tspec->size)
  921. + ERTS_CACHE_LINE_SIZE - 1));
  922. if (!states)
  923. erts_exit(ERTS_ABORT_EXIT,
  924. "Failed to allocate allocator states for %salloc\n",
  925. init->init.util.name_prefix);
  926. tspec->allctr = (Allctr_t **) states;
  927. states += sizeof(Allctr_t *) * (tspec->size + 1);
  928. states = ((((UWord) states) & ERTS_CACHE_LINE_MASK)
  929. ? (char *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
  930. + ERTS_CACHE_LINE_SIZE)
  931. : (char *) states);
  932. tspec->allctr[0] = (Allctr_t *) state;
  933. size = tspec->size;
  934. for (i = 1; i < size; i++)
  935. tspec->allctr[i] = (Allctr_t *)
  936. &((ErtsAllocatorState_t *) states)[i-1];
  937. }
  938. if (init->init.util.fix_type_size) {
  939. size_t tot_fix_list_size;
  940. fix_list_size = sizeof(ErtsAlcFixList_t)*ERTS_ALC_NO_FIXED_SIZES;
  941. fix_list_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(fix_list_size);
  942. tot_fix_list_size = fix_list_size;
  943. if (init->thr_spec)
  944. tot_fix_list_size *= tspec->size;
  945. fix_lists = erts_sys_alloc(0,
  946. NULL,
  947. (tot_fix_list_size
  948. + ERTS_CACHE_LINE_SIZE - 1));
  949. if (!fix_lists)
  950. erts_exit(ERTS_ABORT_EXIT,
  951. "Failed to allocate fix lists for %salloc\n",
  952. init->init.util.name_prefix);
  953. if (((UWord) fix_lists) & ERTS_CACHE_LINE_MASK)
  954. fix_lists = ((ErtsAlcFixList_t *)
  955. ((((UWord) fix_lists) & ~ERTS_CACHE_LINE_MASK)
  956. + ERTS_CACHE_LINE_SIZE));
  957. }
  958. for (i = 0; i < size; i++) {
  959. Allctr_t *as;
  960. astrat = init->astrat;
  961. if (!init->thr_spec)
  962. as0 = state;
  963. else {
  964. as0 = (void *) tspec->allctr[i];
  965. if (!as0)
  966. continue;
  967. if (init->thr_spec < 0) {
  968. init->init.util.ts = i == 0;
  969. init->init.util.tspec = 0;
  970. init->init.util.tpref = -1*init->thr_spec + 1;
  971. }
  972. else {
  973. if (i != 0)
  974. init->init.util.ts = 0;
  975. else {
  976. if (astrat == ERTS_ALC_S_AFIT)
  977. astrat = ERTS_ALC_S_GOODFIT;
  978. init->init.util.ts = 1;
  979. }
  980. init->init.util.tspec = init->thr_spec + 1;
  981. init->init.util.tpref = 0;
  982. }
  983. }
  984. if (fix_lists) {
  985. init->init.util.fix = fix_lists;
  986. fix_lists = ((ErtsAlcFixList_t *)
  987. (((char *) fix_lists) + fix_list_size));
  988. }
  989. init->init.util.alloc_strat = astrat;
  990. init->init.util.ix = i;
  991. switch (astrat) {
  992. case ERTS_ALC_S_GOODFIT:
  993. as = erts_gfalc_start((GFAllctr_t *) as0,
  994. &init->init.gf,
  995. &init->init.util);
  996. break;
  997. case ERTS_ALC_S_BESTFIT:
  998. as = erts_bfalc_start((BFAllctr_t *) as0,
  999. &init->init.bf,
  1000. &init->init.util);
  1001. break;
  1002. case ERTS_ALC_S_AFIT:
  1003. as = erts_afalc_start((AFAllctr_t *) as0,
  1004. &init->init.af,
  1005. &init->init.util);
  1006. break;
  1007. case ERTS_ALC_S_FIRSTFIT:
  1008. as = erts_aoffalc_start((AOFFAllctr_t *) as0,
  1009. &init->init.aoff,
  1010. &init->init.util);
  1011. break;
  1012. default:
  1013. as = NULL;
  1014. ASSERT(0);
  1015. }
  1016. if (!as)
  1017. erts_exit(ERTS_ABORT_EXIT,
  1018. "Failed to start %salloc\n", init->init.util.name_prefix);
  1019. ASSERT(as == (void *) as0);
  1020. af->extra = as;
  1021. }
  1022. if (init->thr_spec)
  1023. af->extra = tspec;
  1024. ai->extra = af->extra;
  1025. }
  1026. static void bad_param(char *param_start, char *param_end)
  1027. {
  1028. size_t len = param_end - param_start;
  1029. char param[100];
  1030. if (len > 99)
  1031. len = 99;
  1032. sys_memcpy((void *) param, (void *) param_start, len);
  1033. param[len] = '\0';
  1034. erts_fprintf(stderr, "bad \"%s\" parameter\n", param);
  1035. erts_usage();
  1036. }
  1037. static void bad_value(char *param_start, char *param_end, char *value)
  1038. {
  1039. size_t len = param_end - param_start;
  1040. char param[100];
  1041. if (len > 99)
  1042. len = 99;
  1043. sys_memcpy((void *) param, (void *) param_start, len);
  1044. param[len] = '\0';
  1045. erts_fprintf(stderr, "bad \"%s\" value: %s\n", param, value);
  1046. erts_usage();
  1047. }
  1048. /* Get arg marks argument as handled by
  1049. putting NULL in argv */
  1050. static char *
  1051. get_value(char* rest, char** argv, int* ip)
  1052. {
  1053. char *param = argv[*ip]+1;
  1054. argv[*ip] = NULL;
  1055. if (*rest == '\0') {
  1056. char *next = argv[*ip + 1];
  1057. if (next[0] == '-'
  1058. && next[1] == '-'
  1059. && next[2] == '\0') {
  1060. bad_value(param, rest, "");
  1061. }
  1062. (*ip)++;
  1063. argv[*ip] = NULL;
  1064. return next;
  1065. }
  1066. return rest;
  1067. }
  1068. static ERTS_INLINE int
  1069. has_prefix(const char *prefix, const char *string)
  1070. {
  1071. int i;
  1072. for (i = 0; prefix[i]; i++)
  1073. if (prefix[i] != string[i])
  1074. return 0;
  1075. return 1;
  1076. }
  1077. static int
  1078. get_bool_value(char *param_end, char** argv, int* ip)
  1079. {
  1080. char *param = argv[*ip]+1;
  1081. char *value = get_value(param_end, argv, ip);
  1082. if (sys_strcmp(value, "true") == 0)
  1083. return 1;
  1084. else if (sys_strcmp(value, "false") == 0)
  1085. return 0;
  1086. else
  1087. bad_value(param, param_end, value);
  1088. return -1;
  1089. }
  1090. static Uint kb_to_bytes(Sint kb, Uint *bytes)
  1091. {
  1092. const Uint max = ((~((Uint) 0))/1024) + 1;
  1093. if (kb < 0 || (Uint)kb > max)
  1094. return 0;
  1095. if ((Uint)kb == max)
  1096. *bytes = ~((Uint) 0);
  1097. else
  1098. *bytes = ((Uint) kb)*1024;
  1099. return 1;
  1100. }
  1101. static Uint
  1102. get_kb_value(char *param_end, char** argv, int* ip)
  1103. {
  1104. Sint tmp;
  1105. Uint bytes = 0;
  1106. char *rest;
  1107. char *param = argv[*ip]+1;
  1108. char *value = get_value(param_end, argv, ip);
  1109. errno = 0;
  1110. tmp = (Sint) ErtsStrToSint(value, &rest, 10);
  1111. if (errno != 0 || rest == value || !kb_to_bytes(tmp, &bytes))
  1112. bad_value(param, param_end, value);
  1113. return bytes;
  1114. }
  1115. static UWord
  1116. get_mb_value(char *param_end, char** argv, int* ip)
  1117. {
  1118. SWord tmp;
  1119. UWord max = ((~((UWord) 0))/(1024*1024)) + 1;
  1120. char *rest;
  1121. char *param = argv[*ip]+1;
  1122. char *value = get_value(param_end, argv, ip);
  1123. errno = 0;
  1124. tmp = (SWord) ErtsStrToSint(value, &rest, 10);
  1125. if (errno != 0 || rest == value || tmp < 0 || max < ((UWord) tmp))
  1126. bad_value(param, param_end, value);
  1127. if (max == (UWord) tmp)
  1128. return ~((UWord) 0);
  1129. else
  1130. return ((UWord) tmp)*1024*1024;
  1131. }
  1132. #if 0
  1133. static Uint
  1134. get_byte_value(char *param_end, char** argv, int* ip)
  1135. {
  1136. Sint tmp;
  1137. char *rest;
  1138. char *param = argv[*ip]+1;
  1139. char *value = get_value(param_end, argv, ip);
  1140. errno = 0;
  1141. tmp = (Sint) ErtsStrToSint(value, &rest, 10);
  1142. if (errno != 0 || rest == value || tmp < 0)
  1143. bad_value(param, param_end, value);
  1144. return (Uint) tmp;
  1145. }
  1146. #endif
  1147. static Uint
  1148. get_amount_value(char *param_end, char** argv, int* ip)
  1149. {
  1150. Sint tmp;
  1151. char *rest;
  1152. char *param = argv[*ip]+1;
  1153. char *value = get_value(param_end, argv, ip);
  1154. errno = 0;
  1155. tmp = (Sint) ErtsStrToSint(value, &rest, 10);
  1156. if (errno != 0 || rest == value || tmp < 0)
  1157. bad_value(param, param_end, value);
  1158. return (Uint) tmp;
  1159. }
  1160. static Uint
  1161. get_acul_value(struct au_init *auip, char *param_end, char** argv, int* ip)
  1162. {
  1163. Sint tmp;
  1164. char *rest;
  1165. char *param = argv[*ip]+1;
  1166. char *value = get_value(param_end, argv, ip);
  1167. if (sys_strcmp(value, "de") == 0) {
  1168. switch (auip->init.util.alloc_no) {
  1169. case ERTS_ALC_A_LONG_LIVED:
  1170. return ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC;
  1171. case ERTS_ALC_A_EHEAP:
  1172. return ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC;
  1173. default:
  1174. return ERTS_ALC_DEFAULT_ENABLED_ACUL;
  1175. }
  1176. }
  1177. errno = 0;
  1178. tmp = (Sint) ErtsStrToSint(value, &rest, 10);
  1179. if (errno != 0 || rest == value || tmp < 0 || 100 < tmp)
  1180. bad_value(param, param_end, value);
  1181. return (Uint) tmp;
  1182. }
  1183. static void
  1184. handle_au_arg(struct au_init *auip,
  1185. char* sub_param,
  1186. char** argv,
  1187. int* ip,
  1188. int u_switch)
  1189. {
  1190. char *param = argv[*ip]+1;
  1191. switch (sub_param[0]) {
  1192. case 'a':
  1193. if (sub_param[1] == 'c') { /* Migration parameters "ac*" */
  1194. UWord value;
  1195. UWord* wp;
  1196. if (!auip->carrier_migration_allowed && !u_switch)
  1197. goto bad_switch;
  1198. if (has_prefix("acul", sub_param)) {
  1199. value = get_acul_value(auip, sub_param + 4, argv, ip);
  1200. wp = &auip->init.util.acul;
  1201. }
  1202. else if (has_prefix("acnl", sub_param)) {
  1203. value = get_amount_value(sub_param + 4, argv, ip);
  1204. wp = &auip->init.util.acnl;
  1205. }
  1206. else if (has_prefix("acfml", sub_param)) {
  1207. value = get_amount_value(sub_param + 5, argv, ip);
  1208. wp = &auip->init.util.acfml;
  1209. }
  1210. else
  1211. goto bad_switch;
  1212. if (auip->carrier_migration_allowed)
  1213. *wp = value;
  1214. }
  1215. else if(has_prefix("asbcst", sub_param)) {
  1216. auip->init.util.asbcst = get_kb_value(sub_param + 6, argv, ip);
  1217. }
  1218. else if(has_prefix("as", sub_param)) {
  1219. char *alg = get_value(sub_param + 2, argv, ip);
  1220. if (sys_strcmp("bf", alg) == 0) {
  1221. auip->astrat = ERTS_ALC_S_BESTFIT;
  1222. auip->init.bf.ao = 0;
  1223. }
  1224. else if (sys_strcmp("aobf", alg) == 0) {
  1225. auip->astrat = ERTS_ALC_S_BESTFIT;
  1226. auip->init.bf.ao = 1;
  1227. }
  1228. else if (sys_strcmp("gf", alg) == 0) {
  1229. auip->astrat = ERTS_ALC_S_GOODFIT;
  1230. }
  1231. else if (sys_strcmp("af", alg) == 0) {
  1232. auip->astrat = ERTS_ALC_S_AFIT;
  1233. }
  1234. else if (sys_strcmp("aoff", alg) == 0) {
  1235. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1236. auip->init.aoff.crr_order = FF_AOFF;
  1237. auip->init.aoff.blk_order = FF_AOFF;
  1238. }
  1239. else if (sys_strcmp("aoffcbf", alg) == 0) {
  1240. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1241. auip->init.aoff.crr_order = FF_AOFF;
  1242. auip->init.aoff.blk_order = FF_BF;
  1243. }
  1244. else if (sys_strcmp("aoffcaobf", alg) == 0) {
  1245. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1246. auip->init.aoff.crr_order = FF_AOFF;
  1247. auip->init.aoff.blk_order = FF_AOBF;
  1248. }
  1249. else if (sys_strcmp("ageffcaoff", alg) == 0) {
  1250. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1251. auip->init.aoff.crr_order = FF_AGEFF;
  1252. auip->init.aoff.blk_order = FF_AOFF;
  1253. }
  1254. else if (sys_strcmp("ageffcbf", alg) == 0) {
  1255. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1256. auip->init.aoff.crr_order = FF_AGEFF;
  1257. auip->init.aoff.blk_order = FF_BF;
  1258. }
  1259. else if (sys_strcmp("ageffcaobf", alg) == 0) {
  1260. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1261. auip->init.aoff.crr_order = FF_AGEFF;
  1262. auip->init.aoff.blk_order = FF_AOBF;
  1263. }
  1264. else {
  1265. if (auip->init.util.alloc_no == ERTS_ALC_A_TEST
  1266. && sys_strcmp("chaosff", alg) == 0) {
  1267. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1268. auip->init.aoff.crr_order = FF_CHAOS;
  1269. auip->init.aoff.blk_order = FF_CHAOS;
  1270. }
  1271. else {
  1272. bad_value(param, sub_param + 1, alg);
  1273. }
  1274. }
  1275. if (!strategy_support_carrier_migration(auip))
  1276. auip->init.util.acul = 0;
  1277. } else if (has_prefix("atags", sub_param)) {
  1278. auip->init.util.atags = get_bool_value(sub_param + 5, argv, ip);
  1279. }
  1280. else
  1281. goto bad_switch;
  1282. break;
  1283. case 'e': {
  1284. int e = get_bool_value(sub_param + 1, argv, ip);
  1285. if (!auip->disable_allowed && !e) {
  1286. if (!u_switch)
  1287. bad_value(param, sub_param + 1, "false");
  1288. else
  1289. ASSERT(auip->enable); /* ignore */
  1290. }
  1291. else auip->enable = e;
  1292. break;
  1293. }
  1294. case 'l':
  1295. if (has_prefix("lmbcs", sub_param)) {
  1296. auip->default_.lmbcs = 0;
  1297. auip->init.util.lmbcs = get_kb_value(sub_param + 5, argv, ip);
  1298. }
  1299. else
  1300. goto bad_switch;
  1301. break;
  1302. case 'm':
  1303. if (has_prefix("mbcgs", sub_param)) {
  1304. auip->init.util.mbcgs = get_amount_value(sub_param + 5, argv, ip);
  1305. }
  1306. else if (has_prefix("mbsd", sub_param)) {
  1307. auip->init.gf.mbsd = get_amount_value(sub_param + 4, argv, ip);
  1308. if (auip->init.gf.mbsd < 1)
  1309. auip->init.gf.mbsd = 1;
  1310. }
  1311. else if (has_prefix("mmbcs", sub_param)) {
  1312. auip->default_.mmbcs = 0;
  1313. auip->init.util.mmbcs = get_kb_value(sub_param + 5, argv, ip);
  1314. }
  1315. else if (has_prefix("mmmbc", sub_param)) {
  1316. auip->default_.mmmbc = 0;
  1317. auip->init.util.mmmbc = get_amount_value(sub_param + 5, argv, ip);
  1318. }
  1319. else if (has_prefix("mmsbc", sub_param)) {
  1320. auip->init.util.mmsbc = get_amount_value(sub_param + 5, argv, ip);
  1321. }
  1322. else
  1323. goto bad_switch;
  1324. break;
  1325. case 'r':
  1326. if(has_prefix("rsbcmt", sub_param)) {
  1327. auip->init.util.rsbcmt = get_amount_value(sub_param + 6, argv, ip);
  1328. if (auip->init.util.rsbcmt > 100)
  1329. auip->init.util.rsbcmt = 100;
  1330. }
  1331. else if(has_prefix("rsbcst", sub_param)) {
  1332. auip->init.util.rsbcst = get_amount_value(sub_param + 6, argv, ip);
  1333. if (auip->init.util.rsbcst > 100)
  1334. auip->init.util.rsbcst = 100;
  1335. }
  1336. else if (has_prefix("rmbcmt", sub_param)) {
  1337. auip->init.util.rmbcmt = get_amount_value(sub_param + 6, argv, ip);
  1338. if (auip->init.util.rmbcmt > 100)
  1339. auip->init.util.rmbcmt = 100;
  1340. }
  1341. else if (has_prefix("ramv", sub_param)) {
  1342. auip->init.util.ramv = get_bool_value(sub_param + 4, argv, ip);
  1343. }
  1344. else
  1345. goto bad_switch;
  1346. break;
  1347. case 's':
  1348. if(has_prefix("sbct", sub_param)) {
  1349. auip->init.util.sbct = get_kb_value(sub_param + 4, argv, ip);
  1350. }
  1351. else if (has_prefix("smbcs", sub_param)) {
  1352. auip->default_.smbcs = 0;
  1353. auip->init.util.smbcs = get_kb_value(sub_param + 5, argv, ip);
  1354. }
  1355. else
  1356. goto bad_switch;
  1357. break;
  1358. case 't': {
  1359. int res = get_bool_value(sub_param+1, argv, ip);
  1360. if (res > 0) {
  1361. if (!auip->thr_spec_allowed) {
  1362. if (!u_switch)
  1363. bad_value(param, sub_param + 1, "true");
  1364. else
  1365. ASSERT(!auip->thr_spec); /* ignore */
  1366. }
  1367. else
  1368. auip->thr_spec = 1;
  1369. break;
  1370. }
  1371. else if (res == 0) {
  1372. auip->thr_spec = 0;
  1373. auip->init.util.acul = 0;
  1374. break;
  1375. }
  1376. goto bad_switch;
  1377. }
  1378. default:
  1379. bad_switch:
  1380. bad_param(param, sub_param);
  1381. }
  1382. }
  1383. static void
  1384. handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
  1385. {
  1386. struct au_init *aui[] = {
  1387. &init->binary_alloc,
  1388. &init->std_alloc,
  1389. &init->ets_alloc,
  1390. &init->eheap_alloc,
  1391. &init->ll_alloc,
  1392. &init->driver_alloc,
  1393. &init->fix_alloc,
  1394. &init->sl_alloc
  1395. /* test_alloc not affected by +Mea??? or +Mu??? */
  1396. };
  1397. int aui_sz = (int) sizeof(aui)/sizeof(aui[0]);
  1398. char *arg;
  1399. char *rest;
  1400. int i, j;
  1401. i = 1;
  1402. ASSERT(argc && argv && init);
  1403. while (i < *argc) {
  1404. if(argv[i][0] == '-') {
  1405. char *param = argv[i]+1;
  1406. switch (argv[i][1]) {
  1407. case 'M':
  1408. switch (argv[i][2]) {
  1409. case 'B':
  1410. handle_au_arg(&init->binary_alloc, &argv[i][3], argv, &i, 0);
  1411. break;
  1412. case 'I':
  1413. if (has_prefix("scs", argv[i]+3)) {
  1414. #if HAVE_ERTS_MSEG
  1415. init->mseg.literal_mmap.scs =
  1416. #endif
  1417. get_mb_value(argv[i]+6, argv, &i);
  1418. }
  1419. else
  1420. handle_au_arg(&init->literal_alloc, &argv[i][3], argv, &i, 0);
  1421. break;
  1422. case 'X':
  1423. if (has_prefix("scs", argv[i]+3)) {
  1424. /* Ignore obsolete */
  1425. (void) get_mb_value(argv[i]+6, argv, &i);
  1426. }
  1427. else
  1428. handle_au_arg(&init->exec_alloc, &argv[i][3], argv, &i, 0);
  1429. break;
  1430. case 'D':
  1431. handle_au_arg(&init->std_alloc, &argv[i][3], argv, &i, 0);
  1432. break;
  1433. case 'E':
  1434. handle_au_arg(&init->ets_alloc, &argv[i][3], argv, &i, 0);
  1435. break;
  1436. case 'F':
  1437. handle_au_arg(&init->fix_alloc, &argv[i][3], argv, &i, 0);
  1438. break;
  1439. case 'H':
  1440. handle_au_arg(&init->eheap_alloc, &argv[i][3], argv, &i, 0);
  1441. break;
  1442. case 'L':
  1443. handle_au_arg(&init->ll_alloc, &argv[i][3], argv, &i, 0);
  1444. break;
  1445. case 'M':
  1446. if (has_prefix("amcbf", argv[i]+3)) {
  1447. #if HAVE_ERTS_MSEG
  1448. init->mseg.amcbf =
  1449. #endif
  1450. get_kb_value(argv[i]+8, argv, &i);
  1451. }
  1452. else if (has_prefix("rmcbf", argv[i]+3)) {
  1453. #if HAVE_ERTS_MSEG
  1454. init->mseg.rmcbf =
  1455. #endif
  1456. get_amount_value(argv[i]+8, argv, &i);
  1457. }
  1458. else if (has_prefix("mcs", argv[i]+3)) {
  1459. #if HAVE_ERTS_MSEG
  1460. init->mseg.mcs =
  1461. #endif
  1462. get_amount_value(argv[i]+6, argv, &i);
  1463. }
  1464. else if (has_prefix("scs", argv[i]+3)) {
  1465. #if HAVE_ERTS_MSEG
  1466. init->mseg.dflt_mmap.scs =
  1467. #endif
  1468. get_mb_value(argv[i]+6, argv, &i);
  1469. }
  1470. else if (has_prefix("sco", argv[i]+3)) {
  1471. #if HAVE_ERTS_MSEG
  1472. init->mseg.dflt_mmap.sco =
  1473. #endif
  1474. get_bool_value(argv[i]+6, argv, &i);
  1475. }
  1476. else if (has_prefix("scrpm", argv[i]+3)) {
  1477. #if HAVE_ERTS_MSEG
  1478. init->mseg.dflt_mmap.scrpm =
  1479. #endif
  1480. get_bool_value(argv[i]+8, argv, &i);
  1481. }
  1482. else if (has_prefix("scrfsd", argv[i]+3)) {
  1483. #if HAVE_ERTS_MSEG
  1484. init->mseg.dflt_mmap.scrfsd =
  1485. #endif
  1486. get_amount_value(argv[i]+9, argv, &i);
  1487. }
  1488. else {
  1489. bad_param(param, param+2);
  1490. }
  1491. break;
  1492. case 'R':
  1493. handle_au_arg(&init->driver_alloc, &argv[i][3], argv, &i, 0);
  1494. break;
  1495. case 'S':
  1496. handle_au_arg(&init->sl_alloc, &argv[i][3], argv, &i, 0);
  1497. break;
  1498. case 'T':
  1499. handle_au_arg(&init->temp_alloc, &argv[i][3], argv, &i, 0);
  1500. break;
  1501. case 'Z':
  1502. handle_au_arg(&init->test_alloc, &argv[i][3], argv, &i, 0);
  1503. break;
  1504. case 'Y': { /* sys_alloc */
  1505. if (has_prefix("tt", param+2)) {
  1506. /* set trim threshold */
  1507. arg = get_value(param+4, argv, &i);
  1508. errno = 0;
  1509. init->trim_threshold = (int) strtol(arg, &rest, 10);
  1510. if (errno != 0
  1511. || rest == arg
  1512. || init->trim_threshold < 0
  1513. || (INT_MAX/1024) < init->trim_threshold) {
  1514. bad_value(param, param+4, arg);
  1515. }
  1516. VERBOSE(DEBUG_SYSTEM,
  1517. ("using trim threshold: %d\n",
  1518. init->trim_threshold));
  1519. init->trim_threshold *= 1024;
  1520. }
  1521. else if (has_prefix("tp", param+2)) {
  1522. /* set top pad */
  1523. arg = get_value(param+4, argv, &i);
  1524. errno = 0;
  1525. init->top_pad = (int) strtol(arg, &rest, 10);
  1526. if (errno != 0
  1527. || rest == arg
  1528. || init->top_pad < 0
  1529. || (INT_MAX/1024) < init->top_pad) {
  1530. bad_value(param, param+4, arg);
  1531. }
  1532. VERBOSE(DEBUG_SYSTEM,
  1533. ("using top pad: %d\n",init->top_pad));
  1534. init->top_pad *= 1024;
  1535. }
  1536. else if (has_prefix("m", param+2)) {
  1537. /* Has been handled by erlexec */
  1538. (void) get_value(param+3, argv, &i);
  1539. }
  1540. else if (has_prefix("e", param+2)) {
  1541. arg = get_value(param+3, argv, &i);
  1542. if (sys_strcmp("true", arg) != 0)
  1543. bad_value(param, param+3, arg);
  1544. }
  1545. else
  1546. bad_param(param, param+2);
  1547. break;
  1548. }
  1549. case 'e':
  1550. switch (argv[i][3]) {
  1551. case 'a': {
  1552. int a;
  1553. arg = get_value(argv[i]+4, argv, &i);
  1554. if (sys_strcmp("min", arg) == 0) {
  1555. for (a = 0; a < aui_sz; a++)
  1556. aui[a]->enable = 0;
  1557. }
  1558. else if (sys_strcmp("max", arg) == 0) {
  1559. for (a = 0; a < aui_sz; a++)
  1560. aui[a]->enable = 1;
  1561. }
  1562. else if (sys_strcmp("config", arg) == 0) {
  1563. init->erts_alloc_config = 1;
  1564. }
  1565. else if (sys_strcmp("r9c", arg) == 0
  1566. || sys_strcmp("r10b", arg) == 0
  1567. || sys_strcmp("r11b", arg) == 0) {
  1568. set_default_sl_alloc_opts(&init->sl_alloc);
  1569. set_default_std_alloc_opts(&init->std_alloc);
  1570. set_default_ll_alloc_opts(&init->ll_alloc);
  1571. set_default_temp_alloc_opts(&init->temp_alloc);
  1572. set_default_eheap_alloc_opts(&init->eheap_alloc);
  1573. set_default_binary_alloc_opts(&init->binary_alloc);
  1574. set_default_ets_alloc_opts(&init->ets_alloc);
  1575. set_default_driver_alloc_opts(&init->driver

Large files files are truncated, but you can click here to view the full file