blob: 4e0130502c2a9353cb34b7eff777a1b474130987 [file] [log] [blame]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <allocman/cspace/single_level.h>
#include <allocman/util.h>
#include <allocman/allocman.h>
#include <sel4/sel4.h>
#include <string.h>
#define BITS_PER_WORD (sizeof(size_t) * 8)
int cspace_single_level_create(struct allocman *alloc, cspace_single_level_t *cspace, struct cspace_single_level_config config)
{
size_t num_slots;
size_t num_entries;
int error;
cspace->config = config;
/* Allocate bitmap */
num_slots = cspace->config.end_slot - cspace->config.first_slot;
num_entries = num_slots / BITS_PER_WORD;
cspace->bitmap_length = num_entries;
if (num_slots % BITS_PER_WORD != 0) {
num_entries++;
}
cspace->bitmap = (size_t*)allocman_mspace_alloc(alloc, num_entries * sizeof(size_t), &error);
if (error) {
return error;
}
/* Make everything 1's */
memset(cspace->bitmap, -1, num_entries * sizeof(size_t));
if (num_slots % BITS_PER_WORD != 0) {
/* Mark the padding slots as allocated */
size_t excess = num_slots % BITS_PER_WORD;
size_t i;
for (i = excess; i < BITS_PER_WORD; i++) {
cspace->bitmap[num_entries - 1] ^= BIT(i);
}
}
cspace->last_entry = 0;
return 0;
}
void cspace_single_level_destroy(struct allocman *alloc, cspace_single_level_t *cspace)
{
allocman_mspace_free(alloc, cspace->bitmap, cspace->bitmap_length * sizeof(size_t));
}
int _cspace_single_level_alloc(allocman_t *alloc, void *_cspace, cspacepath_t *slot)
{
size_t i;
size_t index;
cspace_single_level_t *cspace = (cspace_single_level_t*)_cspace;
i = cspace->last_entry;
if (cspace->bitmap[i] == 0) {
assert(cspace->bitmap_length != 0);
assert(cspace->last_entry < cspace->bitmap_length);
do {
i = (i + 1) % cspace->bitmap_length;
} while (cspace->bitmap[i] == 0 && i != cspace->last_entry);
if (i == cspace->last_entry) {
return 1;
}
cspace->last_entry = i;
}
index = BITS_PER_WORD - 1 - CLZL(cspace->bitmap[i]);
cspace->bitmap[i] &= ~BIT(index);
*slot = _cspace_single_level_make_path(cspace, cspace->config.first_slot + (i * BITS_PER_WORD + index));
return 0;
}
int _cspace_single_level_alloc_at(allocman_t *alloc, void *_cspace, seL4_CPtr slot) {
cspace_single_level_t *cspace = (cspace_single_level_t*)_cspace;
size_t index = slot - cspace->config.first_slot;
/* make sure index is in range */
if (index / BITS_PER_WORD >= cspace->bitmap_length) {
return 1;
}
/* make sure not already allocated */
if ( (cspace->bitmap[index / BITS_PER_WORD] & BIT(index % BITS_PER_WORD)) == 0) {
return 1;
}
/* mark it as allocated */
cspace->bitmap[index / BITS_PER_WORD] &= ~BIT(index % BITS_PER_WORD);
return 0;
}
void _cspace_single_level_free(allocman_t *alloc, void *_cspace, const cspacepath_t *slot)
{
cspace_single_level_t *cspace = (cspace_single_level_t*)_cspace;
size_t index = slot->capPtr - cspace->config.first_slot;
assert((cspace->bitmap[index / BITS_PER_WORD] & BIT(index % BITS_PER_WORD)) == 0);
cspace->bitmap[index / BITS_PER_WORD] |= BIT(index % BITS_PER_WORD);
}