461 lines
13 KiB
C
461 lines
13 KiB
C
|
#include "common.h"
|
||
|
|
||
|
#include <ddekit/lock.h>
|
||
|
#include <ddekit/memory.h>
|
||
|
#include <ddekit/panic.h>
|
||
|
#include <ddekit/pgtab.h>
|
||
|
#include <ddekit/inline.h>
|
||
|
#include <ddekit/types.h>
|
||
|
|
||
|
#ifdef DDEKIT_DEBUG_MEM
|
||
|
#undef DDEBUG
|
||
|
#define DDEBUG DDEKIT_DEBUG_MEM
|
||
|
#endif
|
||
|
#include "debug.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
#define SLAB_SIZE (4096*4)
|
||
|
|
||
|
struct ddekit_slab;
|
||
|
|
||
|
struct ddekit_slab_slab {
|
||
|
struct ddekit_slab * cache;
|
||
|
unsigned long free;
|
||
|
void *objects;
|
||
|
void *mem;
|
||
|
struct ddekit_slab_slab *next;
|
||
|
struct ddekit_slab_slab *prev;
|
||
|
};
|
||
|
|
||
|
struct ddekit_slab {
|
||
|
ddekit_lock_t lock;
|
||
|
void * data; /* user pointer */
|
||
|
int contiguous; /* is it coniguous mem*/
|
||
|
unsigned size; /* the size of he objects */
|
||
|
unsigned number; /* the number of objects stored per slab */
|
||
|
struct ddekit_slab_slab full;
|
||
|
struct ddekit_slab_slab partial;
|
||
|
struct ddekit_slab_slab empty;
|
||
|
};
|
||
|
|
||
|
FORWARD _PROTOTYPE( void ddekit_slab_lock, (struct ddekit_slab * sc) );
|
||
|
FORWARD _PROTOTYPE( void ddekit_slab_unlock, (struct ddekit_slab * sc) );
|
||
|
FORWARD _PROTOTYPE( struct ddekit_slab_slab * ddekit_slab_find_slab,
|
||
|
(struct ddekit_slab * sc, void * obj));
|
||
|
FORWARD _PROTOTYPE(void ddekit_slab_slab_insert,
|
||
|
(struct ddekit_slab_slab *list,
|
||
|
struct ddekit_slab_slab *s));
|
||
|
FORWARD _PROTOTYPE( void ddekit_slab_slab_remove, (struct ddekit_slab_slab *s));
|
||
|
FORWARD _PROTOTYPE( void ddekit_slab_grow, (struct ddekit_slab * sc));
|
||
|
FORWARD _PROTOTYPE( void *ddekit_slab_getobj, (struct ddekit_slab_slab *s));
|
||
|
FORWARD _PROTOTYPE( void ddekit_slab_free_slab,
|
||
|
(struct ddekit_slab_slab * sl, int cont));
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_simple_malloc *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void *ddekit_simple_malloc(unsigned size)
|
||
|
{
|
||
|
/* Simple memory allocation... malloc and free should be ok... */
|
||
|
void * r = malloc(size);
|
||
|
if (!r) {
|
||
|
ddekit_panic("out of mem?");
|
||
|
}
|
||
|
DDEBUG_MSG_VERBOSE("%p", r);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_simple_free *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void ddekit_simple_free(void *p)
|
||
|
{
|
||
|
DDEBUG_MSG_VERBOSE("%p", p);
|
||
|
free(p);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_large_malloc *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void *ddekit_large_malloc(int size)
|
||
|
{
|
||
|
ddekit_addr_t phys;
|
||
|
/* allocate a piece of coniguous memory */
|
||
|
void * r = alloc_contig(size, AC_ALIGN4K, &phys);
|
||
|
if (!r) {
|
||
|
ddekit_panic("out of mem?");
|
||
|
}
|
||
|
ddekit_pgtab_set_region_with_size(r, phys, size, PTE_TYPE_LARGE);
|
||
|
DDEBUG_MSG_VERBOSE("%p, phys: %p, size: %p.",r, phys, size);
|
||
|
DDEBUG_MSG_VERBOSE("%p", r);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_large_free *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void ddekit_large_free(void *p)
|
||
|
{
|
||
|
unsigned len;
|
||
|
DDEBUG_MSG_VERBOSE("get size of region %x", p);
|
||
|
len= ddekit_pgtab_get_size(p);
|
||
|
DDEBUG_MSG_VERBOSE("freeing %x, len %d...", p , len);
|
||
|
ddekit_pgtab_clear_region(p, 0); /* type is not used here... */
|
||
|
DDEBUG_MSG_VERBOSE("cleared region", p , len);
|
||
|
free_contig(p, len);
|
||
|
DDEBUG_MSG_VERBOSE("freed mem", p , len);
|
||
|
DDEBUG_MSG_VERBOSE("%p", p);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_contig_malloc *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void *ddekit_contig_malloc(unsigned long size, unsigned long low,
|
||
|
unsigned long high, unsigned long aligment,
|
||
|
unsigned long boundary)
|
||
|
{
|
||
|
WARN_UNIMPL;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_lock *
|
||
|
*****************************************************************************/
|
||
|
PRIVATE DDEKIT_INLINE void ddekit_slab_lock(struct ddekit_slab * sc) {
|
||
|
ddekit_lock_lock(&sc->lock);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_unlock *
|
||
|
*****************************************************************************/
|
||
|
PRIVATE DDEKIT_INLINE void ddekit_slab_unlock(struct ddekit_slab * sc) {
|
||
|
ddekit_lock_unlock(&sc->lock);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_find_slab *
|
||
|
*****************************************************************************/
|
||
|
PRIVATE struct ddekit_slab_slab *
|
||
|
ddekit_slab_find_slab(struct ddekit_slab * sc, void * obj)
|
||
|
{
|
||
|
|
||
|
struct ddekit_slab_slab *s;
|
||
|
|
||
|
for( s = sc->full.next; s!=&sc->full; s = s->next )
|
||
|
{
|
||
|
if (s->mem <= obj && obj < s->mem+(SLAB_SIZE))
|
||
|
{
|
||
|
return s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for( s = sc->partial.next; s!=&sc->partial; s = s->next )
|
||
|
{
|
||
|
if (s->mem <= obj && obj < s->mem+(SLAB_SIZE))
|
||
|
{
|
||
|
return s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_slab_insert *
|
||
|
*****************************************************************************/
|
||
|
static void ddekit_slab_slab_insert(struct ddekit_slab_slab *list,
|
||
|
struct ddekit_slab_slab *s)
|
||
|
{
|
||
|
s->prev = list;
|
||
|
s->next = list->next;
|
||
|
list->next->prev = s;
|
||
|
list->next = s;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_slab_remove *
|
||
|
*****************************************************************************/
|
||
|
PRIVATE void ddekit_slab_slab_remove(struct ddekit_slab_slab *s)
|
||
|
{
|
||
|
s->next->prev = s->prev;
|
||
|
s->prev->next = s->next;
|
||
|
s->next = s->prev = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_grow *
|
||
|
*****************************************************************************/
|
||
|
PRIVATE void ddekit_slab_grow(struct ddekit_slab *sc)
|
||
|
{
|
||
|
/*
|
||
|
* NOTE:
|
||
|
* As it doesn't seem to make problems ddekit_slabs are disregarding
|
||
|
* alignment. However this should be revisited, maybe this leads to
|
||
|
* performance degregation somewhere.
|
||
|
* Further the ddekit_slab doesn't have to be real slab, as the entries are
|
||
|
* initialized in the personalized DDEs. (slab is simple the wrong name.)
|
||
|
*/
|
||
|
int i;
|
||
|
char *p;
|
||
|
void **p1;
|
||
|
struct ddekit_slab_slab *s;
|
||
|
|
||
|
/* allocate slab control structure */
|
||
|
|
||
|
s = (struct ddekit_slab_slab *)
|
||
|
ddekit_simple_malloc(sizeof(struct ddekit_slab_slab));
|
||
|
|
||
|
s->cache = sc;
|
||
|
|
||
|
if(sc->contiguous)
|
||
|
s->mem = ddekit_large_malloc(SLAB_SIZE);
|
||
|
else
|
||
|
s->mem = ddekit_simple_malloc(SLAB_SIZE);
|
||
|
|
||
|
/* setup the object list */
|
||
|
|
||
|
s->free = sc->number;
|
||
|
|
||
|
/* put obj into list */
|
||
|
p1 = s->mem;
|
||
|
*p1 = s->mem;
|
||
|
s->objects = p1;
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("obj size: %d, memory at: %p , first obj: %p, %p ",
|
||
|
sc->size, s->mem, s->objects);
|
||
|
|
||
|
for (i = 0; i < s->free; i++)
|
||
|
{
|
||
|
p = *p1;
|
||
|
p1 = (void **) (p + sc->size);
|
||
|
|
||
|
if ( i != s->free-1 )
|
||
|
{
|
||
|
*p1 = p1+1;
|
||
|
DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*p1 = 0;
|
||
|
DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* add new slab to free list */
|
||
|
ddekit_slab_slab_insert(&sc->empty, s);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_getobj *
|
||
|
*****************************************************************************/
|
||
|
PRIVATE void *ddekit_slab_getobj(struct ddekit_slab_slab *s)
|
||
|
{
|
||
|
struct ddekit_slab *sc;
|
||
|
void *ret = 0;
|
||
|
|
||
|
sc = s->cache;
|
||
|
ret = s->objects;
|
||
|
|
||
|
/* get pointer to next object */
|
||
|
|
||
|
s->objects = *(void **)((char *) ret + sc->size);
|
||
|
s->free--;
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("old: %p new: %p", ret, s->objects);
|
||
|
|
||
|
/* if no more objects move to full */
|
||
|
|
||
|
if (!s->free)
|
||
|
{
|
||
|
ddekit_slab_slab_remove(s);
|
||
|
ddekit_slab_slab_insert(&sc->full,s);
|
||
|
}
|
||
|
|
||
|
if (s->free == sc->number-1)
|
||
|
{
|
||
|
ddekit_slab_slab_remove(s);
|
||
|
ddekit_slab_slab_insert(&sc->partial,s);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_alloc *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void *ddekit_slab_alloc(struct ddekit_slab * sc)
|
||
|
{
|
||
|
struct ddekit_slab_slab *s=0;
|
||
|
|
||
|
ddekit_slab_lock(sc);
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("from slab %p", sc);
|
||
|
|
||
|
/* first try from partial */
|
||
|
if (sc->partial.next != &sc->partial) {
|
||
|
DDEBUG_MSG_VERBOSE("from slab %p partial (next=%p)", sc,sc->partial.next);
|
||
|
s = sc->partial.next;
|
||
|
}
|
||
|
|
||
|
/* must grow? */
|
||
|
if (!s && (sc->empty.next == &sc->empty )){
|
||
|
DDEBUG_MSG_VERBOSE("slab %p has to grow", sc);
|
||
|
ddekit_slab_grow(sc);
|
||
|
}
|
||
|
|
||
|
/* take from free? */
|
||
|
if (!s) {
|
||
|
DDEBUG_MSG_VERBOSE("from slab %p empty", sc);
|
||
|
s = sc->empty.next;
|
||
|
}
|
||
|
|
||
|
ddekit_slab_unlock(sc);
|
||
|
|
||
|
return ddekit_slab_getobj(s);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_free *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void ddekit_slab_free(struct ddekit_slab *sc, void* obj)
|
||
|
{
|
||
|
void **p;
|
||
|
|
||
|
struct ddekit_slab_slab *s = 0;
|
||
|
|
||
|
ddekit_slab_lock(sc);
|
||
|
/* first find slab the obj came from */
|
||
|
|
||
|
s = ddekit_slab_find_slab(sc, obj);
|
||
|
|
||
|
p = (void **)((char *) obj + sc->size);
|
||
|
|
||
|
*p= s->objects;
|
||
|
s->objects=obj;
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("old: %p, new: %p",*p,s->objects );
|
||
|
|
||
|
s->free++;
|
||
|
|
||
|
if (s->free == sc->number) {
|
||
|
ddekit_slab_slab_remove(s);
|
||
|
ddekit_slab_slab_insert(&sc->empty, s);
|
||
|
}
|
||
|
|
||
|
if (s->free == 1) {
|
||
|
ddekit_slab_slab_remove(s);
|
||
|
ddekit_slab_slab_insert(&sc->partial, s);
|
||
|
}
|
||
|
|
||
|
ddekit_slab_unlock(sc);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_set_data *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void ddekit_slab_set_data(struct ddekit_slab * sc, void *data)
|
||
|
{
|
||
|
ddekit_slab_lock(sc);
|
||
|
sc->data = data;
|
||
|
ddekit_slab_unlock(sc);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_get_data *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void *ddekit_slab_get_data (struct ddekit_slab *sc)
|
||
|
{
|
||
|
void *ret;
|
||
|
ddekit_slab_lock(sc);
|
||
|
ret=sc->data;
|
||
|
ddekit_slab_unlock(sc);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_init *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous)
|
||
|
{
|
||
|
|
||
|
struct ddekit_slab * sc = 0;
|
||
|
|
||
|
sc = (struct ddekit_slab *)
|
||
|
ddekit_simple_malloc(sizeof(struct ddekit_slab));
|
||
|
|
||
|
sc->data = 0;
|
||
|
sc->contiguous = contiguous;
|
||
|
sc->size = size;
|
||
|
sc->number = SLAB_SIZE/(size+sizeof(void*));
|
||
|
|
||
|
if (sc->number == 0) {
|
||
|
ddekit_panic("objects too big!");
|
||
|
}
|
||
|
|
||
|
sc->empty.next = sc->empty.prev = &sc->empty;
|
||
|
sc->partial.next = sc->partial.prev = &sc->partial;
|
||
|
sc->full.next = sc->full.prev = &sc->full;
|
||
|
|
||
|
ddekit_lock_init(&sc->lock);
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("initialzed slab cache %p: size %x, number %d ",
|
||
|
sc, sc->size, sc->number);
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("partial %p next %p", &sc->partial, sc->partial.next);
|
||
|
return sc ;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_free_slab *
|
||
|
*****************************************************************************/
|
||
|
PRIVATE void ddekit_slab_free_slab(struct ddekit_slab_slab * sl, int cont)
|
||
|
{
|
||
|
|
||
|
struct ddekit_slab_slab *s,*t;
|
||
|
|
||
|
if (!sl) {
|
||
|
ddekit_panic("no slab to free!");
|
||
|
}
|
||
|
|
||
|
for ( s = sl->next; s != sl; )
|
||
|
{
|
||
|
DDEBUG_MSG_VERBOSE("cont: %d, %p, s->mem", cont, s->mem);
|
||
|
if(cont)
|
||
|
{
|
||
|
ddekit_large_free(s->mem);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ddekit_simple_free(s->mem);
|
||
|
}
|
||
|
t = s;
|
||
|
s = s->next;
|
||
|
ddekit_simple_free(t);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ddekit_slab_destroy *
|
||
|
*****************************************************************************/
|
||
|
PUBLIC void ddekit_slab_destroy(struct ddekit_slab *sc)
|
||
|
{
|
||
|
DDEBUG_MSG_VERBOSE("%p full", sc);
|
||
|
ddekit_slab_free_slab(&sc->full,sc->contiguous);
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("%p empty", sc);
|
||
|
ddekit_slab_free_slab(&sc->empty,sc->contiguous);
|
||
|
|
||
|
DDEBUG_MSG_VERBOSE("%p partial", sc);
|
||
|
ddekit_slab_free_slab(&sc->partial,sc->contiguous);
|
||
|
|
||
|
ddekit_lock_deinit(&sc->lock);
|
||
|
|
||
|
ddekit_simple_free(sc);
|
||
|
}
|