--- /dev/null
+/**
+ @file segment.c
+ @brief See header for details
+*/
+#include "segment.h"
+#include <stdlib.h>
+#include <string.h>
+
+static uint8_t get_free_index(int32_t bitmap) {
+ static const uint8_t lookup[32] = {
+ 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+ 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
+ };
+ return lookup[((uint32_t)((bitmap & -bitmap) * 0x077CB531U)) >> 27];
+}
+
+segment_t* segment_create(uintptr_t blocksize)
+{
+ segment_t* seg = (segment_t*)malloc(sizeof(segment_t));
+ seg->blocksize = blocksize;
+ seg->start = (uintptr_t*)malloc(sizeof(uintptr_t) * blocksize * NUM_BLOCKS);
+ seg->end = (seg->start + (blocksize * NUM_BLOCKS));
+ memset(seg->blockmap, 0xFFu, sizeof(seg->blockmap));
+ return seg;
+}
+
+void segment_destroy(segment_t* seg)
+{
+ free(seg->start);
+ free(seg);
+}
+
+void* segment_alloc(segment_t* seg) {
+ void* obj = NULL;
+ /* Check if the segment has any free blocks */
+ if (0u != seg->blockmap[0]) {
+ /* Find the free block */
+ uint8_t root_idx = get_free_index(seg->blockmap[0]);
+ uint8_t submap_idx = get_free_index(seg->blockmap[root_idx + 1]);
+ /* Calculate it's address */
+ uintptr_t offset = seg->blocksize * ((root_idx * 16u) + submap_idx);
+ obj = seg->start + offset;
+ /* Mark it allocated */
+ seg->blockmap[root_idx + 1] &= ~(1u << submap_idx);
+ if (0u == seg->blockmap[root_idx + 1])
+ seg->blockmap[0] &= ~(1u << root_idx);
+ }
+ return obj;
+}
--- /dev/null
+/**
+ @file segment.h
+ @brief TODO: Describe this file
+*/
+#ifndef SEGMENT_H
+#define SEGMENT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define NUM_BLOCKS (256u)
+
+#define BLOCKMAP_SIZE (sizeof(uint16_t) + (NUM_BLOCKS / sizeof(uint16_t)))
+
+typedef struct {
+ uintptr_t blocksize;
+ uintptr_t* start;
+ uintptr_t* end;
+ uint16_t blockmap[BLOCKMAP_SIZE];
+} segment_t;
+
+segment_t* segment_create(uintptr_t blocksize);
+
+void segment_destroy(segment_t* seg);
+
+void* segment_alloc(segment_t* seg);
+
+#endif /* SEGMENT_H */
(void)argc;
(void)argv;
RUN_EXTERN_TEST_SUITE(SplayTree);
+ RUN_EXTERN_TEST_SUITE(Segment);
return PRINT_TEST_RESULTS();
}
--- /dev/null
+#include "atf.h"
+#include "segment.h"
+
+TEST_SUITE(Segment) {
+ /* Verify: segment_create
+ *************************************************************************/
+ TEST(Verify_Create_allocates_and_initializes_a_segment) {
+ int i;
+ segment_t* seg = segment_create(2u);
+ CHECK(seg->blocksize == 2u);
+ CHECK(seg->start != NULL);
+ CHECK(seg->end == (seg->start + (NUM_BLOCKS * 2u)));
+ for (i = 0; i < BLOCKMAP_SIZE; i++)
+ CHECK(seg->blockmap[i] == UINT16_MAX);
+ segment_destroy(seg);
+ }
+
+ /* Verify: segment_alloc
+ *************************************************************************/
+ TEST(Verify_alloc_allocates_the_first_block) {
+ segment_t* seg = segment_create(2u);
+ void* obj = segment_alloc(seg);
+ CHECK(obj == seg->start);
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_alloc_allocates_the_second_block) {
+ segment_t* seg = segment_create(2u);
+ seg->blockmap[1] = UINT16_MAX-1;
+ void* obj = segment_alloc(seg);
+ CHECK(obj == &seg->start[2]);
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_alloc_allocates_the_sixteenth_block) {
+ segment_t* seg = segment_create(2u);
+ seg->blockmap[0] = UINT16_MAX-1;
+ seg->blockmap[1] = 0u;
+ void* obj = segment_alloc(seg);
+ CHECK(obj == &seg->start[16*2]);
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_alloc_allocates_blocks_consecutively) {
+ segment_t* seg = segment_create(2u);
+ void* obj1 = segment_alloc(seg);
+ void* obj2 = segment_alloc(seg);
+ void* obj3 = segment_alloc(seg);
+ CHECK(obj1 == &seg->start[0]);
+ CHECK(obj2 == &seg->start[2]);
+ CHECK(obj3 == &seg->start[4]);
+ CHECK(seg->blockmap[0] == UINT16_MAX);
+ CHECK(seg->blockmap[1] == UINT16_MAX-7u);
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_alloc_allocates_blocks_consecutively_across_bitmap_boundaries) {
+ segment_t* seg = segment_create(2u);
+ seg->blockmap[1] = 1 << 15;
+ void* obj1 = segment_alloc(seg);
+ void* obj2 = segment_alloc(seg);
+ CHECK(obj1 == &seg->start[2*15]);
+ CHECK(obj2 == &seg->start[2*16]);
+ CHECK(seg->blockmap[0] == UINT16_MAX-1);
+ CHECK(seg->blockmap[1] == 0u);
+ CHECK(seg->blockmap[2] == UINT16_MAX-1);
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_alloc_returns_NULL_if_no_blocks_available) {
+ segment_t* seg = segment_create(2u);
+ seg->blockmap[0] = 0;
+ void* obj = segment_alloc(seg);
+ CHECK(obj == NULL);
+ segment_destroy(seg);
+ }
+}