This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [RFC 1/*] free memory asynchronously.
- From: OndÅej BÃlka <neleai at seznam dot cz>
- To: libc-alpha at sourceware dot org
- Date: Wed, 26 Feb 2014 22:34:42 +0100
- Subject: Re: [RFC 1/*] free memory asynchronously.
- Authentication-results: sourceware.org; auth=none
- References: <20140226204908 dot GA25189 at domone dot podge>
On Wed, Feb 26, 2014 at 09:49:08PM +0100, OndÅej BÃlka wrote:
> Hi,
>
> To move faster with malloc I will start posting what I have in uglier
> form which would be prettier if we did refactorings.
>
> As I mentioned previously that in fastbins atomic part and locking of
> malloc is really not needed as memory could be returned asynchronously.
>
> A minimal patch to add these is following which just add alloc/free
> logic.
>
I added changelog and forgotten to say that partially fixes following
bug by not having to lock in free:
Bug 12114 - Adding priority inheritance to malloc locking
There is still issue with realloc, I will ping a patch that we should
not realloc memory from different arenas.
[BZ #12114]
* malloc/malloc.c (_async_reclaim, _async_free): New function.
(_int_malloc): Call _async_reclaim).
(_int_free): Call _async_free.
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 74ad92d..eea4ca6 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -1696,6 +1696,11 @@ struct malloc_state
> /* Memory allocated from the system in this arena. */
> INTERNAL_SIZE_T system_mem;
> INTERNAL_SIZE_T max_system_mem;
> +
> + /* Asynchronously returned memory is placed here. It is linked list and
> + free atomically appends it while malloc atomically swaps it with
> + empty list. */
> + mchunkptr returned;
> };
>
> struct malloc_par
> @@ -3176,6 +3181,28 @@ __libc_calloc (size_t n, size_t elem_size)
> ------------------------------ malloc ------------------------------
> */
>
> + /* Reclaim asynchronously returned memory. */
> +static void
> +_async_reclaim (mstate av)
> +{
> + mchunkptr p = av->returned, tmp;
> + if (p)
> + {
> + /* We try to atomicaly swap list with empty one. This could fail when
> + contended with free. Then we wait for another malloc. */
> +
> + if (catomic_compare_and_exchange_bool_acq (&(av->returned), NULL, p))
> + {
> + while (p)
> + {
> + tmp = p->fd;
> + _int_free (av, p, 1);
> + p = tmp;
> + }
> + }
> + }
> +}
> +
> static void *
> _int_malloc (mstate av, size_t bytes)
> {
> @@ -3199,6 +3226,9 @@ _int_malloc (mstate av, size_t bytes)
>
> const char *errstr = NULL;
>
> + /* Check if there is asynchronously returned memory. */
> + _async_reclaim (av);
> +
> /*
> Convert request size to internal form by adding SIZE_SZ bytes
> overhead plus possibly more to obtain necessary alignment and/or
> @@ -3688,6 +3718,25 @@ _int_malloc (mstate av, size_t bytes)
> ------------------------------ free ------------------------------
> */
>
> + /* Return memory asynchronously. */
> +static void
> +_async_free (mstate av, mchunkptr p)
> +{
> + mchunkptr *r = &(av->returned);
> +
> + /* Append to linked list. As future improvement we could maintain a linked
> + lists for each other arena and use separate field for this appending. */
> +
> + mchunkptr old = *r, old2;
> + do
> + {
> + p->fd = old2 = old;
> + }
> + while ((old = catomic_compare_and_exchange_val_rel (r, p, old2)) != old2);
> +}
> +
> static void
> _int_free (mstate av, mchunkptr p, int have_lock)
> {
> @@ -3705,6 +3754,14 @@ _int_free (mstate av, mchunkptr p, int have_lock)
>
> size = chunksize (p);
>
> + if (!have_lock)
> + {
> + _async_free (av, p);
> + return;
> + }
> +
> /* Little security check which won't hurt performance: the
> allocator never wrapps around at the end of the address space.
> Therefore we can exclude some size values which might appear
--
Software uses US measurements, but the OS is in metric...