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