PageRenderTime 67ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 1ms

/erts/emulator/beam/erl_alloc.c

https://github.com/vladdu/otp
C | 4095 lines | 3523 code | 456 blank | 116 comment | 604 complexity | 4edcef43d23026d317f54903ef6bc3a1 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, Unlicense

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

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