mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 14:47:09 +00:00
alloc quar work.
git-svn-id: file:///svn/unbound/trunk@164 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
1a38497dbe
commit
696d38318c
@ -1,5 +1,6 @@
|
||||
6 March 2007: Wouter
|
||||
- Testbed works with threading (different machines, different options).
|
||||
- alloc work, does the special type.
|
||||
|
||||
2 March 2007: Wouter
|
||||
- do not compile fork funcs unless needed. Otherwise will give
|
||||
|
138
util/alloc.c
138
util/alloc.c
@ -42,3 +42,141 @@
|
||||
#include "config.h"
|
||||
#include "util/alloc.h"
|
||||
|
||||
/** prealloc some entries in the cache. To minimize contention.
|
||||
* @param alloc: the structure to fill up.
|
||||
*/
|
||||
static void
|
||||
prealloc(struct alloc_cache* alloc)
|
||||
{
|
||||
alloc_special_t* p;
|
||||
int i;
|
||||
for(i=0; i<ALLOC_SPECIAL_MAX; i++) {
|
||||
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t))))
|
||||
fatal_exit("prealloc: out of memory");
|
||||
alloc_special_next(p) = alloc->quar;
|
||||
alloc->quar = p;
|
||||
alloc->num_quar++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
alloc_init(struct alloc_cache* alloc, struct alloc_cache* super)
|
||||
{
|
||||
memset(alloc, 0, sizeof(*alloc));
|
||||
alloc->super = super;
|
||||
lock_quick_init(&alloc->lock);
|
||||
}
|
||||
|
||||
void
|
||||
alloc_delete(struct alloc_cache* alloc)
|
||||
{
|
||||
alloc_special_t* p, *np;
|
||||
if(!alloc)
|
||||
return;
|
||||
lock_quick_destroy(&alloc->lock);
|
||||
if(alloc->super && alloc->quar) {
|
||||
/* push entire list into super */
|
||||
p = alloc->quar;
|
||||
while(alloc_special_next(p)) /* find last */
|
||||
p = alloc_special_next(p);
|
||||
lock_quick_lock(&alloc->super->lock);
|
||||
alloc_special_next(p) = alloc->super->quar;
|
||||
alloc->super->quar = alloc->quar;
|
||||
alloc->super->num_quar += alloc->num_quar;
|
||||
lock_quick_unlock(&alloc->super->lock);
|
||||
} else {
|
||||
/* free */
|
||||
p = alloc->quar;
|
||||
while(p) {
|
||||
np = alloc_special_next(p);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
alloc->quar = 0;
|
||||
alloc->num_quar = 0;
|
||||
}
|
||||
|
||||
alloc_special_t*
|
||||
alloc_special_obtain(struct alloc_cache* alloc)
|
||||
{
|
||||
alloc_special_t* p;
|
||||
log_assert(alloc);
|
||||
/* see if in local cache */
|
||||
if(alloc->quar) {
|
||||
p = alloc->quar;
|
||||
alloc->quar = alloc_special_next(p);
|
||||
alloc->num_quar--;
|
||||
alloc->special_allocated++;
|
||||
return p;
|
||||
}
|
||||
/* see if in global cache */
|
||||
if(alloc->super) {
|
||||
lock_quick_lock(&alloc->super->lock);
|
||||
if((p = alloc->super->quar)) {
|
||||
alloc->super->quar = alloc_special_next(p);
|
||||
alloc->super->num_quar--;
|
||||
}
|
||||
lock_quick_unlock(&alloc->super->lock);
|
||||
if(p) {
|
||||
alloc->special_allocated++;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
/* allocate new */
|
||||
prealloc(alloc);
|
||||
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t))))
|
||||
fatal_exit("alloc_special_obtain: out of memory");
|
||||
alloc->special_allocated++;
|
||||
return p;
|
||||
}
|
||||
|
||||
/** push mem and some more items to the super */
|
||||
static void
|
||||
pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem)
|
||||
{
|
||||
int i;
|
||||
alloc_special_t *p = alloc->quar;
|
||||
log_assert(p);
|
||||
log_assert(alloc && alloc->super &&
|
||||
alloc->num_quar >= ALLOC_SPECIAL_MAX);
|
||||
/* push ALLOC_SPECIAL_MAX/2 after mem */
|
||||
alloc_special_next(mem) = alloc->quar;
|
||||
for(i=1; i<ALLOC_SPECIAL_MAX/2; i++) {
|
||||
p = alloc_special_next(p);
|
||||
}
|
||||
alloc->quar = alloc_special_next(p);
|
||||
alloc->num_quar -= ALLOC_SPECIAL_MAX/2;
|
||||
|
||||
lock_quick_lock(&alloc->super->lock);
|
||||
alloc_special_next(p) = alloc->super->quar;
|
||||
alloc->super->quar = mem;
|
||||
alloc->super->num_quar += ALLOC_SPECIAL_MAX/2 + 1;
|
||||
lock_quick_unlock(&alloc->super->lock);
|
||||
}
|
||||
|
||||
void
|
||||
alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem)
|
||||
{
|
||||
log_assert(alloc);
|
||||
if(!mem)
|
||||
return;
|
||||
if(alloc->super && alloc->num_quar >= ALLOC_SPECIAL_MAX) {
|
||||
/* push it to the super structure */
|
||||
alloc->special_allocated --;
|
||||
pushintosuper(alloc, mem);
|
||||
return;
|
||||
}
|
||||
|
||||
alloc_special_next(mem) = alloc->quar;
|
||||
alloc->quar = mem;
|
||||
alloc->num_quar++;
|
||||
alloc->special_allocated--;
|
||||
}
|
||||
|
||||
void
|
||||
alloc_stats(struct alloc_cache* alloc)
|
||||
{
|
||||
log_info("%salloc: %d allocated, %d in cache.", alloc->super?"":"sup",
|
||||
(int)alloc->special_allocated, (int)alloc->num_quar);
|
||||
}
|
||||
|
95
util/alloc.h
95
util/alloc.h
@ -42,10 +42,6 @@
|
||||
* o Avoid locking costs of getting global lock to call malloc().
|
||||
* o The packed rrset type needs to be kept on special freelists,
|
||||
* so that they are reused for other packet rrset allocations.
|
||||
* o This service is not there to improve speed of malloc.
|
||||
* Some caching is performed to help avoid locking costs.
|
||||
* o This service does not prevent fragmentation.
|
||||
* The caching will help somewhat for this.
|
||||
*
|
||||
* Design choices:
|
||||
* o The global malloc/free is used to handle fragmentation, etc.
|
||||
@ -61,120 +57,67 @@
|
||||
|
||||
#include "util/locks.h"
|
||||
|
||||
/** all allocations are in multiples of this size */
|
||||
#define ALLOC_ALIGN 32 /* bytes */
|
||||
|
||||
/**
|
||||
* This size and smaller is kept in cached lists by size.
|
||||
* Must be a multiple of ALLOC_ALIGN.
|
||||
*/
|
||||
#define ALLOC_LARGESIZE 1024 /* bytes */
|
||||
|
||||
/** number of bins */
|
||||
#define ALLOC_BINS (ALLOC_LARGESIZE / ALLOC_ALIGN)
|
||||
|
||||
/** The special type, packed rrset. Not allowed to be used for other memory */
|
||||
typedef uint64_t alloc_special_t;
|
||||
/** clean the special type. Pass pointer. */
|
||||
#define alloc_special_clean(x) memset(x, 0, sizeof(alloc_special_t))
|
||||
/** access next pointer. (in available spot). Pass pointer. */
|
||||
#define alloc_special_next(x) ((alloc_special_t*)(*(x)))
|
||||
#define alloc_special_next(x) (*((alloc_special_t**)(x)))
|
||||
|
||||
/** The number of cached items. */
|
||||
#define ALLOC_CACHENUM 10 /* memory blocks */
|
||||
/** how many blocks to cache locally. */
|
||||
#define ALLOC_SPECIAL_MAX 10
|
||||
|
||||
/** Preallocated per thread. This number for every size. */
|
||||
#define ALLOC_PREALLOC 32 /* memory blocks */
|
||||
|
||||
/** shorthand */
|
||||
typedef struct alloc_cache alloc_t;
|
||||
/**
|
||||
* Structure that provides caching based on size. Used one per thread.
|
||||
* Structure that provides allocation. Use one per thread.
|
||||
* The one on top has a NULL super pointer.
|
||||
*/
|
||||
struct alloc_cache {
|
||||
/** lock, only used for the super. */
|
||||
lock_quick_t lock;
|
||||
/** global allocator above this one. NULL for none (malloc/free) */
|
||||
struct alloc_super* super;
|
||||
/** singly linked lists per size: [0]32, [1]64, ... [n-1]LARGESIZE */
|
||||
void* bins[ALLOC_BINS];
|
||||
/** the number of items per bin. */
|
||||
size_t nums[ALLOC_BINS];
|
||||
struct alloc_cache* super;
|
||||
/** singly linked lists of special type. These are free for use. */
|
||||
alloc_special_t* quar;
|
||||
/** number of items in quarantine. */
|
||||
size_t num_quar;
|
||||
|
||||
/* some statistics */
|
||||
/** amount allocated. */
|
||||
size_t bytes_allocated;
|
||||
/** number of items allocated. */
|
||||
size_t items_allocated;
|
||||
/** wasted space due to assigning oversized aligned blocks. */
|
||||
size_t internal_frag;
|
||||
/** amount in cache. */
|
||||
size_t bytes_in_bins;
|
||||
/** number of special type allocated */
|
||||
size_t special_allocated;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure with lock to provide global cache of special items and allocs.
|
||||
*/
|
||||
struct alloc_super {
|
||||
/** lock for single access. */
|
||||
lock_quick_t lock;
|
||||
/** singly linked lists of special type. These are free for use. */
|
||||
alloc_special_t* quar;
|
||||
/** number of items in quarantine. */
|
||||
size_t num_quar;
|
||||
};
|
||||
|
||||
/**
|
||||
* Init super alloc. (zeroes the struct, inits the lock).
|
||||
* @param super: to init.
|
||||
*/
|
||||
void asuper_init(struct alloc_super* super);
|
||||
|
||||
/**
|
||||
* Init alloc (zeroes the struct).
|
||||
* @param alloc: this parameter is allocated by the caller.
|
||||
* @param super: super to use (init that before with super_init).
|
||||
*/
|
||||
void alloc_init(alloc_t* alloc, struct alloc_super* super);
|
||||
void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super);
|
||||
|
||||
/**
|
||||
* Free the alloc. Pushes all the cached items into the super structure.
|
||||
* Or deletes them if super is NULL.
|
||||
* Does not free the alloc struct itself.
|
||||
* @param alloc: is almost zeroed on exit (except some stats).
|
||||
*/
|
||||
void alloc_delete(alloc_t* alloc);
|
||||
|
||||
/**
|
||||
* Allocate memory
|
||||
* @param alloc: where to alloc it.
|
||||
* @param size: how much.
|
||||
* @return: memory block. Will not return NULL (instead fatal_exit).
|
||||
*/
|
||||
void* alloc_alloc(alloc_t* alloc, size_t size);
|
||||
|
||||
/**
|
||||
* Free memory.
|
||||
* @param alloc: where to alloc it.
|
||||
* @param mem: block to free.
|
||||
*/
|
||||
void alloc_free(alloc_t* alloc, void* mem);
|
||||
void alloc_delete(struct alloc_cache* alloc);
|
||||
|
||||
/**
|
||||
* Get a new special_t element.
|
||||
* @param alloc: where to alloc it.
|
||||
* @return: memory block. Will not return NULL (instead fatal_exit).
|
||||
*/
|
||||
alloc_special_t* alloc_special_alloc(alloc_t* alloc);
|
||||
alloc_special_t* alloc_special_obtain(struct alloc_cache* alloc);
|
||||
|
||||
/**
|
||||
* Return special_t back to pool.
|
||||
* @param alloc: where to alloc it.
|
||||
* @param mem: block to free.
|
||||
*/
|
||||
void alloc_special_free(alloc_t* alloc, alloc_special_t* mem);
|
||||
void alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem);
|
||||
|
||||
/**
|
||||
* Print debug information (statistics).
|
||||
* @param alloc: on what alloc.
|
||||
*/
|
||||
void alloc_stats(struct alloc_cache* alloc);
|
||||
|
||||
#endif /* UTIL_ALLOC_H */
|
||||
|
Loading…
Reference in New Issue
Block a user