]> git.mdlowis.com Git - archive/atc.git/commitdiff
Finished segment find and mark routine
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 4 Apr 2015 17:32:46 +0000 (13:32 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 4 Apr 2015 17:32:46 +0000 (13:32 -0400)
source/runtime/segment.c
tests/test_segment.c

index ee9226b9202e8fedd28b6556c88c697f6bba4c4d..fa69bc6136f2414be4a666aad45af62a2963afac 100644 (file)
@@ -39,6 +39,21 @@ bool segment_full(segment_t* seg) {
     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 */
@@ -46,13 +61,8 @@ void* segment_alloc(segment_t* seg) {
         /* 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;
 }
@@ -63,8 +73,15 @@ void segment_clear_map(segment_t* seg)
 }
 
 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;
 }
 
index 016e455fbbc5decdc548c4a502046c63ef5c87f5..4bbd7ea123af627f375a3ff4f21ee99e22386c29 100644 (file)
@@ -1,6 +1,8 @@
 #include "atf.h"
 #include "segment.h"
 
+#include <stdio.h>
+
 TEST_SUITE(Segment) {
     /* Verify: segment_create
      *************************************************************************/
@@ -74,4 +76,43 @@ TEST_SUITE(Segment) {
         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);
+    }
 }