This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC 2/2] Adding memory pool API.
- From: OndÅej BÃlka <neleai at seznam dot cz>
- To: libc-alpha at sourceware dot org
- Date: Mon, 11 Nov 2013 17:10:44 +0100
- Subject: [RFC 2/2] Adding memory pool API.
- Authentication-results: sourceware.org; auth=none
- References: <20131111142049 dot GA13002 at domone dot podge>
On a custom free we could build a memory pool api.
It is designed to be fast on single thread usage but to allow
multi-thread usage. I plan to add a small memory pool into malloc
to improve performance so in this api allocations must happen in single
thread. Relaxing this is possible but pointless as malloc would do
almost equal job.
To avoid performance arguments I reimplemented thread identification by
a thread local variable (which is also less ugly than pthread_self).
In actual implementation we should add preallocation logic and free
logic.
Also as api is concerned it would need better naming that is now.
#include <stdint.h>
#include <stdlib.h>
void *
dmalloc (size_t s, void *data, void (*destroy)(void *, size_t, void *, void (*)(void *)));
/* As pthread_self is ugly and potentialy slow we use a tls alternative. */
uint64_t threadno;
__thread uint64_t threadid;
/* We allow to get stack allocation only from thread that
initialized stack but returning from arbitrary thread.
For multithread usage a malloc already contain pool logic
for small sizes. */
struct stack {
uint64_t threadid;
void **available;
void **returned;
size_t size;
};
struct stack *stack_create(size_t size)
{
struct stack *s = malloc(sizeof (struct stack));
if (!threadid)
threadid = __sync_fetch_and_add (&threadno, 1) + 1;
s->size = size;
s->threadid = threadid;
s->available = NULL;
s->returned = NULL;
return s;
}
static void stack_return (void *_p, size_t size, void *_s, void (*freep)(void *))
{
void **p = (void **) _p;
struct stack *s = (struct stack *) _s;
void **old;
if (threadid == s->threadid) {
*p = s-> available;
s->available = p;
} else {
do {
old = s->returned;
*p = (void *) old;
} while (!__sync_bool_compare_and_swap (&s->returned, old, p));
}
}
void *stack_get(struct stack *s){
if (s->threadid != threadid)
abort();
if (s->available)
{
void *ret = s->available;
s->available = (void **) *s->available;
return ret;
}
else
{
if (s->returned)
{
do {
s->available = s->returned;
} while (!__sync_bool_compare_and_swap(&s->returned, s->available, NULL));
return stack_get(s);
}
return dmalloc (s->size, s, stack_return);
}
}
void stack_destroy(struct stack *s){
/* After this call a stack comes to zombie state and will wait
until all memory is freed until it destroys itself. */
}