PageRenderTime 555ms CodeModel.GetById 53ms RepoModel.GetById 3ms app.codeStats 3ms

/erts/emulator/beam/erl_alloc.c

https://github.com/bsmr-erlang/otp
C | 4125 lines | 3555 code | 457 blank | 113 comment | 601 complexity | 3b54aac3d465911f8bc3eb46ca1fc489 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0

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

  1. /*
  2. * %CopyrightBegin%
  3. *
  4. * Copyright Ericsson AB 2002-2018. All Rights Reserved.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * %CopyrightEnd%
  19. */
  20. /*
  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_NIF_EXP_TRACE)]
  595. = sizeof(NifExportTrace);
  596. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MREF_NSCHED_ENT)]
  597. = sizeof(ErtsNSchedMagicRefTableEntry);
  598. fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MINDIRECTION)]
  599. = ERTS_MAGIC_BIN_UNALIGNED_SIZE(sizeof(ErtsMagicIndirectionWord));
  600. #ifdef HARD_DEBUG
  601. hdbg_init();
  602. #endif
  603. lock_all_physical_memory = 0;
  604. ncpu = eaiop->ncpu;
  605. if (ncpu < 1)
  606. ncpu = 1;
  607. erts_tsd_key_create(&erts_allctr_prelock_tsd_key,
  608. "erts_allctr_prelock_tsd_key");
  609. erts_sys_alloc_init();
  610. erts_init_utils_mem();
  611. set_default_sl_alloc_opts(&init.sl_alloc);
  612. set_default_std_alloc_opts(&init.std_alloc);
  613. set_default_ll_alloc_opts(&init.ll_alloc);
  614. set_default_temp_alloc_opts(&init.temp_alloc);
  615. set_default_eheap_alloc_opts(&init.eheap_alloc);
  616. set_default_binary_alloc_opts(&init.binary_alloc);
  617. set_default_ets_alloc_opts(&init.ets_alloc);
  618. set_default_driver_alloc_opts(&init.driver_alloc);
  619. set_default_fix_alloc_opts(&init.fix_alloc,
  620. fix_type_sizes);
  621. set_default_literal_alloc_opts(&init.literal_alloc);
  622. #ifdef ERTS_ALC_A_EXEC
  623. set_default_exec_alloc_opts(&init.exec_alloc);
  624. #endif
  625. set_default_test_alloc_opts(&init.test_alloc);
  626. if (argc && argv)
  627. handle_args(argc, argv, &init);
  628. if (lock_all_physical_memory) {
  629. #ifdef HAVE_MLOCKALL
  630. errno = 0;
  631. if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) {
  632. int err = errno;
  633. char *errstr = err ? strerror(err) : "unknown";
  634. erts_exit(1, "Failed to lock physical memory: %s (%d)\n",
  635. errstr, err);
  636. }
  637. #else
  638. erts_exit(1, "Failed to lock physical memory: Not supported\n");
  639. #endif
  640. }
  641. /* Make adjustments for carrier migration support */
  642. init.temp_alloc.init.util.acul = 0;
  643. adjust_carrier_migration_support(&init.sl_alloc);
  644. adjust_carrier_migration_support(&init.std_alloc);
  645. adjust_carrier_migration_support(&init.ll_alloc);
  646. adjust_carrier_migration_support(&init.eheap_alloc);
  647. adjust_carrier_migration_support(&init.binary_alloc);
  648. adjust_carrier_migration_support(&init.ets_alloc);
  649. adjust_carrier_migration_support(&init.driver_alloc);
  650. adjust_carrier_migration_support(&init.fix_alloc);
  651. adjust_carrier_migration_support(&init.literal_alloc);
  652. #ifdef ERTS_ALC_A_EXEC
  653. adjust_carrier_migration_support(&init.exec_alloc);
  654. #endif
  655. if (init.erts_alloc_config) {
  656. /* Adjust flags that erts_alloc_config won't like */
  657. /* No thread specific instances */
  658. init.temp_alloc.thr_spec = 0;
  659. init.sl_alloc.thr_spec = 0;
  660. init.std_alloc.thr_spec = 0;
  661. init.ll_alloc.thr_spec = 0;
  662. init.eheap_alloc.thr_spec = 0;
  663. init.binary_alloc.thr_spec = 0;
  664. init.ets_alloc.thr_spec = 0;
  665. init.driver_alloc.thr_spec = 0;
  666. init.fix_alloc.thr_spec = 0;
  667. init.literal_alloc.thr_spec = 0;
  668. #ifdef ERTS_ALC_A_EXEC
  669. init.exec_alloc.thr_spec = 0;
  670. #endif
  671. /* No carrier migration */
  672. init.temp_alloc.init.util.acul = 0;
  673. init.sl_alloc.init.util.acul = 0;
  674. init.std_alloc.init.util.acul = 0;
  675. init.ll_alloc.init.util.acul = 0;
  676. init.eheap_alloc.init.util.acul = 0;
  677. init.binary_alloc.init.util.acul = 0;
  678. init.ets_alloc.init.util.acul = 0;
  679. init.driver_alloc.init.util.acul = 0;
  680. init.fix_alloc.init.util.acul = 0;
  681. init.literal_alloc.init.util.acul = 0;
  682. #ifdef ERTS_ALC_A_EXEC
  683. init.exec_alloc.init.util.acul = 0;
  684. #endif
  685. }
  686. /* Only temp_alloc can use thread specific interface */
  687. if (init.temp_alloc.thr_spec)
  688. init.temp_alloc.thr_spec = erts_no_schedulers;
  689. /* Others must use thread preferred interface */
  690. adjust_tpref(&init.sl_alloc, erts_no_schedulers);
  691. adjust_tpref(&init.std_alloc, erts_no_schedulers);
  692. adjust_tpref(&init.ll_alloc, erts_no_schedulers);
  693. adjust_tpref(&init.eheap_alloc, erts_no_schedulers);
  694. adjust_tpref(&init.binary_alloc, erts_no_schedulers);
  695. adjust_tpref(&init.ets_alloc, erts_no_schedulers);
  696. adjust_tpref(&init.driver_alloc, erts_no_schedulers);
  697. adjust_tpref(&init.fix_alloc, erts_no_schedulers);
  698. adjust_tpref(&init.literal_alloc, erts_no_schedulers);
  699. #ifdef ERTS_ALC_A_EXEC
  700. adjust_tpref(&init.exec_alloc, erts_no_schedulers);
  701. #endif
  702. /*
  703. * The following allocators cannot be run with afit strategy.
  704. * Make sure they don't...
  705. */
  706. refuse_af_strategy(&init.sl_alloc);
  707. refuse_af_strategy(&init.std_alloc);
  708. refuse_af_strategy(&init.ll_alloc);
  709. refuse_af_strategy(&init.eheap_alloc);
  710. refuse_af_strategy(&init.binary_alloc);
  711. refuse_af_strategy(&init.ets_alloc);
  712. refuse_af_strategy(&init.driver_alloc);
  713. refuse_af_strategy(&init.fix_alloc);
  714. refuse_af_strategy(&init.literal_alloc);
  715. #ifdef ERTS_ALC_A_EXEC
  716. refuse_af_strategy(&init.exec_alloc);
  717. #endif
  718. if (!init.temp_alloc.thr_spec)
  719. refuse_af_strategy(&init.temp_alloc);
  720. erts_mtrace_pre_init();
  721. #if HAVE_ERTS_MSEG
  722. init.mseg.nos = erts_no_schedulers;
  723. erts_mseg_init(&init.mseg);
  724. #endif
  725. erts_alcu_init(&init.alloc_util);
  726. erts_afalc_init();
  727. erts_bfalc_init();
  728. erts_gfalc_init();
  729. erts_aoffalc_init();
  730. for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
  731. erts_allctrs[i].alloc = NULL;
  732. erts_allctrs[i].realloc = NULL;
  733. erts_allctrs[i].free = NULL;
  734. erts_allctrs[i].extra = NULL;
  735. erts_allctrs_info[i].alloc_util = 0;
  736. erts_allctrs_info[i].enabled = 0;
  737. erts_allctrs_info[i].thr_spec = 0;
  738. erts_allctrs_info[i].extra = NULL;
  739. }
  740. erts_allctrs[ERTS_ALC_A_SYSTEM].alloc = erts_sys_alloc;
  741. erts_allctrs[ERTS_ALC_A_SYSTEM].realloc = erts_sys_realloc;
  742. erts_allctrs[ERTS_ALC_A_SYSTEM].free = erts_sys_free;
  743. erts_allctrs_info[ERTS_ALC_A_SYSTEM].enabled = 1;
  744. set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, ncpu);
  745. set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc, ncpu);
  746. set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc, ncpu);
  747. set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc, ncpu);
  748. set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc, ncpu);
  749. set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc, ncpu);
  750. set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
  751. set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
  752. set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
  753. set_au_allocator(ERTS_ALC_A_LITERAL, &init.literal_alloc, ncpu);
  754. #ifdef ERTS_ALC_A_EXEC
  755. set_au_allocator(ERTS_ALC_A_EXEC, &init.exec_alloc, ncpu);
  756. #endif
  757. set_au_allocator(ERTS_ALC_A_TEST, &init.test_alloc, ncpu);
  758. for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
  759. if (!erts_allctrs[i].alloc)
  760. erts_exit(ERTS_ABORT_EXIT,
  761. "Missing alloc function for %s\n", ERTS_ALC_A2AD(i));
  762. if (!erts_allctrs[i].realloc)
  763. erts_exit(ERTS_ABORT_EXIT,
  764. "Missing realloc function for %s\n", ERTS_ALC_A2AD(i));
  765. if (!erts_allctrs[i].free)
  766. erts_exit(ERTS_ABORT_EXIT,
  767. "Missing free function for %s\n", ERTS_ALC_A2AD(i));
  768. }
  769. sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);
  770. sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);
  771. erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
  772. start_au_allocator(ERTS_ALC_A_TEMPORARY,
  773. &init.temp_alloc,
  774. &temp_alloc_state);
  775. start_au_allocator(ERTS_ALC_A_SHORT_LIVED,
  776. &init.sl_alloc,
  777. &sl_alloc_state);
  778. start_au_allocator(ERTS_ALC_A_STANDARD,
  779. &init.std_alloc,
  780. &std_alloc_state);
  781. start_au_allocator(ERTS_ALC_A_LONG_LIVED,
  782. &init.ll_alloc,
  783. &ll_alloc_state);
  784. start_au_allocator(ERTS_ALC_A_EHEAP,
  785. &init.eheap_alloc,
  786. &eheap_alloc_state);
  787. start_au_allocator(ERTS_ALC_A_BINARY,
  788. &init.binary_alloc,
  789. &binary_alloc_state);
  790. start_au_allocator(ERTS_ALC_A_ETS,
  791. &init.ets_alloc,
  792. &ets_alloc_state);
  793. start_au_allocator(ERTS_ALC_A_DRIVER,
  794. &init.driver_alloc,
  795. &driver_alloc_state);
  796. start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
  797. &init.fix_alloc,
  798. &fix_alloc_state);
  799. start_au_allocator(ERTS_ALC_A_LITERAL,
  800. &init.literal_alloc,
  801. &literal_alloc_state);
  802. #ifdef ERTS_ALC_A_EXEC
  803. start_au_allocator(ERTS_ALC_A_EXEC,
  804. &init.exec_alloc,
  805. &exec_alloc_state);
  806. #endif
  807. start_au_allocator(ERTS_ALC_A_TEST,
  808. &init.test_alloc,
  809. &test_alloc_state);
  810. erts_mtrace_install_wrapper_functions();
  811. init_aireq_alloc();
  812. #ifdef DEBUG
  813. extra_block_size += install_debug_functions();
  814. #endif
  815. adjust_fix_alloc_sizes(extra_block_size);
  816. }
  817. void
  818. erts_alloc_late_init(void)
  819. {
  820. }
  821. static void *
  822. erts_realloc_fixed_size(ErtsAlcType_t type, void *extra, void *p, Uint size)
  823. {
  824. erts_exit(ERTS_ABORT_EXIT,
  825. "Attempt to reallocate a block of the fixed size type %s\n",
  826. ERTS_ALC_T2TD(type));
  827. }
  828. static void
  829. set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
  830. {
  831. ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
  832. ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
  833. ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
  834. /*
  835. * Some allocators are forced on if halfword heap is used.
  836. */
  837. if (init->init.util.force)
  838. init->enable = 1;
  839. tspec->enabled = 0;
  840. tspec->dd = 0;
  841. tspec->aix = alctr_n;
  842. tspec->size = 0;
  843. ai->thr_spec = 0;
  844. if (!init->enable) {
  845. af->alloc = erts_sys_alloc;
  846. af->realloc = erts_sys_realloc;
  847. af->free = erts_sys_free;
  848. af->extra = NULL;
  849. ai->alloc_util = 0;
  850. ai->enabled = 0;
  851. ai->extra = NULL;
  852. return;
  853. }
  854. if (init->thr_spec) {
  855. if (init->thr_spec > 0) {
  856. af->alloc = erts_alcu_alloc_thr_spec;
  857. if (init->init.util.fix_type_size)
  858. af->realloc = erts_realloc_fixed_size;
  859. else if (init->init.util.ramv)
  860. af->realloc = erts_alcu_realloc_mv_thr_spec;
  861. else
  862. af->realloc = erts_alcu_realloc_thr_spec;
  863. af->free = erts_alcu_free_thr_spec;
  864. }
  865. else {
  866. af->alloc = erts_alcu_alloc_thr_pref;
  867. if (init->init.util.fix_type_size)
  868. af->realloc = erts_realloc_fixed_size;
  869. else if (init->init.util.ramv)
  870. af->realloc = erts_alcu_realloc_mv_thr_pref;
  871. else
  872. af->realloc = erts_alcu_realloc_thr_pref;
  873. af->free = erts_alcu_free_thr_pref;
  874. tspec->dd = 1;
  875. }
  876. tspec->enabled = 1;
  877. tspec->size = abs(init->thr_spec) + 1;
  878. ai->thr_spec = tspec->size;
  879. }
  880. else
  881. if (init->init.util.ts) {
  882. af->alloc = erts_alcu_alloc_ts;
  883. if (init->init.util.fix_type_size)
  884. af->realloc = erts_realloc_fixed_size;
  885. else if (init->init.util.ramv)
  886. af->realloc = erts_alcu_realloc_mv_ts;
  887. else
  888. af->realloc = erts_alcu_realloc_ts;
  889. af->free = erts_alcu_free_ts;
  890. }
  891. else
  892. {
  893. erts_exit(ERTS_ABORT_EXIT, "%salloc is not thread safe\n",
  894. init->init.util.name_prefix);
  895. }
  896. af->extra = NULL;
  897. ai->alloc_util = 1;
  898. ai->enabled = 1;
  899. }
  900. static void
  901. start_au_allocator(ErtsAlcType_t alctr_n,
  902. struct au_init *init,
  903. ErtsAllocatorState_t *state)
  904. {
  905. int i;
  906. int size = 1;
  907. void *as0;
  908. ErtsAlcStrat_t astrat;
  909. ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
  910. ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
  911. ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
  912. ErtsAlcFixList_t *fix_lists = NULL;
  913. size_t fix_list_size = 0;
  914. if (!init->enable)
  915. return;
  916. if (init->thr_spec) {
  917. char *states = erts_sys_alloc(0,
  918. NULL,
  919. ((sizeof(Allctr_t *)
  920. * (tspec->size + 1))
  921. + (sizeof(ErtsAllocatorState_t)
  922. * tspec->size)
  923. + ERTS_CACHE_LINE_SIZE - 1));
  924. if (!states)
  925. erts_exit(ERTS_ABORT_EXIT,
  926. "Failed to allocate allocator states for %salloc\n",
  927. init->init.util.name_prefix);
  928. tspec->allctr = (Allctr_t **) states;
  929. states += sizeof(Allctr_t *) * (tspec->size + 1);
  930. states = ((((UWord) states) & ERTS_CACHE_LINE_MASK)
  931. ? (char *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
  932. + ERTS_CACHE_LINE_SIZE)
  933. : (char *) states);
  934. tspec->allctr[0] = (Allctr_t *) state;
  935. size = tspec->size;
  936. for (i = 1; i < size; i++)
  937. tspec->allctr[i] = (Allctr_t *)
  938. &((ErtsAllocatorState_t *) states)[i-1];
  939. }
  940. if (init->init.util.fix_type_size) {
  941. size_t tot_fix_list_size;
  942. fix_list_size = sizeof(ErtsAlcFixList_t)*ERTS_ALC_NO_FIXED_SIZES;
  943. fix_list_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(fix_list_size);
  944. tot_fix_list_size = fix_list_size;
  945. if (init->thr_spec)
  946. tot_fix_list_size *= tspec->size;
  947. fix_lists = erts_sys_alloc(0,
  948. NULL,
  949. (tot_fix_list_size
  950. + ERTS_CACHE_LINE_SIZE - 1));
  951. if (!fix_lists)
  952. erts_exit(ERTS_ABORT_EXIT,
  953. "Failed to allocate fix lists for %salloc\n",
  954. init->init.util.name_prefix);
  955. if (((UWord) fix_lists) & ERTS_CACHE_LINE_MASK)
  956. fix_lists = ((ErtsAlcFixList_t *)
  957. ((((UWord) fix_lists) & ~ERTS_CACHE_LINE_MASK)
  958. + ERTS_CACHE_LINE_SIZE));
  959. }
  960. for (i = 0; i < size; i++) {
  961. Allctr_t *as;
  962. astrat = init->astrat;
  963. if (!init->thr_spec)
  964. as0 = state;
  965. else {
  966. as0 = (void *) tspec->allctr[i];
  967. if (!as0)
  968. continue;
  969. if (init->thr_spec < 0) {
  970. init->init.util.ts = i == 0;
  971. init->init.util.tspec = 0;
  972. init->init.util.tpref = -1*init->thr_spec + 1;
  973. }
  974. else {
  975. if (i != 0)
  976. init->init.util.ts = 0;
  977. else {
  978. if (astrat == ERTS_ALC_S_AFIT)
  979. astrat = ERTS_ALC_S_GOODFIT;
  980. init->init.util.ts = 1;
  981. }
  982. init->init.util.tspec = init->thr_spec + 1;
  983. init->init.util.tpref = 0;
  984. }
  985. }
  986. if (fix_lists) {
  987. init->init.util.fix = fix_lists;
  988. fix_lists = ((ErtsAlcFixList_t *)
  989. (((char *) fix_lists) + fix_list_size));
  990. }
  991. init->init.util.alloc_strat = astrat;
  992. init->init.util.ix = i;
  993. switch (astrat) {
  994. case ERTS_ALC_S_GOODFIT:
  995. as = erts_gfalc_start((GFAllctr_t *) as0,
  996. &init->init.gf,
  997. &init->init.util);
  998. break;
  999. case ERTS_ALC_S_BESTFIT:
  1000. as = erts_bfalc_start((BFAllctr_t *) as0,
  1001. &init->init.bf,
  1002. &init->init.util);
  1003. break;
  1004. case ERTS_ALC_S_AFIT:
  1005. as = erts_afalc_start((AFAllctr_t *) as0,
  1006. &init->init.af,
  1007. &init->init.util);
  1008. break;
  1009. case ERTS_ALC_S_FIRSTFIT:
  1010. as = erts_aoffalc_start((AOFFAllctr_t *) as0,
  1011. &init->init.aoff,
  1012. &init->init.util);
  1013. break;
  1014. default:
  1015. as = NULL;
  1016. ASSERT(0);
  1017. }
  1018. if (!as)
  1019. erts_exit(ERTS_ABORT_EXIT,
  1020. "Failed to start %salloc\n", init->init.util.name_prefix);
  1021. ASSERT(as == (void *) as0);
  1022. af->extra = as;
  1023. }
  1024. if (init->thr_spec)
  1025. af->extra = tspec;
  1026. ai->extra = af->extra;
  1027. }
  1028. static void bad_param(char *param_start, char *param_end)
  1029. {
  1030. size_t len = param_end - param_start;
  1031. char param[100];
  1032. if (len > 99)
  1033. len = 99;
  1034. sys_memcpy((void *) param, (void *) param_start, len);
  1035. param[len] = '\0';
  1036. erts_fprintf(stderr, "bad \"%s\" parameter\n", param);
  1037. erts_usage();
  1038. }
  1039. static void bad_value(char *param_start, char *param_end, char *value)
  1040. {
  1041. size_t len = param_end - param_start;
  1042. char param[100];
  1043. if (len > 99)
  1044. len = 99;
  1045. sys_memcpy((void *) param, (void *) param_start, len);
  1046. param[len] = '\0';
  1047. erts_fprintf(stderr, "bad \"%s\" value: %s\n", param, value);
  1048. erts_usage();
  1049. }
  1050. /* Get arg marks argument as handled by
  1051. putting NULL in argv */
  1052. static char *
  1053. get_value(char* rest, char** argv, int* ip)
  1054. {
  1055. char *param = argv[*ip]+1;
  1056. argv[*ip] = NULL;
  1057. if (*rest == '\0') {
  1058. char *next = argv[*ip + 1];
  1059. if (next[0] == '-'
  1060. && next[1] == '-'
  1061. && next[2] == '\0') {
  1062. bad_value(param, rest, "");
  1063. }
  1064. (*ip)++;
  1065. argv[*ip] = NULL;
  1066. return next;
  1067. }
  1068. return rest;
  1069. }
  1070. static ERTS_INLINE int
  1071. has_prefix(const char *prefix, const char *string)
  1072. {
  1073. int i;
  1074. for (i = 0; prefix[i]; i++)
  1075. if (prefix[i] != string[i])
  1076. return 0;
  1077. return 1;
  1078. }
  1079. static int
  1080. get_bool_value(char *param_end, char** argv, int* ip)
  1081. {
  1082. char *param = argv[*ip]+1;
  1083. char *value = get_value(param_end, argv, ip);
  1084. if (sys_strcmp(value, "true") == 0)
  1085. return 1;
  1086. else if (sys_strcmp(value, "false") == 0)
  1087. return 0;
  1088. else
  1089. bad_value(param, param_end, value);
  1090. return -1;
  1091. }
  1092. static Uint kb_to_bytes(Sint kb, Uint *bytes)
  1093. {
  1094. const Uint max = ((~((Uint) 0))/1024) + 1;
  1095. if (kb < 0 || (Uint)kb > max)
  1096. return 0;
  1097. if ((Uint)kb == max)
  1098. *bytes = ~((Uint) 0);
  1099. else
  1100. *bytes = ((Uint) kb)*1024;
  1101. return 1;
  1102. }
  1103. static Uint
  1104. get_kb_value(char *param_end, char** argv, int* ip)
  1105. {
  1106. Sint tmp;
  1107. Uint bytes = 0;
  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 || !kb_to_bytes(tmp, &bytes))
  1114. bad_value(param, param_end, value);
  1115. return bytes;
  1116. }
  1117. static UWord
  1118. get_mb_value(char *param_end, char** argv, int* ip)
  1119. {
  1120. SWord tmp;
  1121. UWord max = ((~((UWord) 0))/(1024*1024)) + 1;
  1122. char *rest;
  1123. char *param = argv[*ip]+1;
  1124. char *value = get_value(param_end, argv, ip);
  1125. errno = 0;
  1126. tmp = (SWord) ErtsStrToSint(value, &rest, 10);
  1127. if (errno != 0 || rest == value || tmp < 0 || max < ((UWord) tmp))
  1128. bad_value(param, param_end, value);
  1129. if (max == (UWord) tmp)
  1130. return ~((UWord) 0);
  1131. else
  1132. return ((UWord) tmp)*1024*1024;
  1133. }
  1134. #if 0
  1135. static Uint
  1136. get_byte_value(char *param_end, char** argv, int* ip)
  1137. {
  1138. Sint tmp;
  1139. char *rest;
  1140. char *param = argv[*ip]+1;
  1141. char *value = get_value(param_end, argv, ip);
  1142. errno = 0;
  1143. tmp = (Sint) ErtsStrToSint(value, &rest, 10);
  1144. if (errno != 0 || rest == value || tmp < 0)
  1145. bad_value(param, param_end, value);
  1146. return (Uint) tmp;
  1147. }
  1148. #endif
  1149. static Uint
  1150. get_amount_value(char *param_end, char** argv, int* ip)
  1151. {
  1152. Sint tmp;
  1153. char *rest;
  1154. char *param = argv[*ip]+1;
  1155. char *value = get_value(param_end, argv, ip);
  1156. errno = 0;
  1157. tmp = (Sint) ErtsStrToSint(value, &rest, 10);
  1158. if (errno != 0 || rest == value || tmp < 0)
  1159. bad_value(param, param_end, value);
  1160. return (Uint) tmp;
  1161. }
  1162. static Uint
  1163. get_acul_value(struct au_init *auip, char *param_end, char** argv, int* ip)
  1164. {
  1165. Sint tmp;
  1166. char *rest;
  1167. char *param = argv[*ip]+1;
  1168. char *value = get_value(param_end, argv, ip);
  1169. if (sys_strcmp(value, "de") == 0) {
  1170. switch (auip->init.util.alloc_no) {
  1171. case ERTS_ALC_A_LONG_LIVED:
  1172. return ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC;
  1173. case ERTS_ALC_A_EHEAP:
  1174. return ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC;
  1175. default:
  1176. return ERTS_ALC_DEFAULT_ENABLED_ACUL;
  1177. }
  1178. }
  1179. errno = 0;
  1180. tmp = (Sint) ErtsStrToSint(value, &rest, 10);
  1181. if (errno != 0 || rest == value || tmp < 0 || 100 < tmp)
  1182. bad_value(param, param_end, value);
  1183. return (Uint) tmp;
  1184. }
  1185. static void
  1186. handle_au_arg(struct au_init *auip,
  1187. char* sub_param,
  1188. char** argv,
  1189. int* ip,
  1190. int u_switch)
  1191. {
  1192. char *param = argv[*ip]+1;
  1193. switch (sub_param[0]) {
  1194. case 'a':
  1195. if (sub_param[1] == 'c') { /* Migration parameters "ac*" */
  1196. UWord value;
  1197. UWord* wp;
  1198. if (!auip->carrier_migration_allowed && !u_switch)
  1199. goto bad_switch;
  1200. if (has_prefix("acul", sub_param)) {
  1201. value = get_acul_value(auip, sub_param + 4, argv, ip);
  1202. wp = &auip->init.util.acul;
  1203. }
  1204. else if (has_prefix("acnl", sub_param)) {
  1205. value = get_amount_value(sub_param + 4, argv, ip);
  1206. wp = &auip->init.util.acnl;
  1207. }
  1208. else if (has_prefix("acfml", sub_param)) {
  1209. value = get_amount_value(sub_param + 5, argv, ip);
  1210. wp = &auip->init.util.acfml;
  1211. }
  1212. else
  1213. goto bad_switch;
  1214. if (auip->carrier_migration_allowed)
  1215. *wp = value;
  1216. }
  1217. else if(has_prefix("asbcst", sub_param)) {
  1218. auip->init.util.asbcst = get_kb_value(sub_param + 6, argv, ip);
  1219. }
  1220. else if(has_prefix("as", sub_param)) {
  1221. char *alg = get_value(sub_param + 2, argv, ip);
  1222. if (sys_strcmp("bf", alg) == 0) {
  1223. auip->astrat = ERTS_ALC_S_BESTFIT;
  1224. auip->init.bf.ao = 0;
  1225. }
  1226. else if (sys_strcmp("aobf", alg) == 0) {
  1227. auip->astrat = ERTS_ALC_S_BESTFIT;
  1228. auip->init.bf.ao = 1;
  1229. }
  1230. else if (sys_strcmp("gf", alg) == 0) {
  1231. auip->astrat = ERTS_ALC_S_GOODFIT;
  1232. }
  1233. else if (sys_strcmp("af", alg) == 0) {
  1234. auip->astrat = ERTS_ALC_S_AFIT;
  1235. }
  1236. else if (sys_strcmp("aoff", alg) == 0) {
  1237. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1238. auip->init.aoff.crr_order = FF_AOFF;
  1239. auip->init.aoff.blk_order = FF_AOFF;
  1240. }
  1241. else if (sys_strcmp("aoffcbf", alg) == 0) {
  1242. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1243. auip->init.aoff.crr_order = FF_AOFF;
  1244. auip->init.aoff.blk_order = FF_BF;
  1245. }
  1246. else if (sys_strcmp("aoffcaobf", alg) == 0) {
  1247. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1248. auip->init.aoff.crr_order = FF_AOFF;
  1249. auip->init.aoff.blk_order = FF_AOBF;
  1250. }
  1251. else if (sys_strcmp("ageffcaoff", alg) == 0) {
  1252. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1253. auip->init.aoff.crr_order = FF_AGEFF;
  1254. auip->init.aoff.blk_order = FF_AOFF;
  1255. }
  1256. else if (sys_strcmp("ageffcbf", alg) == 0) {
  1257. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1258. auip->init.aoff.crr_order = FF_AGEFF;
  1259. auip->init.aoff.blk_order = FF_BF;
  1260. }
  1261. else if (sys_strcmp("ageffcaobf", alg) == 0) {
  1262. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1263. auip->init.aoff.crr_order = FF_AGEFF;
  1264. auip->init.aoff.blk_order = FF_AOBF;
  1265. }
  1266. else {
  1267. if (auip->init.util.alloc_no == ERTS_ALC_A_TEST
  1268. && sys_strcmp("chaosff", alg) == 0) {
  1269. auip->astrat = ERTS_ALC_S_FIRSTFIT;
  1270. auip->init.aoff.crr_order = FF_CHAOS;
  1271. auip->init.aoff.blk_order = FF_CHAOS;
  1272. }
  1273. else {
  1274. bad_value(param, sub_param + 1, alg);
  1275. }
  1276. }
  1277. if (!strategy_support_carrier_migration(auip))
  1278. auip->init.util.acul = 0;
  1279. } else if (has_prefix("atags", sub_param)) {
  1280. auip->init.util.atags = get_bool_value(sub_param + 5, argv, ip);
  1281. }
  1282. else
  1283. goto bad_switch;
  1284. break;
  1285. case 'e': {
  1286. int e = get_bool_value(sub_param + 1, argv, ip);
  1287. if (!auip->disable_allowed && !e) {
  1288. if (!u_switch)
  1289. bad_value(param, sub_param + 1, "false");
  1290. else
  1291. ASSERT(auip->enable); /* ignore */
  1292. }
  1293. else auip->enable = e;
  1294. break;
  1295. }
  1296. case 'l':
  1297. if (has_prefix("lmbcs", sub_param)) {
  1298. auip->default_.lmbcs = 0;
  1299. auip->init.util.lmbcs = get_kb_value(sub_param + 5, argv, ip);
  1300. }
  1301. else
  1302. goto bad_switch;
  1303. break;
  1304. case 'm':
  1305. if (has_prefix("mbcgs", sub_param)) {
  1306. auip->init.util.mbcgs = get_amount_value(sub_param + 5, argv, ip);
  1307. }
  1308. else if (has_prefix("mbsd", sub_param)) {
  1309. auip->init.gf.mbsd = get_amount_value(sub_param + 4, argv, ip);
  1310. if (auip->init.gf.mbsd < 1)
  1311. auip->init.gf.mbsd = 1;
  1312. }
  1313. else if (has_prefix("mmbcs", sub_param)) {
  1314. auip->default_.mmbcs = 0;
  1315. auip->init.util.mmbcs = get_kb_value(sub_param + 5, argv, ip);
  1316. }
  1317. else if (has_prefix("mmmbc", sub_param)) {
  1318. auip->default_.mmmbc = 0;
  1319. auip->init.util.mmmbc = get_amount_value(sub_param + 5, argv, ip);
  1320. }
  1321. else if (has_prefix("mmsbc", sub_param)) {
  1322. auip->init.util.mmsbc = get_amount_value(sub_param + 5, argv, ip);
  1323. }
  1324. else
  1325. goto bad_switch;
  1326. break;
  1327. case 'r':
  1328. if(has_prefix("rsbcmt", sub_param)) {
  1329. auip->init.util.rsbcmt = get_amount_value(sub_param + 6, argv, ip);
  1330. if (auip->init.util.rsbcmt > 100)
  1331. auip->init.util.rsbcmt = 100;
  1332. }
  1333. else if(has_prefix("rsbcst", sub_param)) {
  1334. auip->init.util.rsbcst = get_amount_value(sub_param + 6, argv, ip);
  1335. if (auip->init.util.rsbcst > 100)
  1336. auip->init.util.rsbcst = 100;
  1337. }
  1338. else if (has_prefix("rmbcmt", sub_param)) {
  1339. auip->init.util.rmbcmt = get_amount_value(sub_param + 6, argv, ip);
  1340. if (auip->init.util.rmbcmt > 100)
  1341. auip->init.util.rmbcmt = 100;
  1342. }
  1343. else if (has_prefix("ramv", sub_param)) {
  1344. auip->init.util.ramv = get_bool_value(sub_param + 4, argv, ip);
  1345. }
  1346. else
  1347. goto bad_switch;
  1348. break;
  1349. case 's':
  1350. if(has_prefix("sbct", sub_param)) {
  1351. auip->init.util.sbct = get_kb_value(sub_param + 4, argv, ip);
  1352. }
  1353. else if (has_prefix("smbcs", sub_param)) {
  1354. auip->default_.smbcs = 0;
  1355. auip->init.util.smbcs = get_kb_value(sub_param + 5, argv, ip);
  1356. }
  1357. else
  1358. goto bad_switch;
  1359. break;
  1360. case 't': {
  1361. int res = get_bool_value(sub_param+1, argv, ip);
  1362. if (res > 0) {
  1363. if (!auip->thr_spec_allowed) {
  1364. if (!u_switch)
  1365. bad_value(param, sub_param + 1, "true");
  1366. else
  1367. ASSERT(!auip->thr_spec); /* ignore */
  1368. }
  1369. else
  1370. auip->thr_spec = 1;
  1371. break;
  1372. }
  1373. else if (res == 0) {
  1374. auip->thr_spec = 0;
  1375. auip->init.util.acul = 0;
  1376. break;
  1377. }
  1378. goto bad_switch;
  1379. }
  1380. default:
  1381. bad_switch:
  1382. bad_param(param, sub_param);
  1383. }
  1384. }
  1385. static void
  1386. handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
  1387. {
  1388. struct au_init *aui[] = {
  1389. &init->binary_alloc,
  1390. &init->std_alloc,
  1391. &init->ets_alloc,
  1392. &init->eheap_alloc,
  1393. &init->ll_alloc,
  1394. &init->driver_alloc,
  1395. &init->fix_alloc,
  1396. &init->sl_alloc
  1397. /* test_alloc not affected by +Mea??? or +Mu??? */
  1398. };
  1399. int aui_sz = (int) sizeof(aui)/sizeof(aui[0]);
  1400. char *arg;
  1401. char *rest;
  1402. int i, j;
  1403. i = 1;
  1404. ASSERT(argc && argv && init);
  1405. while (i < *argc) {
  1406. if(argv[i][0] == '-') {
  1407. char *param = argv[i]+1;
  1408. switch (argv[i][1]) {
  1409. case 'M':
  1410. switch (argv[i][2]) {
  1411. case 'B':
  1412. handle_au_arg(&init->binary_alloc, &argv[i][3], argv, &i, 0);
  1413. break;
  1414. case 'I':
  1415. if (has_prefix("scs", argv[i]+3)) {
  1416. #if HAVE_ERTS_MSEG
  1417. init->mseg.literal_mmap.scs =
  1418. #endif
  1419. get_mb_value(argv[i]+6, argv, &i);
  1420. }
  1421. else
  1422. handle_au_arg(&init->literal_alloc, &argv[i][3], argv, &i, 0);
  1423. break;
  1424. case 'X':
  1425. if (has_prefix("scs", argv[i]+3)) {
  1426. /* Ignore obsolete */
  1427. (void) get_mb_value(argv[i]+6, argv, &i);
  1428. }
  1429. else
  1430. handle_au_arg(&init->exec_alloc, &argv[i][3], argv, &i, 0);
  1431. break;
  1432. case 'D':
  1433. handle_au_arg(&init->std_alloc, &argv[i][3], argv, &i, 0);
  1434. break;
  1435. case 'E':
  1436. handle_au_arg(&init->ets_alloc, &argv[i][3], argv, &i, 0);
  1437. break;
  1438. case 'F':
  1439. handle_au_arg(&init->fix_alloc, &argv[i][3], argv, &i, 0);
  1440. break;
  1441. case 'H':
  1442. handle_au_arg(&init->eheap_alloc, &argv[i][3], argv, &i, 0);
  1443. break;
  1444. case 'L':
  1445. handle_au_arg(&init->ll_alloc, &argv[i][3], argv, &i, 0);
  1446. break;
  1447. case 'M':
  1448. if (has_prefix("amcbf", argv[i]+3)) {
  1449. #if HAVE_ERTS_MSEG
  1450. init->mseg.amcbf =
  1451. #endif
  1452. get_kb_value(argv[i]+8, argv, &i);
  1453. }
  1454. else if (has_prefix("rmcbf", argv[i]+3)) {
  1455. #if HAVE_ERTS_MSEG
  1456. init->mseg.rmcbf =
  1457. #endif
  1458. get_amount_value(argv[i]+8, argv, &i);
  1459. }
  1460. else if (has_prefix("mcs", argv[i]+3)) {
  1461. #if HAVE_ERTS_MSEG
  1462. init->mseg.mcs =
  1463. #endif
  1464. get_amount_value(argv[i]+6, argv, &i);
  1465. }
  1466. else if (has_prefix("scs", argv[i]+3)) {
  1467. #if HAVE_ERTS_MSEG
  1468. init->mseg.dflt_mmap.scs =
  1469. #endif
  1470. get_mb_value(argv[i]+6, argv, &i);
  1471. }
  1472. else if (has_prefix("sco", argv[i]+3)) {
  1473. #if HAVE_ERTS_MSEG
  1474. init->mseg.dflt_mmap.sco =
  1475. #endif
  1476. get_bool_value(argv[i]+6, argv, &i);
  1477. }
  1478. else if (has_prefix("scrpm", argv[i]+3)) {
  1479. #if HAVE_ERTS_MSEG
  1480. init->mseg.dflt_mmap.scrpm =
  1481. #endif
  1482. get_bool_value(argv[i]+8, argv, &i);
  1483. }
  1484. else if (has_prefix("scrfsd", argv[i]+3)) {
  1485. #if HAVE_ERTS_MSEG
  1486. init->mseg.dflt_mmap.scrfsd =
  1487. #endif
  1488. get_amount_value(argv[i]+9, argv, &i);
  1489. }
  1490. else {
  1491. bad_param(param, param+2);
  1492. }
  1493. break;
  1494. case 'R':
  1495. handle_au_arg(&init->driver_alloc, &argv[i][3], argv, &i, 0);
  1496. break;
  1497. case 'S':
  1498. handle_au_arg(&init->sl_alloc, &argv[i][3], argv, &i, 0);
  1499. break;
  1500. case 'T':
  1501. handle_au_arg(&init->temp_alloc, &argv[i][3], argv, &i, 0);
  1502. break;
  1503. case 'Z':
  1504. handle_au_arg(&init->test_alloc, &argv[i][3], argv, &i, 0);
  1505. break;
  1506. case 'Y': { /* sys_alloc */
  1507. if (has_prefix("tt", param+2)) {
  1508. /* set trim threshold */
  1509. arg = get_value(param+4, argv, &i);
  1510. errno = 0;
  1511. init->trim_threshold = (int) strtol(arg, &rest, 10);
  1512. if (errno != 0
  1513. || rest == arg
  1514. || init->trim_threshold < 0
  1515. || (INT_MAX/1024) < init->trim_threshold) {
  1516. bad_value(param, param+4, arg);
  1517. }
  1518. VERBOSE(DEBUG_SYSTEM,
  1519. ("using trim threshold: %d\n",
  1520. init->trim_threshold));
  1521. init->trim_threshold *= 1024;
  1522. }
  1523. else if (has_prefix("tp", param+2)) {
  1524. /* set top pad */
  1525. arg = get_value(param+4, argv, &i);
  1526. errno = 0;
  1527. init->top_pad = (int) strtol(arg, &rest, 10);
  1528. if (errno != 0
  1529. || rest == arg
  1530. || init->top_pad < 0
  1531. || (INT_MAX/1024) < init->top_pad) {
  1532. bad_value(param, param+4, arg);
  1533. }
  1534. VERBOSE(DEBUG_SYSTEM,
  1535. ("using top pad: %d\n",init->top_pad));
  1536. init->top_pad *= 1024;
  1537. }
  1538. else if (has_prefix("m", param+2)) {
  1539. /* Has been handled by erlexec */
  1540. (void) get_value(param+3, argv, &i);
  1541. }
  1542. else if (has_prefix("e", param+2)) {
  1543. arg = get_value(param+3, argv, &i);
  1544. if (sys_strcmp("true", arg) != 0)
  1545. bad_value(param, param+3, arg);
  1546. }
  1547. else
  1548. bad_param(param, param+2);
  1549. break;
  1550. }
  1551. case 'e':
  1552. switch (argv[i][3]) {
  1553. case 'a': {
  1554. int a;
  1555. arg = get_value(argv[i]+4, argv, &i);
  1556. if (sys_strcmp("min", arg) == 0) {
  1557. for (a = 0; a < aui_sz; a++)
  1558. aui[a]->enable = 0;
  1559. }
  1560. else if (sys_strcmp("max", arg) == 0) {
  1561. for (a = 0; a < aui_sz; a++)
  1562. aui[a]->enable = 1;
  1563. }
  1564. else if (sys_strcmp("config", arg) == 0) {
  1565. init->erts_alloc_config = 1;
  1566. }
  1567. else if (sys_strcmp("r9c", arg) == 0
  1568. || sys_strcmp("r10b", arg) == 0
  1569. || sys_strcmp("r11b", arg) == 0) {
  1570. set_default_sl_alloc_opts(&init->sl_alloc);
  1571. set_default_std_alloc_opts(&init->std_alloc);
  1572. set_default_ll_alloc_opts(&init->ll_alloc);
  1573. set_default_temp_alloc_opts(&init->temp_alloc);
  1574. set_default_eheap_alloc_opts(&init->eheap_alloc);
  1575. set_default_binary_alloc_opts(&init->binary_alloc);
  1576. se

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