2021-05-23 22:24:02 +08:00

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;
}