Question about the spare chunk
cee1
fykcee1 at gmail.com
Mon Dec 8 04:28:34 PST 2014
2014-12-05 13:17 GMT+08:00 cee1 <fykcee1 at gmail.com>:
> Hi,
>
> Thanks for the reply!
>
> 2014-12-04 7:41 GMT+08:00 Jason Evans <jasone at canonware.com>:
>> On Dec 3, 2014, at 6:17 AM, cee1 <fykcee1 at gmail.com> wrote:
>>> Here the old spare chunk is replaced by the new one and dealloced.
>>>
>>> The deallocating process is done without the lock protection. In this
>>> lockless period, is it possible another arena_chunk_dealloc running in
>>> another thread replaces and deallocates ** our new spare chunk ** ?
>>> Which is still in the chunks_dirty tree and will be accessed by the
>>> purge process later.
>>
>> The chunk being passed to chunk_dealloc() has been completely dissociated from the arena prior to the malloc_mutex_unlock() call, so there's no way for it to be accessed by the arena again. If another thread concurrently calls into arena_chunk_dealloc() to deallocate the current spare, then the same logic holds for that chunk deallocation.
>
> Could you describe this more detail?
>
> """ <--- code snippet in arena_chunk_dealloc()
>
> assert(arena_mapbits_dirty_get(chunk, map_bias) ==
> arena_mapbits_dirty_get(chunk, chunk_npages-1));
> /*
> * Remove run from the runs_avail tree, so that the arena does not use
> * it.
> */
> arena_avail_remove(arena, chunk, map_bias, chunk_npages-map_bias, false, false);
>
> if (arena->spare != NULL) {
> arena_chunk_t *spare = arena->spare;
> arena->spare = chunk;
>
> malloc_mutex_unlock(&arena->lock);
> ...
> """
>
> What I understand:
> 1. The chunk may be whole dirty, i.e. n_dirty == 1.
>
> 2. After calling arena_avail_remove, the chunk may still be in
> arena->chunks_dirty
Sorry for didn't notice the chunk will be removed from
arena->chunks_dirty in arena_avail_remove():
"""
if (arena_mapbits_dirty_get(chunk, pageind) != 0) {
arena->ndirty -= npages;
chunk->ndirty -= npages;
}
if (chunk->ndirty != 0)
arena_chunk_dirty_insert(&arena->chunks_dirty, chunk);
"""
Then the question becomes what case does the branch in
arena_chunk_purge() to catch:
"""
if (chunk == arena->spare) {
assert(arena_mapbits_dirty_get(chunk, map_bias) != 0);
assert(arena_mapbits_dirty_get(chunk, chunk_npages-1) != 0);
arena_chunk_alloc(arena);
}
"""
The invocation path is
"arena_run_dalloc()/arena_maybe_purge()/arena_purge()
/arena_chunk_purge(arena, chunk, all)"
I notice:
1. The chunk parameter of arena_chunk_purge() is from "chunk =
arena_chunk_dirty_first(&arena->chunks_dirty)"
2. arena->chunks_dirty should not hold any reference to arena->spare
So the branch should always be skipped, am I right?
>
> BTW, in function arena_run_regind(), I notice a "plus 1" in
> """
> define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1)
> """
>
> Why we need this?
--
Regards,
- cee1
More information about the jemalloc-discuss
mailing list