68 lines
1.6 KiB
D
68 lines
1.6 KiB
D
/**
|
|
* A1 memory allocator.
|
|
*/
|
|
module hulk.hurl.a1;
|
|
|
|
import hulk.hurl;
|
|
import hulk.hippo;
|
|
import hulk.util;
|
|
import hulk.pagetable;
|
|
import hulk.memory;
|
|
|
|
/**
|
|
* The A1 memory allocator is a one-shot memory allocator for kernel memory
|
|
* that is allocated but never freed.
|
|
*/
|
|
struct A1
|
|
{
|
|
/**
|
|
* Number of bytes allocated in the A1 region so far.
|
|
*/
|
|
private static __gshared size_t allocated;
|
|
|
|
/**
|
|
* Allocate memory.
|
|
*
|
|
* @param size
|
|
* Size of memory to allocate.
|
|
*
|
|
* @return Address of allocated memory. This address will always be aligned
|
|
* to a multiple of 16 bytes.
|
|
*/
|
|
public static void * allocate(size_t size)
|
|
{
|
|
/* Round size up to a multiple of 16. */
|
|
size = round_up_power_2(size, 16u);
|
|
|
|
ulong address = Hurl.A1_BASE + allocated;
|
|
|
|
ulong current_limit = round_up_power_2(address, PAGE_SIZE);
|
|
|
|
allocated += size;
|
|
|
|
ulong desired_limit = round_up_power_2(Hurl.A1_BASE + allocated, PAGE_SIZE);
|
|
|
|
while (desired_limit > current_limit)
|
|
{
|
|
void * page = Hippo.allocate_page();
|
|
Hurl.map(current_limit, page, PT_WRITABLE);
|
|
current_limit += PAGE_SIZE;
|
|
}
|
|
|
|
memset64(cast(void *)address, 0, size / 8);
|
|
|
|
return cast(void *)address;
|
|
}
|
|
|
|
/**
|
|
* Allocate memory to store an instance of a given type.
|
|
*
|
|
* @return Address of allocated memory. This address will always be aligned
|
|
* to a multiple of 16 bytes.
|
|
*/
|
|
public static T * allocate(T)()
|
|
{
|
|
return cast(T *)allocate(T.sizeof);
|
|
}
|
|
}
|