[Mesa-dev] [PATCH 3/7] util/slab: Add function to flush allocations from a child pool

Haehnle, Nicolai Nicolai.Haehnle at amd.com
Wed Nov 21 21:31:45 UTC 2018


On 21.11.18 22:23, Ian Romanick wrote:
> On 11/21/2018 12:23 PM, Haehnle, Nicolai wrote:
>> On 21.11.18 19:19, Ian Romanick wrote:
>>> On 11/21/2018 03:08 AM, Haehnle, Nicolai wrote:
>>>> On 21.11.18 01:39, Ian Romanick wrote:
>>>>> From: Ian Romanick <ian.d.romanick at intel.com>
>>>>>
>>>>> Ralloc has a feature that all allocations from a temporary memory
>>>>> context can be whisked away in a single call without fear of leaks.  As
>>>>> the slab allocator is designed for use in multhreaded scenarios with a
>>>>> child pool per CPU, it lacks this feature.  However, many users will be
>>>>> single threaded with a single child pool.  For these users, we can have
>>>>> our cake and eat it too.
>>>>>
>>>>> Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
>>>>> Cc: Nicolai Hähnle <nicolai.haehnle at amd.com>
>>>>> ---
>>>>>     src/util/slab.c | 21 +++++++++++++++++++++
>>>>>     src/util/slab.h |  1 +
>>>>>     2 files changed, 22 insertions(+)
>>>>>
>>>>> diff --git a/src/util/slab.c b/src/util/slab.c
>>>>> index 5f048666b56..1bcc1db6e09 100644
>>>>> --- a/src/util/slab.c
>>>>> +++ b/src/util/slab.c
>>>>> @@ -172,6 +172,27 @@ void slab_destroy_child(struct slab_child_pool *pool)
>>>>>        pool->parent = NULL;
>>>>>     }
>>>>>     
>>>>> +/**
>>>>> + * Flush all allocations from a pool.  Single-threaded (no mutex).
>>>>> + */
>>>>> +void
>>>>> +slab_flush_st(struct slab_mempool *parent)
>>>>
>>>> The name of the function argument should be "pool" for consistency.
>>>
>>> This is one thing that annoyed me while writing this function.
>>> Sometimes "pool" is a slab_mempool.  Sometimes "pool" is a
>>> slab_child_pool.  What do you do when you have both?  For the most part,
>>> the thing that gets the most use in a function is the thing called pool.
>>>    In this case, that's the slab_child_pool, but that's not the parameter
>>> passed in.
>>>
>>> slab_alloc_st, slab_free_st, slab_create, and slab_destroy are the only
>>> other functions that take a slab_mempool.  These functions work around
>>> this issue by immediately calling some other public function with
>>> &pool->child.  I didn't want to make a public function to flush an
>>> arbitrary slab_child_pool because that's very dangerous in the general
>>> case.  Having a one-line public function that calls a private function
>>> will just beg some newbie to come along and fix it... and end up with
>>> the same problem. :)
>>>
>>>>> +{
>>>>> +   struct slab_child_pool *const pool = &parent->child;
>>>>> +
>>>>> +   assert(pool->migrated == NULL);
>>>>> +   assert(pool->parent == parent);
>>>>
>>>> I'm surprised this works. Why isn't pool->parent == &parent->parent?
>>>
>>> This is just a sanity check on an invariant of the data structure.  If
>>> the slab_mempool wasn't initialized or if it has been destroyed,
>>> parent->child.parent will be garbage or NULL.
>>
>> Right, I get that, but pool->parent is of type slab_parent_pool while
>> parent is of type slab_mempool. I don't see how that adds up.
> 
> Ah, now I see what you're saying.  Ignoring the other naming discussion,
> this should be
> 
>     assert(pool->parent == &parent->parent);
> 
> On that topic... how would you feel about changing the "pool" parameter
> to be "mempool" in the 5 places (counting the one added by this patch)
> where that parameter has type 'struct slab_mempool *'?  Then we'll
> universally have 'struct slab_child_pool *pool' and 'struct slab_mempool
> *mempool'.

+1, that's a good idea!

Cheers,
Nicolai


> 
>> Cheers,
>> Nicolai
>>
>>>> Or, with a consistently named function argument, why isn't
>>>> pool->child.parent == &pool->parent?
>>>>
>>>> The intention of the patch looks fine though.
>>>>
>>>> Cheers,
>>>> Nicolai
>>>>
>>>>
>>>>> +
>>>>> +   while (pool->pages) {
>>>>> +      struct slab_page_header *page = pool->pages;
>>>>> +      pool->pages = page->u.next;
>>>>> +
>>>>> +      free(page);
>>>>> +   }
>>>>> +
>>>>> +   pool->free = NULL;
>>>>> +}
>>>>> +
>>>>>     static bool
>>>>>     slab_add_new_page(struct slab_child_pool *pool)
>>>>>     {
>>>>> diff --git a/src/util/slab.h b/src/util/slab.h
>>>>> index e83f8ec1a0e..a4279d8e65b 100644
>>>>> --- a/src/util/slab.h
>>>>> +++ b/src/util/slab.h
>>>>> @@ -90,5 +90,6 @@ void slab_create(struct slab_mempool *pool,
>>>>>     void slab_destroy(struct slab_mempool *pool);
>>>>>     void *slab_alloc_st(struct slab_mempool *pool);
>>>>>     void slab_free_st(struct slab_mempool *pool, void *ptr);
>>>>> +void slab_flush_st(struct slab_mempool *parent);
>>>>>     
>>>>>     #endif
>>>>>


More information about the mesa-dev mailing list