return (0u == seg->blockmap[0]);
}
+static void* alloc_block(segment_t* seg, uintptr_t root_idx, uintptr_t submap_idx) {
+ void* object = NULL;
+ uintptr_t submap_mask = (1u << submap_idx);
+ if (0u != (seg->blockmap[root_idx + 1] & submap_mask)) {
+ /* Get the object's pointer */
+ uintptr_t offset = seg->blocksize * ((root_idx * 16u) + submap_idx);
+ object = seg->start + offset;
+ /* Mark it as allocated */
+ seg->blockmap[root_idx + 1] &= ~(submap_mask);
+ if (0u == seg->blockmap[root_idx + 1])
+ seg->blockmap[0] &= ~(1u << root_idx);
+ }
+ return object;
+}
+
void* segment_alloc(segment_t* seg) {
void* obj = NULL;
/* Check if the segment has any free blocks */
/* 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);
+ /* Allocate and return its address */
+ obj = alloc_block(seg, root_idx, submap_idx);
}
return obj;
}
}
void* segment_find_and_mark(segment_t* seg, uintptr_t addr) {
- (void)seg;
- (void)addr;
- return NULL;
+ void* obj = NULL;
+ uintptr_t start = (uintptr_t)&(seg->start[0]);
+ uintptr_t end = (uintptr_t)seg->end;
+ if ((start <= addr) && (addr < end)) {
+ uintptr_t block_num = (addr - start) / (seg->blocksize * sizeof(uintptr_t));
+ uintptr_t root_idx = block_num / 16u;
+ uintptr_t submap_idx = block_num % 16u;
+ obj = alloc_block(seg, root_idx, submap_idx);
+ }
+ return obj;
}
#include "atf.h"
#include "segment.h"
+#include <stdio.h>
+
TEST_SUITE(Segment) {
/* Verify: segment_create
*************************************************************************/
CHECK(obj == NULL);
segment_destroy(seg);
}
+
+ /* Verify: segment_find_and_mark
+ *************************************************************************/
+ TEST(Verify_find_and_mark_should_find_and_mark_a_block) {
+ segment_t* seg = segment_create(2u, NULL);
+ CHECK(&seg->start[2] == segment_find_and_mark(seg, (uintptr_t)&seg->start[2]));
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_find_and_mark_should_find_and_mark_first_block) {
+ segment_t* seg = segment_create(2u, NULL);
+ CHECK(&seg->start[0] == segment_find_and_mark(seg, (uintptr_t)&seg->start[0]));
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_find_and_mark_should_find_and_mark_last_block) {
+ segment_t* seg = segment_create(2u, NULL);
+ CHECK(&seg->start[510] == segment_find_and_mark(seg, ((uintptr_t)&seg->start[511]) + (sizeof(uintptr_t) - 1) ));
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_find_and_mark_should_return_null_when_block_is_already_in_use) {
+ segment_t* seg = segment_create(2u, NULL);
+ seg->blockmap[1] &= ~(2);
+ CHECK(NULL == segment_find_and_mark(seg, (uintptr_t)&seg->start[2]));
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_find_and_mark_should_return_null_when_address_is_lower_than_segment_range) {
+ segment_t* seg = segment_create(2u, NULL);
+ CHECK(NULL == segment_find_and_mark(seg, (uintptr_t)&seg->start[-1]));
+ segment_destroy(seg);
+ }
+
+ TEST(Verify_find_and_mark_should_return_null_when_address_is_greater_than_segment_range) {
+ segment_t* seg = segment_create(2u, NULL);
+ CHECK(NULL == segment_find_and_mark(seg, (uintptr_t)&seg->start[512]));
+ segment_destroy(seg);
+ }
}