This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC 2/2] Adding memory pool API.


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.  */

}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]