#include #include #include #include #include #include #include static u32 phy_malloc_4k_lock; static phyaddr_t phy_malloc_4k_p = 96 * MB; // 96MB~128MB = 0x0600_0000 ~ 0x0800_0000 // 32MB = 32 * 1024 / 4 = 8192 PAGES #define PHY_START (96 * MB) #define PHY_END (128 * MB) #define PHY_PAGENUM ((PHY_END - PHY_START) / PGSIZE) // map them to 8192 slots #define PHY_INDEX(paddr) ((paddr - PHY_START) >> 12) #define PHY_PADDR(idx) ((idx << 12) + PHY_START) // we have a head index point to the lowest free slot // if slot[i] is free, slot[i] = the index of the next free slot // else, slot[i] = -1 // when initialize, slots are initialized to {1, 2, 3, ...} // when alloc, head mov to slot[i], then set slot[i] = 0 // when free, set slot[i]=head, head = i static int phy_free_head; static int phy_free_table[PHY_PAGENUM]; void phy_init_4k() { for (int i = 0; i < PHY_PAGENUM - 1; ++ i) { phy_free_table[i] = i + 1; } phy_free_table[PHY_PAGENUM-1] = -1; phy_free_head = 0; } /* * 释放物理页面,这里并没有为你实现好free_4k的代码, * 你需要自己实现一个数据结构用于维护释放的页面, * 需要有回收资源的意识,这是一个系统必须有的功能。 */ void phy_free_4k(phyaddr_t paddr) { assert(paddr % PGSIZE == 0); assert(96 * MB <= paddr && paddr < 128 * MB); while(xchg(&phy_malloc_4k_lock, 1) == 1) schedule(); phy_free_table[PHY_INDEX(paddr)] = phy_free_head; phy_free_head = PHY_INDEX(paddr); xchg(&phy_malloc_4k_lock, 0); } /* * 分配物理页面,每次分配4kb,一页 * 分配的物理内存区间为96MB~128MB */ phyaddr_t phy_malloc_4k(void) { while(xchg(&phy_malloc_4k_lock, 1) == 1) schedule(); assert(0 <= phy_free_head && phy_free_head < PHY_PAGENUM); phyaddr_t paddr = PHY_PADDR(phy_free_head); phy_free_head = phy_free_table[phy_free_head]; phy_free_table[PHY_INDEX(paddr)] = -1; // assert(phy_malloc_4k_p < 128 * MB); // phyaddr_t paddr = phy_malloc_4k_p; // phy_malloc_4k_p += PGSIZE; free: xchg(&phy_malloc_4k_lock, 0); return paddr; } struct kmalloc_header { struct kmalloc_header *ptr; size_t size; }; static struct kmalloc_header *freePtr; static u32 malloc_lock; /* * 释放kmalloc申请的内存 */ void kfree(void *v) { struct kmalloc_header *bp, *p; bp = (struct kmalloc_header*)v - 1; while(xchg(&malloc_lock, 1) == 1) schedule(); for (p = freePtr; !(bp > p && bp < p->ptr); p = p->ptr) { if (p >= p->ptr && (bp > p || bp < p->ptr)) { break; } } if (bp + bp->size == p->ptr) { bp->size += p->ptr->size; bp->ptr = p->ptr->ptr; } else { bp->ptr = p->ptr; } if (p + p->size == bp) { p->size += bp->size; p->ptr = bp->ptr; } else { p->ptr = bp; } freePtr = p; free: xchg(&malloc_lock, 0); } /* * 分配内存,大小为n字节。 * 分配物理内存区间为64MB~96MB */ void * kmalloc(size_t n) { struct kmalloc_header *p, *prevP; size_t nUnits; void *ret; while(xchg(&malloc_lock, 1) == 1) schedule(); nUnits = (n + sizeof(struct kmalloc_header) - 1) / sizeof(struct kmalloc_header) + 1; if ((prevP = freePtr) == 0) { freePtr = prevP = (void *)K_PHY2LIN(64 * MB); freePtr->ptr = freePtr; freePtr->size = (32 * MB) / sizeof(struct kmalloc_header); } for (p = prevP->ptr ; ; prevP = p, p = p->ptr) { if (p->size >= nUnits) { if (p->size == nUnits) { prevP->ptr = p->ptr; } else { p->size -= nUnits; p += p->size; p->size = nUnits; } freePtr = prevP; ret = (void*)(p + 1); goto free; } if (p == freePtr) { panic("malloc failed!"); } } free: xchg(&malloc_lock, 0); return ret; }