in win32/src/gballoc_ll_jemalloc.c [228:351]
static int gballoc_ll_set_decay(int64_t decay_milliseconds, bool is_dirty_decay)
{
int result;
const char* decay_type = is_dirty_decay ? "dirty" : "muzzy";
const char* option_arenas = is_dirty_decay ? "arenas.dirty_decay_ms" : "arenas.muzzy_decay_ms";
const char* option_arena = is_dirty_decay ? "arena.%" PRIu32 ".dirty_decay_ms" : "arena.%" PRIu32 ".muzzy_decay_ms";
if (decay_milliseconds < -1)
{
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_019: [ If decay_milliseconds is less than -1, gballoc_ll_set_option shall fail and return a non-zero value. ]*/
LogError("decay_milliseconds must be -1 or greater, decay_milliseconds=%" PRId64 "", decay_milliseconds);
result = MU_FAILURE;
}
else
{
int64_t old_decay_milliseconds = -1;
size_t old_decay_milliseconds_size = sizeof(old_decay_milliseconds);
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_005: [ gballoc_ll_set_option shall retrieve the old decay value and set the new decay value to decay_milliseconds for new arenas by calling je_mallctl with arenas.dirty_decay_ms if option_name is dirty_decay or arenas.muzzy_decay_ms if option_name is muzzy_decay as the command. ]*/
if (je_mallctl(option_arenas, &old_decay_milliseconds, &old_decay_milliseconds_size, &decay_milliseconds, sizeof(decay_milliseconds)) != 0)
{
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_018: [ If there are any errors, gballoc_ll_set_option shall fail and return a non-zero value. ]*/
LogError("je_mallctl(option_arenas=%s, &old_decay_milliseconds=%p, &old_decay_milliseconds_size=%p, &decay_milliseconds=%p, sizeof(decay_milliseconds)=%zu) failed, old_decay_milliseconds=%" PRId64 "", option_arenas, &old_decay_milliseconds, &old_decay_milliseconds_size, &decay_milliseconds, sizeof(decay_milliseconds), old_decay_milliseconds);
result = MU_FAILURE;
}
else
{
LogInfo("jemalloc %s_decay_ms set to %" PRId64 " for new arenas, old value was %" PRId64 "", decay_type, decay_milliseconds, old_decay_milliseconds);
uint32_t narenas;
size_t narenas_size = sizeof(narenas);
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_007: [ gballoc_ll_set_option shall fetch the number of existing jemalloc arenas by calling je_mallctl with opt.narenas as the command. ]*/
if (je_mallctl("opt.narenas", &narenas, &narenas_size, NULL, 0) != 0)
{
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_018: [ If there are any errors, gballoc_ll_set_option shall fail and return a non-zero value. ]*/
LogError("je_mallctl(opt.narenas, &narenas=%p, &narenas_size=%p, NULL, 0) failed", &narenas, &narenas_size);
result = MU_FAILURE;
}
else
{
char command[64];
uint32_t i;
int snprintf_result;
int arena_decay_result;
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_008: [ For each existing arena except last (since it is reserved for huge arena) ]*/
for (i = 0; i < narenas; i++)
{
snprintf_result = snprintf(command, sizeof(command), option_arena, i);
if (snprintf_result < 0 || (size_t)snprintf_result >= sizeof(command))
{
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_018: [ If there are any errors, gballoc_ll_set_option shall fail and return a non-zero value. ]*/
LogError("snprintf(command=%p, sizeof(command)=%zu, option_arena=%s, i=%" PRIu32 ") failed %s", command, sizeof(command), option_arena, i, (snprintf_result < 0) ? " with encoding error" : " due to insufficient buffer size");
break;
}
else
{
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_009: [ gballoc_ll_set_option shall set the decay time for the arena to decay_milliseconds milliseconds by calling je_mallctl with arena.<i>.dirty_decay_ms if option_name is dirty_decay or arena.<i>.muzzy_decay_ms if option_name is muzzy_decay as the command. ]*/
arena_decay_result = je_mallctl(command, NULL, NULL, &decay_milliseconds, sizeof(decay_milliseconds));
if (arena_decay_result != 0)
{
if (arena_decay_result == EFAULT)
{
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_020: [ If je_mallctl returns EFAULT, gballoc_ll_set_option shall continue without failing as this error is expected when the arena doesn't exist. ]*/
LogError("je_mallctl(command=%s, NULL, NULL, &decay_milliseconds=%p, sizeof(decay_milliseconds)=%zu) failed, continuing without failure as the arena doesn't exist, old_decay_milliseconds=%" PRId64 "", command, &decay_milliseconds, sizeof(decay_milliseconds), old_decay_milliseconds);
}
else
{
/*Codes_SRS_GBALLOC_LL_JEMALLOC_28_018: [ If there are any errors, gballoc_ll_set_option shall fail and return a non-zero value. ]*/
LogError("je_mallctl(command=%s, NULL, NULL, &decay_milliseconds=%p, sizeof(decay_milliseconds)=%zu) failed, old_decay_milliseconds=%" PRId64 "", command, &decay_milliseconds, sizeof(decay_milliseconds), old_decay_milliseconds);
break;
}
}
}
}
if (i < narenas)
{
for (uint32_t j = 0; j < i; j++)
{
snprintf_result = snprintf(command, sizeof(command), option_arena, j);
if (snprintf_result < 0 || (size_t)snprintf_result >= sizeof(command))
{
LogError("snprintf(command=%p, sizeof(command)=%zu, option_arena=%s, j=%" PRIu32 ") failed %s during cleanup", command, sizeof(command), option_arena, j, (snprintf_result < 0) ? " with encoding error" : " due to insufficient buffer size");
}
else
{
arena_decay_result = je_mallctl(command, NULL, NULL, &old_decay_milliseconds, sizeof(old_decay_milliseconds));
if (arena_decay_result != 0)
{
if (arena_decay_result == EFAULT)
{
LogError("je_mallctl(command=%s, NULL, NULL, &old_decay_milliseconds=%p, sizeof(old_decay_milliseconds)=%zu) failed during cleanup as the arenas doesn't exist", command, &old_decay_milliseconds, sizeof(old_decay_milliseconds));
}
else
{
LogError("je_mallctl(command=%s, NULL, NULL, &old_decay_milliseconds=%p, sizeof(old_decay_milliseconds)=%zu) failed during cleanup", command, &old_decay_milliseconds, sizeof(old_decay_milliseconds));
}
}
}
}
result = MU_FAILURE;
}
else
{
result = 0;
LogInfo("jemalloc %s_decay_ms set to %" PRId64 ", old value was %" PRId64 "", decay_type, decay_milliseconds, old_decay_milliseconds);
goto all_ok;
}
}
if (je_mallctl(option_arenas, NULL, NULL, &old_decay_milliseconds, sizeof(old_decay_milliseconds)) != 0)
{
LogError("je_mallctl(option_arenas=%s, NULL, NULL, &old_decay_milliseconds=%p, sizeof(old_decay_milliseconds)=%zu) failed during cleanup", option_arenas, &old_decay_milliseconds, sizeof(old_decay_milliseconds));
}
}
}
all_ok:
return result;
}