libkernaux/src/pfa.c

133 lines
3.3 KiB
C
Raw Normal View History

2020-12-07 04:46:37 +00:00
#ifdef HAVE_CONFIG_H
2020-11-30 11:40:33 +00:00
#include "config.h"
2020-12-07 04:46:37 +00:00
#endif
2020-11-30 11:40:33 +00:00
#include <kernaux/pfa.h>
#include <kernaux/stdlib.h>
static void KernAux_PFA_mark(
2021-12-13 23:03:13 +00:00
KernAux_PFA pfa,
2020-12-06 10:16:15 +00:00
bool status,
size_t start,
size_t end
)
__attribute__((nonnull));
2021-12-13 23:03:13 +00:00
void KernAux_PFA_initialize(const KernAux_PFA pfa)
{
2020-12-06 10:16:15 +00:00
kernaux_memset(pfa->pages, false, sizeof(pfa->pages));
}
2021-12-13 23:10:05 +00:00
bool KernAux_PFA_is_available(const KernAux_PFA pfa, const size_t page_addr)
{
if (page_addr % KERNAUX_PFA_PAGE_SIZE != 0) return false;
return pfa->pages[page_addr / KERNAUX_PFA_PAGE_SIZE];
}
void KernAux_PFA_mark_available(
2021-12-13 23:03:13 +00:00
const KernAux_PFA pfa,
const size_t start,
const size_t end
) {
2020-12-06 10:16:15 +00:00
KernAux_PFA_mark(pfa, true, start, end);
}
void KernAux_PFA_mark_unavailable(
2021-12-13 23:03:13 +00:00
const KernAux_PFA pfa,
const size_t start,
const size_t end
) {
2020-12-06 10:16:15 +00:00
KernAux_PFA_mark(pfa, false, start, end);
}
void KernAux_PFA_mark(
2021-12-13 23:03:13 +00:00
const KernAux_PFA pfa,
2020-12-06 10:16:15 +00:00
const bool status,
size_t start,
size_t end
) {
if (start >= end) return;
const size_t start_rem = start % KERNAUX_PFA_PAGE_SIZE;
const size_t end_rem = (end + 1) % KERNAUX_PFA_PAGE_SIZE;
if (start_rem != 0) {
start = start - start_rem + KERNAUX_PFA_PAGE_SIZE;
}
if (end_rem != 0) {
end = end - end_rem;
}
const size_t start_index = start / KERNAUX_PFA_PAGE_SIZE;
const size_t end_index = end / KERNAUX_PFA_PAGE_SIZE;
for (size_t index = start_index; index <= end_index; ++index) {
pfa->pages[index] = status;
}
}
2020-11-30 23:38:55 +00:00
2021-12-13 23:03:13 +00:00
size_t KernAux_PFA_alloc_page(const KernAux_PFA pfa)
2020-11-30 23:38:55 +00:00
{
// We start from 1 because 0 indicates failure.
// It is not very useful to alloc page at address 0;
for (size_t index = 1; index < KERNAUX_PFA_PAGES_COUNT_MAX; ++index) {
2020-11-30 23:38:55 +00:00
if (pfa->pages[index]) {
2020-12-06 10:16:15 +00:00
pfa->pages[index] = false;
2020-11-30 23:38:55 +00:00
return index * KERNAUX_PFA_PAGE_SIZE;
}
}
return 0;
}
size_t KernAux_PFA_alloc_pages(const KernAux_PFA pfa, const size_t mem_size)
{
if (mem_size % KERNAUX_PFA_PAGE_SIZE != 0) return 0;
const size_t pages_count = mem_size / KERNAUX_PFA_PAGE_SIZE;
// We start from 1 because 0 indicates failure.
// It is not very useful to alloc page at address 0;
for (size_t start = 1; start < KERNAUX_PFA_PAGES_COUNT_MAX;) {
size_t end = start;
for (; end < start + pages_count; ++end) {
if (!pfa->pages[end]) break;
}
if (end >= KERNAUX_PFA_PAGES_COUNT_MAX) return 0;
if (end == start + pages_count - 1) {
for (size_t index = start; index <= end; ++index) {
pfa->pages[index] = false;
}
return start * KERNAUX_PFA_PAGE_SIZE;
}
start = end + 1;
}
return 0;
}
2021-12-13 23:03:13 +00:00
void KernAux_PFA_free_page(const KernAux_PFA pfa, size_t page_addr)
2020-11-30 23:38:55 +00:00
{
if (page_addr % KERNAUX_PFA_PAGE_SIZE != 0) return;
2020-11-30 23:38:55 +00:00
2020-12-06 10:16:15 +00:00
pfa->pages[page_addr / KERNAUX_PFA_PAGE_SIZE] = true;
2020-11-30 23:38:55 +00:00
}
void KernAux_PFA_free_pages(
const KernAux_PFA pfa,
const size_t page_addr,
const size_t mem_size
) {
if (page_addr % KERNAUX_PFA_PAGE_SIZE != 0) return;
if (mem_size % KERNAUX_PFA_PAGE_SIZE != 0) return;
const size_t start_index = page_addr / KERNAUX_PFA_PAGE_SIZE;
const size_t pages_count = mem_size / KERNAUX_PFA_PAGE_SIZE;
for (size_t index = 0; index < pages_count; ++index) {
pfa->pages[start_index + index] = true;
}
}