diff options
Diffstat (limited to 'src/framework/mem/dmm_segment.c')
-rw-r--r-- | src/framework/mem/dmm_segment.c | 145 |
1 files changed, 78 insertions, 67 deletions
diff --git a/src/framework/mem/dmm_segment.c b/src/framework/mem/dmm_segment.c index 6358506..7600d3e 100644 --- a/src/framework/mem/dmm_segment.c +++ b/src/framework/mem/dmm_segment.c @@ -16,11 +16,14 @@ #include <stdio.h> #include <string.h> +#include <limits.h> +#include "dmm_common.h" #include "dmm_rwlock.h" #include "dmm_segment.h" #include "nstack_log.h" -#define SECTION_SIZE 64 /* cache line size */ +#define BLOCK_SIZE 64 /* cache line size */ +#define BLOCK_MASK (BLOCK_SIZE - 1) #define FIRST_NAME "FIRST SECTION FOR SEGMENT" #define LAST_NAME "LAST SECTION FOR FREE HEAD" @@ -28,6 +31,11 @@ #define MEM_ERR(fmt, ...) \ NS_LOGPID(LOGFW, "DMM-MEM", NSLOG_ERR, fmt, ##__VA_ARGS__) +typedef struct +{ + char _dummy_block_size[BLOCK_SIZE]; +} _dmm_packed __BLOCK; + /* init create: \--total number @@ -53,13 +61,15 @@ typedef struct dmm_section int prev_rel; int used_num; int free_num; - int __flags; /* reserved */ + int flags; /* reserved */ size_t req_size; /* in bytes */ int less_rel; /* for free list */ int more_rel; /* for free list */ char name[DMM_MEM_NAME_SIZE]; -} __attribute__ ((__aligned__ (SECTION_SIZE))) section_t; -SIZE_OF_TYPE_EQUAL_TO (section_t, SECTION_SIZE); +} _dmm_cache_aligned section_t; + +/* dmm_section struct hold blocks number */ +#define SECTION_HOLD ((sizeof(struct dmm_section) + (BLOCK_SIZE - 1)) / BLOCK_SIZE) struct dmm_segment { @@ -80,23 +90,22 @@ CALC_NUM (size_t size) { if (size) { - const size_t MASK = SECTION_SIZE - 1; - return (size + MASK) / SECTION_SIZE + 1; + return SECTION_HOLD + (size + BLOCK_MASK) / BLOCK_SIZE; } - return 2; /* if size is 0, then alloc 1 block */ + return SECTION_HOLD + 1; /* if size is 0, then alloc 1 block */ } inline static int SEC_REL (const section_t * base, const section_t * sec) { - return sec - base; + return (__BLOCK *) sec - (__BLOCK *) base; } section_t * REL_SEC (section_t * base, int rel) { - return base + rel; + return (section_t *) ((__BLOCK *) base + rel); } inline static int @@ -108,25 +117,25 @@ SEC_INDEX (struct dmm_segment *seg, section_t * sec) inline static section_t * LESS_SEC (section_t * sec) { - return sec + sec->less_rel; + return REL_SEC (sec, sec->less_rel); } inline static section_t * MORE_SEC (section_t * sec) { - return sec + sec->more_rel; + return REL_SEC (sec, sec->more_rel); } inline static section_t * PREV_SEC (section_t * sec) { - return sec + sec->prev_rel; + return REL_SEC (sec, sec->prev_rel); } inline static section_t * NEXT_SEC (section_t * sec) { - return sec + (sec->free_num + sec->used_num); + return REL_SEC (sec, sec->free_num + sec->used_num); } inline static int @@ -136,7 +145,7 @@ CHECK_ADDR (struct dmm_segment *seg, void *mem) return -1; if (mem > (void *) seg->last) return -1; - if ((long) mem & (SECTION_SIZE - 1)) + if ((long) mem & BLOCK_MASK) return -1; return 0; @@ -185,7 +194,7 @@ mem_alloc (struct dmm_segment *seg, size_t size) } while (num > pos->free_num); - /* allocate pos pos section tail */ + /* allocate from pos section's tail */ /* change next section's prev possion */ next = NEXT_SEC (pos); @@ -201,13 +210,13 @@ mem_alloc (struct dmm_segment *seg, size_t size) sec->more_rel = 0; sec->name[0] = 0; - /* adjust pos */ + /* adjust pos section */ pos->free_num -= num; less = LESS_SEC (pos); more = MORE_SEC (pos); - /* remove pos free list */ + /* remove from free list */ less->more_rel = SEC_REL (less, more); more->less_rel = SEC_REL (more, less); pos->more_rel = 0; @@ -294,23 +303,35 @@ mem_free (struct dmm_segment *seg, section_t * sec) } void +dmm_seg_lock (struct dmm_segment *seg) +{ + dmm_write_lock (&seg->lock); +} + +void +dmm_seg_unlock (struct dmm_segment *seg) +{ + dmm_write_unlock (&seg->lock); +} + +void dmm_seg_dump (struct dmm_segment *seg) { section_t *sec; dmm_read_lock (&seg->lock); - (void) printf ("---- segment:%p base:%p size:%lu --------------\n" - " first[%d]:%p last[%d]:%p total_num:%d used_num:%d\n" - " sec_num:%d used_size:%lu use%%:%lu%% free%%:%lu%%\n", - seg, seg->base, seg->size, - SEC_INDEX (seg, seg->first), seg->first, - SEC_INDEX (seg, seg->last), seg->last, - seg->total_num, seg->used_num, - seg->sec_num, seg->used_size, - seg->used_size * 100 / seg->size, - (seg->total_num - - seg->used_num) * SECTION_SIZE * 100 / seg->size); + (void) + printf + ("---- segment:%p base:%p size:%lu ---- BS:%u SS:%lu SH:%lu ----\n" + " first[%d]:%p last[%d]:%p total_num:%d used_num:%d\n" + " sec_num:%d used_size:%lu use%%:%lu%% free%%:%ld%%\n", seg, + seg->base, seg->size, BLOCK_SIZE, sizeof (struct dmm_section), + SECTION_HOLD, SEC_INDEX (seg, seg->first), seg->first, SEC_INDEX (seg, + seg->last), + seg->last, seg->total_num, seg->used_num, seg->sec_num, seg->used_size, + seg->used_size * 100 / seg->size, + (seg->total_num - seg->used_num) * (BLOCK_SIZE * 100) / seg->size); (void) printf ("----------------------------------------\n" "%18s %9s %9s %9s %9s %10s %9s %9s %s\n", @@ -345,16 +366,15 @@ dmm_seg_dump (struct dmm_segment *seg) inline static int align_section (void *base, size_t size, section_t ** first) { - const long MASK = ((long) SECTION_SIZE - 1); const int SEG_NUM = CALC_NUM (sizeof (struct dmm_segment)); const long align = (long) base; - const long addr = (align + MASK) & (~MASK); - const size_t total = (size - (addr - align)) / SECTION_SIZE; + const long addr = (align + BLOCK_MASK) & (~BLOCK_MASK); + const size_t total = (size - (addr - align)) / BLOCK_SIZE; - if (total > 0x7fffFFFF) + if (total > INT_MAX) return -1; - if (total < SEG_NUM + 1) /* first+segment + last */ + if (total < SEG_NUM + SECTION_HOLD) /* first+segment + last */ return -1; *first = (section_t *) addr; @@ -364,21 +384,21 @@ align_section (void *base, size_t size, section_t ** first) struct dmm_segment * dmm_seg_create (void *base, size_t size) { - const int SEG_NUM = CALC_NUM (sizeof (struct dmm_segment)); section_t *first, *last; struct dmm_segment *seg; - int total = align_section (base, size, &first); + const int total = align_section (base, size, &first); + const int SEG_NUM = CALC_NUM (sizeof (struct dmm_segment)); if (total <= 0) return NULL; - last = first + (total - 1); + last = first + (total - SECTION_HOLD); /* first section */ first->prev_rel = 0; first->used_num = SEG_NUM; first->req_size = sizeof (struct dmm_segment); - first->free_num = total - (SEG_NUM + 1); + first->free_num = total - (SEG_NUM + SECTION_HOLD); first->less_rel = SEC_REL (first, last); first->more_rel = SEC_REL (first, last); first->name[0] = 0; @@ -402,9 +422,9 @@ dmm_seg_create (void *base, size_t size) seg->first = first; seg->last = last; seg->total_num = total; - seg->sec_num = 2; + seg->sec_num = 2; /* first and tail */ seg->used_size = sizeof (struct dmm_segment); - seg->used_num = first->used_num; + seg->used_num = first->used_num + SECTION_HOLD; return seg; } @@ -414,12 +434,12 @@ dmm_seg_attach (void *base, size_t size) { section_t *first, *last; struct dmm_segment *seg; - int total = align_section (base, size, &first); + const int total = align_section (base, size, &first); if (total <= 0) return NULL; - last = first + (total - 1); + last = first + (total - SECTION_HOLD); seg = (struct dmm_segment *) (first + 1); if (seg->base != base) @@ -451,9 +471,9 @@ dmm_mem_alloc (struct dmm_segment *seg, size_t size) { section_t *sec; - dmm_write_lock (&seg->lock); + dmm_seg_lock (seg); sec = mem_alloc (seg, size); - dmm_write_unlock (&seg->lock); + dmm_seg_unlock (seg); return sec ? sec + 1 : NULL; } @@ -467,9 +487,9 @@ dmm_mem_free (struct dmm_segment *seg, void *mem) return -1; } - dmm_write_lock (&seg->lock); + dmm_seg_lock (seg); mem_free (seg, ((section_t *) mem) - 1); - dmm_write_unlock (&seg->lock); + dmm_seg_unlock (seg); return 0; } @@ -499,45 +519,36 @@ dmm_mem_map (struct dmm_segment *seg, size_t size, if (!name || !name[0] || strlen (name) >= DMM_MEM_NAME_SIZE) return NULL; - dmm_write_lock (&seg->lock); - sec = mem_lookup (seg, name); if (sec) { MEM_ERR ("Map '%s' exist", name); mem = NULL; } - else if (!(sec = mem_alloc (seg, size))) + else if (NULL != (sec = mem_alloc (seg, size))) { - MEM_ERR ("alloc '%s' failed for size %lu", name, size); - mem = NULL; + (void) strncpy (sec->name, name, sizeof (sec->name)); + mem = sec + 1; } else { - (void) strncpy (sec->name, name, sizeof (sec->name)); - mem = sec + 1; + MEM_ERR ("alloc '%s' failed for size %lu", name, size); + mem = NULL; } - dmm_write_unlock (&seg->lock); - return mem; } int -dmm_mem_unmap (struct dmm_segment *seg, const char name[DMM_MEM_NAME_SIZE]) +dmm_mem_unmap (struct dmm_segment *seg, void *mem) { - section_t *sec; - - if (!name || !name[0]) - return -1; - - dmm_write_lock (&seg->lock); - - sec = mem_lookup (seg, name); - if (sec) - mem_free (seg, sec); + if (CHECK_ADDR (seg, mem)) + { + MEM_ERR ("Invalid address:%p", mem); + return -1; + } - dmm_write_unlock (&seg->lock); + mem_free (seg, ((section_t *) mem) - 1); - return sec != NULL ? 0 : -1; + return 0; } |