195 lines
4.3 KiB
C
195 lines
4.3 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <math.h>
|
|
#include <sys/mman.h>
|
|
|
|
/* unit test */
|
|
#include "minunit.h"
|
|
/* kernel/mm/xxx */
|
|
#include "buddy.h"
|
|
#include "slab.h"
|
|
|
|
#define ROUND 1000
|
|
#define NPAGES (128 * 1000)
|
|
|
|
#define START_VADDR phys_to_virt(24*1024*1024)
|
|
|
|
void printk(const char *fmt, ...)
|
|
{
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
|
vprintf(fmt, va);
|
|
va_end(va);
|
|
}
|
|
|
|
struct phys_mem_pool global_mem;
|
|
|
|
/* test buddy allocator */
|
|
|
|
static unsigned long buddy_num_free_page(struct phys_mem_pool *zone)
|
|
{
|
|
unsigned long i, ret;
|
|
|
|
ret = 0;
|
|
for (i = 0; i < BUDDY_MAX_ORDER; ++i) {
|
|
ret += zone->free_lists[i].nr_free;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void valid_page_idx(struct phys_mem_pool *zone, long idx)
|
|
{
|
|
mu_assert((idx < zone->pool_phys_page_num)
|
|
&& (idx >= 0), "invalid page idx");
|
|
}
|
|
|
|
static unsigned long get_page_idx(struct phys_mem_pool *zone, struct page *page)
|
|
{
|
|
long idx;
|
|
|
|
idx = page - zone->page_metadata;
|
|
valid_page_idx(zone, idx);
|
|
|
|
return idx;
|
|
}
|
|
|
|
static void test_alloc(struct phys_mem_pool *zone, long n, long order)
|
|
{
|
|
long i;
|
|
struct page *page;
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
page = buddy_get_pages(zone, order);
|
|
mu_check(page != NULL);
|
|
get_page_idx(zone, page);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void test_buddy(void)
|
|
{
|
|
void *start;
|
|
unsigned long npages;
|
|
unsigned long size;
|
|
unsigned long start_addr;
|
|
|
|
long nget;
|
|
long ncheck;
|
|
|
|
struct page *page;
|
|
long i;
|
|
|
|
/* free_mem_size: npages * 0x1000 */
|
|
npages = 128 * 0x1000;
|
|
/* PAGE_SIZE + page metadata size */
|
|
size = npages * (sizeof(struct page));
|
|
start = mmap((void *)0x50000000000, size, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
size = npages * (0x1000);
|
|
start_addr =
|
|
(unsigned long)mmap((void *)0x60000000000, size,
|
|
PROT_READ | PROT_WRITE,
|
|
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
|
|
/* skip the metadata area */
|
|
init_buddy(&global_mem, start, start_addr, npages);
|
|
|
|
/* check the init state */
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = npages / powl(2, BUDDY_MAX_ORDER - 1);
|
|
//printf("ncheck is %ld\n", ncheck);
|
|
mu_check(nget == ncheck);
|
|
|
|
/* alloc single page for $npages times */
|
|
test_alloc(&global_mem, npages, 0);
|
|
|
|
/* should have 0 free pages */
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = 0;
|
|
mu_check(nget == ncheck);
|
|
|
|
/* free all pages */
|
|
for (i = 0; i < npages; ++i) {
|
|
page = global_mem.page_metadata + i;
|
|
buddy_free_pages(&global_mem, page);
|
|
}
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = npages / powl(2, BUDDY_MAX_ORDER - 1);
|
|
mu_check(nget == ncheck);
|
|
|
|
/* alloc 2-pages for $npages/2 times */
|
|
test_alloc(&global_mem, npages / 2, 1);
|
|
|
|
/* should have 0 free pages */
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = 0;
|
|
mu_check(nget == ncheck);
|
|
|
|
/* free all pages */
|
|
for (i = 0; i < npages; i += 2) {
|
|
page = global_mem.page_metadata + i;
|
|
buddy_free_pages(&global_mem, page);
|
|
}
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = npages / powl(2, BUDDY_MAX_ORDER - 1);
|
|
mu_check(nget == ncheck);
|
|
|
|
/* alloc MAX_ORDER-pages for */
|
|
test_alloc(&global_mem, npages / powl(2, BUDDY_MAX_ORDER - 1),
|
|
BUDDY_MAX_ORDER - 1);
|
|
|
|
/* should have 0 free pages */
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = 0;
|
|
mu_check(nget == ncheck);
|
|
|
|
/* free all pages */
|
|
for (i = 0; i < npages; i += powl(2, BUDDY_MAX_ORDER - 1)) {
|
|
page = global_mem.page_metadata + i;
|
|
buddy_free_pages(&global_mem, page);
|
|
}
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = npages / powl(2, BUDDY_MAX_ORDER - 1);
|
|
mu_check(nget == ncheck);
|
|
|
|
/* alloc single page for $npages times */
|
|
test_alloc(&global_mem, npages, 0);
|
|
|
|
/* should have 0 free pages */
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = 0;
|
|
mu_check(nget == ncheck);
|
|
|
|
/* free a half pages */
|
|
for (i = 0; i < npages; i += 2) {
|
|
page = global_mem.page_metadata + i;
|
|
buddy_free_pages(&global_mem, page);
|
|
}
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = npages / 2;
|
|
mu_check(nget == ncheck);
|
|
|
|
/* free another half pages */
|
|
for (i = 1; i < npages; i += 2) {
|
|
page = global_mem.page_metadata + i;
|
|
buddy_free_pages(&global_mem, page);
|
|
}
|
|
nget = buddy_num_free_page(&global_mem);
|
|
ncheck = npages / powl(2, BUDDY_MAX_ORDER - 1);
|
|
mu_check(nget == ncheck);
|
|
}
|
|
|
|
MU_TEST_SUITE(test_suite)
|
|
{
|
|
MU_RUN_TEST(test_buddy);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
MU_RUN_SUITE(test_suite);
|
|
MU_REPORT();
|
|
return minunit_status;
|
|
}
|