diff options
author | Sverker Eriksson <sverker@erlang.org> | 2012-11-29 19:25:07 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <egil@erlang.org> | 2012-12-14 15:12:58 +0100 |
commit | b27bb5275d58b0abeadc4664ed27febe625f8ff0 (patch) | |
tree | a8cd69367c64bc82143a00197ac07880fe8dce7f /erts/emulator/beam/erl_alloc_util.c | |
parent | 971d054018d94dd89c2323e237f9c6c3afa91e3b (diff) | |
download | otp-b27bb5275d58b0abeadc4664ed27febe625f8ff0.tar.gz otp-b27bb5275d58b0abeadc4664ed27febe625f8ff0.tar.bz2 otp-b27bb5275d58b0abeadc4664ed27febe625f8ff0.zip |
erts: Fix bug when allocating size near sbc_threshold
A block larger than sbc_threshold can be allocated in MBC if the subsequent
"residue block" is smaller than min_block_size.
Solved by lowering sbc_threshold to ("hard limit" - min_block_size).
Diffstat (limited to 'erts/emulator/beam/erl_alloc_util.c')
-rw-r--r-- | erts/emulator/beam/erl_alloc_util.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index e6aa93b9d8..f4e6f0bba0 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -1404,6 +1404,7 @@ mbc_alloc_finalize(Allctr_t *allctr, ASSERT(FBLK_TO_MBC(nxt_blk) == crr); } else { + ASSERT(org_blk_sz <= MBC_ABLK_SZ_MASK); blk_sz = org_blk_sz; if (flags & LAST_BLK_HDR_FLG) { if (valid_blk_info) @@ -4163,12 +4164,6 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) allctr->ramv = init->ramv; allctr->main_carrier_size = init->mmbcs; - allctr->sbc_threshold = init->sbct; -#ifndef ARCH_64 - if (allctr->sbc_threshold > MBC_ABLK_SZ_MASK - ABLK_HDR_SZ) { - allctr->sbc_threshold = MBC_ABLK_SZ_MASK - ABLK_HDR_SZ + 1; - } -#endif #if HAVE_ERTS_MSEG allctr->mseg_opt.abs_shrink_th = init->asbcst; @@ -4210,6 +4205,23 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) } #endif + allctr->sbc_threshold = init->sbct; +#ifndef ARCH_64 + if (allctr->sbc_threshold > 0) { + Uint max_mbc_block_sz = UNIT_CEILING(allctr->sbc_threshold - 1 + ABLK_HDR_SZ); + if (max_mbc_block_sz + UNIT_FLOOR(allctr->min_block_size - 1) > MBC_ABLK_SZ_MASK + || max_mbc_block_sz < allctr->sbc_threshold) { /* wrap around */ + /* + * By limiting sbc_threshold to (hard limit - min_block_size) + * we avoid having to split off free "residue blocks" + * smaller than min_block_size. + */ + max_mbc_block_sz = MBC_ABLK_SZ_MASK - UNIT_FLOOR(allctr->min_block_size - 1); + allctr->sbc_threshold = max_mbc_block_sz - ABLK_HDR_SZ + 1; + } + } +#endif + allctr->sbmbc_threshold = init->sbmbct; |