add list_mem function in slab allocator.
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1178 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
parent
14a840b911
commit
1a8721ecdf
112
src/slab.c
112
src/slab.c
|
@ -56,8 +56,14 @@
|
||||||
#include "kservice.h"
|
#include "kservice.h"
|
||||||
|
|
||||||
/* #define RT_SLAB_DEBUG */
|
/* #define RT_SLAB_DEBUG */
|
||||||
|
#define RT_MEM_STATS
|
||||||
|
|
||||||
#if defined (RT_USING_HEAP) && defined (RT_USING_SLAB)
|
#if defined (RT_USING_HEAP) && defined (RT_USING_SLAB)
|
||||||
|
/* some statistical variable */
|
||||||
|
#ifdef RT_MEM_STATS
|
||||||
|
static rt_size_t used_mem, max_mem;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef RT_USING_HOOK
|
#ifdef RT_USING_HOOK
|
||||||
static void (*rt_malloc_hook)(void *ptr, rt_size_t size);
|
static void (*rt_malloc_hook)(void *ptr, rt_size_t size);
|
||||||
static void (*rt_free_hook)(void *ptr);
|
static void (*rt_free_hook)(void *ptr);
|
||||||
|
@ -188,13 +194,6 @@ static int zone_size;
|
||||||
static int zone_limit;
|
static int zone_limit;
|
||||||
static int zone_page_cnt;
|
static int zone_page_cnt;
|
||||||
|
|
||||||
#ifdef RT_MEM_STATS
|
|
||||||
/* some statistical variable */
|
|
||||||
static rt_uint32_t rt_mem_allocated = 0;
|
|
||||||
static rt_uint32_t rt_mem_zone = 0;
|
|
||||||
static rt_uint32_t rt_mem_page_allocated = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Misc constants. Note that allocations that are exact multiples of
|
* Misc constants. Note that allocations that are exact multiples of
|
||||||
* RT_MM_PAGE_SIZE, or exceed the zone limit, fall through to the kmem module.
|
* RT_MM_PAGE_SIZE, or exceed the zone limit, fall through to the kmem module.
|
||||||
|
@ -227,6 +226,7 @@ struct rt_page_head
|
||||||
char dummy[RT_MM_PAGE_SIZE - (sizeof(struct rt_page_head*) + sizeof (rt_size_t))];
|
char dummy[RT_MM_PAGE_SIZE - (sizeof(struct rt_page_head*) + sizeof (rt_size_t))];
|
||||||
};
|
};
|
||||||
static struct rt_page_head *rt_page_list;
|
static struct rt_page_head *rt_page_list;
|
||||||
|
static struct rt_semaphore heap_sem;
|
||||||
|
|
||||||
void *rt_page_alloc(rt_size_t npages)
|
void *rt_page_alloc(rt_size_t npages)
|
||||||
{
|
{
|
||||||
|
@ -235,6 +235,8 @@ void *rt_page_alloc(rt_size_t npages)
|
||||||
|
|
||||||
if(npages == 0) return RT_NULL;
|
if(npages == 0) return RT_NULL;
|
||||||
|
|
||||||
|
/* lock heap */
|
||||||
|
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
|
||||||
for (prev = &rt_page_list; (b = *prev) != RT_NULL; prev = &(b->next))
|
for (prev = &rt_page_list; (b = *prev) != RT_NULL; prev = &(b->next))
|
||||||
{
|
{
|
||||||
if (b->page > npages)
|
if (b->page > npages)
|
||||||
|
@ -254,6 +256,8 @@ void *rt_page_alloc(rt_size_t npages)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* unlock heap */
|
||||||
|
rt_sem_release(&heap_sem);
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +273,8 @@ void rt_page_free(void *addr, rt_size_t npages)
|
||||||
|
|
||||||
n = (struct rt_page_head *)addr;
|
n = (struct rt_page_head *)addr;
|
||||||
|
|
||||||
|
/* lock heap */
|
||||||
|
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
|
||||||
for (prev = &rt_page_list; (b = *prev) != RT_NULL; prev = &(b->next))
|
for (prev = &rt_page_list; (b = *prev) != RT_NULL; prev = &(b->next))
|
||||||
{
|
{
|
||||||
RT_ASSERT(b->page > 0);
|
RT_ASSERT(b->page > 0);
|
||||||
|
@ -282,7 +288,7 @@ void rt_page_free(void *addr, rt_size_t npages)
|
||||||
b->next = b->next->next;
|
b->next = b->next->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b == n + npages)
|
if (b == n + npages)
|
||||||
|
@ -291,7 +297,7 @@ void rt_page_free(void *addr, rt_size_t npages)
|
||||||
n->next = b->next;
|
n->next = b->next;
|
||||||
*prev = n;
|
*prev = n;
|
||||||
|
|
||||||
return;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b > n + npages) break;
|
if (b > n + npages) break;
|
||||||
|
@ -300,6 +306,10 @@ void rt_page_free(void *addr, rt_size_t npages)
|
||||||
n->page = npages;
|
n->page = npages;
|
||||||
n->next = b;
|
n->next = b;
|
||||||
*prev = n;
|
*prev = n;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
/* unlock heap */
|
||||||
|
rt_sem_release(&heap_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -339,6 +349,9 @@ void rt_system_heap_init(void *begin_addr, void* end_addr)
|
||||||
limsize = heap_end - heap_start;
|
limsize = heap_end - heap_start;
|
||||||
npages = limsize / RT_MM_PAGE_SIZE;
|
npages = limsize / RT_MM_PAGE_SIZE;
|
||||||
|
|
||||||
|
/* initialize heap semaphore */
|
||||||
|
rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO);
|
||||||
|
|
||||||
#ifdef RT_SLAB_DEBUG
|
#ifdef RT_SLAB_DEBUG
|
||||||
rt_kprintf("heap[0x%x - 0x%x], size 0x%x, 0x%x pages\n", heap_start, heap_end, limsize, npages);
|
rt_kprintf("heap[0x%x - 0x%x], size 0x%x, 0x%x pages\n", heap_start, heap_end, limsize, npages);
|
||||||
#endif
|
#endif
|
||||||
|
@ -478,12 +491,19 @@ void *rt_malloc(rt_size_t size)
|
||||||
size >> RT_MM_PAGE_BITS,
|
size >> RT_MM_PAGE_BITS,
|
||||||
((rt_uint32_t)chunk - heap_start) >> RT_MM_PAGE_BITS);
|
((rt_uint32_t)chunk - heap_start) >> RT_MM_PAGE_BITS);
|
||||||
#endif
|
#endif
|
||||||
|
/* lock heap */
|
||||||
|
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
/* lock interrupt */
|
#ifdef RT_MEM_STATS
|
||||||
interrupt_level = rt_hw_interrupt_disable();
|
used_mem += size;
|
||||||
|
if (used_mem > max_mem) max_mem = used_mem;
|
||||||
|
#endif
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* lock heap */
|
||||||
|
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to allocate out of an existing zone. First try the free list,
|
* Attempt to allocate out of an existing zone. First try the free list,
|
||||||
* then allocate out of unallocated space. If we find a good zone move
|
* then allocate out of unallocated space. If we find a good zone move
|
||||||
|
@ -499,7 +519,6 @@ void *rt_malloc(rt_size_t size)
|
||||||
rt_kprintf("try to malloc 0x%x on zone: %d\n", size, zi);
|
rt_kprintf("try to malloc 0x%x on zone: %d\n", size, zi);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
interrupt_level = rt_hw_interrupt_disable();
|
|
||||||
if ((z = zone_array[zi]) != RT_NULL)
|
if ((z = zone_array[zi]) != RT_NULL)
|
||||||
{
|
{
|
||||||
RT_ASSERT(z->z_nfree > 0);
|
RT_ASSERT(z->z_nfree > 0);
|
||||||
|
@ -531,6 +550,11 @@ void *rt_malloc(rt_size_t size)
|
||||||
z->z_freechunk = z->z_freechunk->c_next;
|
z->z_freechunk = z->z_freechunk->c_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RT_MEM_STATS
|
||||||
|
used_mem += z->z_chunksize;
|
||||||
|
if (used_mem > max_mem) max_mem = used_mem;
|
||||||
|
#endif
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,10 +577,16 @@ void *rt_malloc(rt_size_t size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* unlock heap, since page allocator will think about lock */
|
||||||
|
rt_sem_release(&heap_sem);
|
||||||
|
|
||||||
/* allocate a zone from page */
|
/* allocate a zone from page */
|
||||||
z = rt_page_alloc(zone_size / RT_MM_PAGE_SIZE);
|
z = rt_page_alloc(zone_size / RT_MM_PAGE_SIZE);
|
||||||
if (z == RT_NULL) goto fail;
|
if (z == RT_NULL) goto fail;
|
||||||
|
|
||||||
|
/* lock heap */
|
||||||
|
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
#ifdef RT_SLAB_DEBUG
|
#ifdef RT_SLAB_DEBUG
|
||||||
rt_kprintf("alloc a new zone: 0x%x\n", (rt_uint32_t)z);
|
rt_kprintf("alloc a new zone: 0x%x\n", (rt_uint32_t)z);
|
||||||
#endif
|
#endif
|
||||||
|
@ -599,10 +629,15 @@ void *rt_malloc(rt_size_t size)
|
||||||
/* link to zone array */
|
/* link to zone array */
|
||||||
z->z_next = zone_array[zi];
|
z->z_next = zone_array[zi];
|
||||||
zone_array[zi] = z;
|
zone_array[zi] = z;
|
||||||
|
|
||||||
|
#ifdef RT_MEM_STATS
|
||||||
|
used_mem += z->z_chunksize;
|
||||||
|
if (used_mem > max_mem) max_mem = used_mem;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
rt_hw_interrupt_enable(interrupt_level);
|
rt_sem_release(&heap_sem);
|
||||||
|
|
||||||
#ifdef RT_USING_HOOK
|
#ifdef RT_USING_HOOK
|
||||||
if (rt_malloc_hook != RT_NULL) rt_malloc_hook((char*)chunk, size);
|
if (rt_malloc_hook != RT_NULL) rt_malloc_hook((char*)chunk, size);
|
||||||
|
@ -611,7 +646,7 @@ done:
|
||||||
return chunk;
|
return chunk;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
rt_hw_interrupt_enable(interrupt_level);
|
rt_sem_release(&heap_sem);
|
||||||
return RT_NULL;
|
return RT_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,7 +751,6 @@ void rt_free(void *ptr)
|
||||||
slab_zone *z;
|
slab_zone *z;
|
||||||
slab_chunk *chunk;
|
slab_chunk *chunk;
|
||||||
struct memusage *kup;
|
struct memusage *kup;
|
||||||
rt_base_t interrupt_level;
|
|
||||||
|
|
||||||
/* free a RT_NULL pointer */
|
/* free a RT_NULL pointer */
|
||||||
if (ptr == RT_NULL) return ;
|
if (ptr == RT_NULL) return ;
|
||||||
|
@ -735,11 +769,13 @@ void rt_free(void *ptr)
|
||||||
|
|
||||||
/* get memory usage */
|
/* get memory usage */
|
||||||
#ifdef RT_SLAB_DEBUG
|
#ifdef RT_SLAB_DEBUG
|
||||||
|
{
|
||||||
rt_uint32 addr = ((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
|
rt_uint32 addr = ((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
|
||||||
rt_kprintf("free a memory 0x%x and align to 0x%x, kup index %d\n",
|
rt_kprintf("free a memory 0x%x and align to 0x%x, kup index %d\n",
|
||||||
(rt_uint32_t)ptr,
|
(rt_uint32_t)ptr,
|
||||||
(rt_uint32_t)addr,
|
(rt_uint32_t)addr,
|
||||||
((rt_uint32_t)(addr) - heap_start) >> RT_MM_PAGE_BITS);
|
((rt_uint32_t)(addr) - heap_start) >> RT_MM_PAGE_BITS);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
kup = btokup((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
|
kup = btokup((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
|
||||||
|
@ -748,11 +784,16 @@ void rt_free(void *ptr)
|
||||||
{
|
{
|
||||||
rt_uint32_t size;
|
rt_uint32_t size;
|
||||||
|
|
||||||
|
/* lock heap */
|
||||||
|
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
|
||||||
/* clear page counter */
|
/* clear page counter */
|
||||||
interrupt_level = rt_hw_interrupt_disable();
|
|
||||||
size = kup->size;
|
size = kup->size;
|
||||||
kup->size = 0;
|
kup->size = 0;
|
||||||
rt_hw_interrupt_enable(interrupt_level);
|
|
||||||
|
#ifdef RT_MEM_STATS
|
||||||
|
used_mem -= size;
|
||||||
|
#endif
|
||||||
|
rt_sem_release(&heap_sem);
|
||||||
|
|
||||||
#ifdef RT_SLAB_DEBUG
|
#ifdef RT_SLAB_DEBUG
|
||||||
rt_kprintf("free large memory block 0x%x, page count %d\n", (rt_uint32_t)ptr, size);
|
rt_kprintf("free large memory block 0x%x, page count %d\n", (rt_uint32_t)ptr, size);
|
||||||
|
@ -763,15 +804,21 @@ void rt_free(void *ptr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* lock heap */
|
||||||
|
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
/* zone case. get out zone. */
|
/* zone case. get out zone. */
|
||||||
z = (slab_zone*)(((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK) - kup->size * RT_MM_PAGE_SIZE);
|
z = (slab_zone*)(((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK) - kup->size * RT_MM_PAGE_SIZE);
|
||||||
RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
|
RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
|
||||||
|
|
||||||
interrupt_level = rt_hw_interrupt_disable();
|
|
||||||
chunk = (slab_chunk*)ptr;
|
chunk = (slab_chunk*)ptr;
|
||||||
chunk->c_next = z->z_freechunk;
|
chunk->c_next = z->z_freechunk;
|
||||||
z->z_freechunk = chunk;
|
z->z_freechunk = chunk;
|
||||||
|
|
||||||
|
#ifdef RT_MEM_STATS
|
||||||
|
used_mem -= z->z_chunksize;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bump the number of free chunks. If it becomes non-zero the zone
|
* Bump the number of free chunks. If it becomes non-zero the zone
|
||||||
* must be added back onto the appropriate list.
|
* must be added back onto the appropriate list.
|
||||||
|
@ -827,13 +874,40 @@ void rt_free(void *ptr)
|
||||||
kup ++;
|
kup ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* unlock heap */
|
||||||
|
rt_sem_release(&heap_sem);
|
||||||
|
|
||||||
/* release pages */
|
/* release pages */
|
||||||
rt_page_free(z, zone_size);
|
rt_page_free(z, zone_size);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rt_hw_interrupt_enable(interrupt_level);
|
/* unlock heap */
|
||||||
|
rt_sem_release(&heap_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RT_MEM_STATS
|
||||||
|
void rt_memory_info(rt_uint32_t *total,
|
||||||
|
rt_uint32_t *used,
|
||||||
|
rt_uint32_t *max_used)
|
||||||
|
{
|
||||||
|
if (total != RT_NULL) *total = heap_end - heap_start;
|
||||||
|
if (used != RT_NULL) *used = used_mem;
|
||||||
|
if (max_used != RT_NULL) *max_used = max_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RT_USING_FINSH
|
||||||
|
#include <finsh.h>
|
||||||
|
void list_mem()
|
||||||
|
{
|
||||||
|
rt_kprintf("total memory: %d\n", heap_end - heap_start);
|
||||||
|
rt_kprintf("used memory : %d\n", used_mem);
|
||||||
|
rt_kprintf("maximum allocated memory: %d\n", max_mem);
|
||||||
|
}
|
||||||
|
FINSH_FUNCTION_EXPORT(list_mem, list memory usage information)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue