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:
bernard.xiong@gmail.com 2010-12-05 11:59:54 +00:00
parent 14a840b911
commit 1a8721ecdf
1 changed files with 98 additions and 24 deletions

View File

@ -56,8 +56,14 @@
#include "kservice.h"
/* #define RT_SLAB_DEBUG */
#define RT_MEM_STATS
#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
static void (*rt_malloc_hook)(void *ptr, rt_size_t size);
static void (*rt_free_hook)(void *ptr);
@ -188,13 +194,6 @@ static int zone_size;
static int zone_limit;
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
* 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))];
};
static struct rt_page_head *rt_page_list;
static struct rt_semaphore heap_sem;
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;
/* lock heap */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
for (prev = &rt_page_list; (b = *prev) != RT_NULL; prev = &(b->next))
{
if (b->page > npages)
@ -254,6 +256,8 @@ void *rt_page_alloc(rt_size_t npages)
break;
}
}
/* unlock heap */
rt_sem_release(&heap_sem);
return b;
}
@ -269,6 +273,8 @@ void rt_page_free(void *addr, rt_size_t npages)
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))
{
RT_ASSERT(b->page > 0);
@ -282,7 +288,7 @@ void rt_page_free(void *addr, rt_size_t npages)
b->next = b->next->next;
}
return;
goto _return;
}
if (b == n + npages)
@ -291,7 +297,7 @@ void rt_page_free(void *addr, rt_size_t npages)
n->next = b->next;
*prev = n;
return;
goto _return;
}
if (b > n + npages) break;
@ -300,6 +306,10 @@ void rt_page_free(void *addr, rt_size_t npages)
n->page = npages;
n->next = b;
*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;
npages = limsize / RT_MM_PAGE_SIZE;
/* initialize heap semaphore */
rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO);
#ifdef RT_SLAB_DEBUG
rt_kprintf("heap[0x%x - 0x%x], size 0x%x, 0x%x pages\n", heap_start, heap_end, limsize, npages);
#endif
@ -478,12 +491,19 @@ void *rt_malloc(rt_size_t size)
size >> RT_MM_PAGE_BITS,
((rt_uint32_t)chunk - heap_start) >> RT_MM_PAGE_BITS);
#endif
/* lock heap */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
/* lock interrupt */
interrupt_level = rt_hw_interrupt_disable();
#ifdef RT_MEM_STATS
used_mem += size;
if (used_mem > max_mem) max_mem = used_mem;
#endif
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,
* 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);
#endif
interrupt_level = rt_hw_interrupt_disable();
if ((z = zone_array[zi]) != RT_NULL)
{
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;
}
#ifdef RT_MEM_STATS
used_mem += z->z_chunksize;
if (used_mem > max_mem) max_mem = used_mem;
#endif
goto done;
}
@ -553,10 +577,16 @@ void *rt_malloc(rt_size_t size)
}
else
{
/* unlock heap, since page allocator will think about lock */
rt_sem_release(&heap_sem);
/* allocate a zone from page */
z = rt_page_alloc(zone_size / RT_MM_PAGE_SIZE);
if (z == RT_NULL) goto fail;
/* lock heap */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
#ifdef RT_SLAB_DEBUG
rt_kprintf("alloc a new zone: 0x%x\n", (rt_uint32_t)z);
#endif
@ -599,10 +629,15 @@ void *rt_malloc(rt_size_t size)
/* link to zone array */
z->z_next = zone_array[zi];
zone_array[zi] = z;
#ifdef RT_MEM_STATS
used_mem += z->z_chunksize;
if (used_mem > max_mem) max_mem = used_mem;
#endif
}
done:
rt_hw_interrupt_enable(interrupt_level);
rt_sem_release(&heap_sem);
#ifdef RT_USING_HOOK
if (rt_malloc_hook != RT_NULL) rt_malloc_hook((char*)chunk, size);
@ -611,7 +646,7 @@ done:
return chunk;
fail:
rt_hw_interrupt_enable(interrupt_level);
rt_sem_release(&heap_sem);
return RT_NULL;
}
@ -716,7 +751,6 @@ void rt_free(void *ptr)
slab_zone *z;
slab_chunk *chunk;
struct memusage *kup;
rt_base_t interrupt_level;
/* free a RT_NULL pointer */
if (ptr == RT_NULL) return ;
@ -735,11 +769,13 @@ void rt_free(void *ptr)
/* get memory usage */
#ifdef RT_SLAB_DEBUG
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_uint32_t)ptr,
(rt_uint32_t)addr,
((rt_uint32_t)(addr) - heap_start) >> RT_MM_PAGE_BITS);
{
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_uint32_t)ptr,
(rt_uint32_t)addr,
((rt_uint32_t)(addr) - heap_start) >> RT_MM_PAGE_BITS);
}
#endif
kup = btokup((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
@ -748,11 +784,16 @@ void rt_free(void *ptr)
{
rt_uint32_t size;
/* lock heap */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
/* clear page counter */
interrupt_level = rt_hw_interrupt_disable();
size = kup->size;
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
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;
}
/* lock heap */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
/* zone case. get out zone. */
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);
interrupt_level = rt_hw_interrupt_disable();
chunk = (slab_chunk*)ptr;
chunk->c_next = z->z_freechunk;
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
* must be added back onto the appropriate list.
@ -827,13 +874,40 @@ void rt_free(void *ptr)
kup ++;
}
/* unlock heap */
rt_sem_release(&heap_sem);
/* release pages */
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