Skip to content

Commit

Permalink
Merge pull request #482 from esmakokten/heap_implementation_change
Browse files Browse the repository at this point in the history
Removed function pointers from heap implementation
  • Loading branch information
gparmer committed Jul 22, 2024
2 parents e7d0a77 + 7da584a commit 99a8118
Show file tree
Hide file tree
Showing 7 changed files with 464 additions and 444 deletions.
29 changes: 29 additions & 0 deletions composition_scripts/unit_heap.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[system]
description = "Simplest system for the heap functionality test"

[[components]]
name = "booter"
img = "no_interface.llbooter"
implements = [{interface = "init"}, {interface = "addr"}]
deps = [{srv = "kernel", interface = "init", variant = "kernel"}]
constructor = "kernel"

[[components]]
name = "capmgr"
img = "capmgr.simple"
deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}]
implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}, {interface = "contigmem"}]
constructor = "booter"

[[components]]
name = "sched"
img = "sched.pfprr_quantum_static"
deps = [{srv = "capmgr", interface = "init"}, {srv = "capmgr", interface = "capmgr"}, {srv = "capmgr", interface = "memmgr"}]
implements = [{interface = "sched"}, {interface = "init"}]
constructor = "booter"

[[components]]
name = "heapuser"
img = "tests.unit_heap"
deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "capmgr", interface = "contigmem"}]
constructor = "booter"
18 changes: 18 additions & 0 deletions src/components/implementation/tests/unit_heap/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Required variables used to drive the compilation process. It is OK
# for many of these to be empty.
#
# The set of interfaces that this component exports for use by other
# components. This is a list of the interface names.
INTERFACE_EXPORTS =
# The interfaces this component is dependent on for compilation (this
# is a list of directory names in interface/)
INTERFACE_DEPENDENCIES = init
# The library dependencies this component is reliant on for
# compilation/linking (this is a list of directory names in lib/)
LIBRARY_DEPENDENCIES = component time util posix posix_cap posix_sched
# Note: Both the interface and library dependencies should be
# *minimal*. That is to say that removing a dependency should cause
# the build to fail. The build system does not validate this
# minimality; that's on you!

include Makefile.subsubdir
154 changes: 154 additions & 0 deletions src/components/implementation/tests/unit_heap/heap_user.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#include <cos_debug.h>
#include <llprint.h>
#include <assert.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <string.h>
#include <heap.h>
#include <malloc.h>
#include <posix.h>

#define VAL_BOUND 1000000

typedef enum {
MIN = 0,
MAX,
} heap_type_t;

int
c_min(void *a, void *b)
{
return ((struct hentry *)a)->value <= ((struct hentry *)b)->value;
}
int
c_max(void *a, void *b)
{
return ((struct hentry *)a)->value >= ((struct hentry *)b)->value;
}
void
u(void *e, int pos)
{
((struct hentry *)e)->index = pos;
}

DECLARE_HEAP(min, c_min, u);
DECLARE_HEAP(max, c_max, u);

static void
entries_validate(struct heap *h, struct hentry *es, int amnt)
{
int i;

for (i = 0; i < amnt; i++) {
assert(h->data[es[i].index] == &es[i]);
}
}

static void
test_driver(int amnt, int type)
{
int i;
struct hentry *prev, *es;
struct heap * h;

h = heap_alloc(amnt);
es = malloc(sizeof(struct hentry) * amnt);
assert(es);

for (i = 0; i < amnt; i++) {
es[i].value = rand() % VAL_BOUND;
printc("adding@%d:%d\n", i, es[i].value);
if (type == MIN) {
assert(!min_heap_add(h, &es[i]));
assert(!min_heap_verify(h, 1));
} else {
assert(!max_heap_add(h, &es[i]));
assert(!max_heap_verify(h, 1));
}
}
entries_validate(h, es, amnt);
for (i = 0; i < amnt; i++) {
es[i].value = rand() % VAL_BOUND;
printc("adjusting@%d:%d\n", i, es[i].value);
if (type == MIN) {
min_heap_adjust(h, es[i].index);
assert(!min_heap_verify(h, 1));
} else {
max_heap_adjust(h, es[i].index);
assert(!max_heap_verify(h, 1));
}
}
entries_validate(h, es, amnt);
prev = h->data[1];
for (i = 0; i < amnt; i++) {
struct hentry *curr = type == MIN ? min_heap_highest(h) : max_heap_highest(h);
printc("highest:%d\n", curr->value);
if (type == MIN) {
if (!c_min((struct hentry *)prev, (struct hentry *)curr)) assert(0);
} else {
if (!c_max((struct hentry *)prev, (struct hentry *)curr)) assert(0);
}
prev = curr;
}
if (type == MIN) {
assert(!min_heap_highest(h));
assert(!min_heap_verify(h, 1));
} else {
assert(!max_heap_highest(h));
assert(!max_heap_verify(h, 1));
}

assert(heap_size(h) == 0);
for (i = 0; i < amnt; i++) {
es[i].value = rand() % VAL_BOUND;
printc("adding@%d:%d\n", i, es[i].value);
assert(!min_heap_add(h, &es[i]));
}
entries_validate(h, es, amnt);
for (i = amnt; i > 0; i--) {
int idx;
idx = (rand() % i) + 1;
struct hentry *curr = type == MIN ? min_heap_remove(h, idx) : max_heap_remove(h, idx);
printc("removing:%d\n", curr->value);
assert(curr);
assert(h->e == i);
}

if (type == MIN) {
assert(!min_heap_highest(h));
assert(!min_heap_verify(h, 1));
} else {
assert(!max_heap_highest(h));
assert(!max_heap_verify(h, 1));
}
assert(heap_size(h) == 0);

heap_destroy(h);
free(es);
}

#define ITER 10
#define BOUND 4096

int
main(void)
{
int i;

srand(time(NULL));

for (i = 0; i < ITER; i++) {
int items = rand() % BOUND;

printc("MIN-HEAP TEST - iter:%d items:%d\n", i, items);
test_driver(items, MIN);
printc("MAX-HEAP TEST - iter:%d items:%d\n", i, items);
test_driver(items, MAX);
}

printc("TEST PASSED\n");
return 0;
}
40 changes: 21 additions & 19 deletions src/components/implementation/tmrmgr/simple/tmrmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,25 @@ struct tmr_info {
};

SS_STATIC_SLAB(timer, struct tmr_info, MAX_NUM_TMR);
struct heap* timer_active;
struct heap * timer_active;
unsigned int timer_heap[sizeof(struct heap) / sizeof(unsigned int) + MAX_NUM_TMR];
thdid_t main_thdid;
unsigned long modifying;

int
timer_cmp_fn(void* a, void* b)
{
return ((struct tmr_info*)a)->timeout_cyc <= ((struct tmr_info*)b)->timeout_cyc;
}

void
timer_update_fn(void* e, int pos)
{
((struct tmr_info*)e)->index = pos;
}

DECLARE_HEAP(tmrmgr, timer_cmp_fn, timer_update_fn);

tmr_id_t
tmrmgr_create(unsigned int usecs, tmr_flags_t flags)
{
Expand Down Expand Up @@ -80,7 +94,7 @@ tmrmgr_start(tmr_id_t id)
lock = ps_faa(&modifying, 1);
if (lock == 0) {
t->timeout_cyc = time_now() + time_usec2cyc(t->usecs);
assert(heap_add(timer_active, t) == 0);
assert(tmrmgr_heap_add(timer_active, t) == 0);
ps_faa(&modifying, -1);
} else return -2;

Expand All @@ -106,7 +120,7 @@ tmrmgr_stop(tmr_id_t id)

lock = ps_faa(&modifying, 1);
if (lock == 0) {
heap_remove(timer_active, t->index);
tmrmgr_heap_remove(timer_active, t->index);
t->timeout_cyc = 0;
ps_faa(&modifying, -1);
} else return -2;
Expand Down Expand Up @@ -181,12 +195,12 @@ main(void)
while(t->timeout_cyc <= (wakeup + time_usec2cyc(MIN_USECS_LIMIT))) {
debug("Timer manager: id %d expired.\n", ss_timer_id(t));
evt_trigger(t->evt_id);
t = heap_highest((struct heap *)timer_heap);
t = tmrmgr_heap_highest((struct heap *)timer_heap);

if (t->flags == TMR_PERIODIC) {
debug("Timer manager: added back id %d to heap.\n", ss_timer_id(t));
t->timeout_cyc = time_now() + time_usec2cyc(t->usecs);
assert(heap_add((struct heap *)timer_heap, t) == 0);
assert(tmrmgr_heap_add((struct heap *)timer_heap, t) == 0);
} else {
t->timeout_cyc = 0;
}
Expand All @@ -209,25 +223,13 @@ main(void)
return 0;
}

int
timer_cmp_fn(void* a, void* b)
{
return ((struct tmr_info*)a)->timeout_cyc <= ((struct tmr_info*)b)->timeout_cyc;
}

void
timer_update_fn(void* e, int pos)
{
((struct tmr_info*)e)->index = pos;
}

void
cos_init(void)
{
printc("Timer manager: init.\n");

/* Initialize active timer heap */
modifying = 0;
timer_active = (struct heap*)timer_heap;
heap_init(timer_active, MAX_NUM_TMR, timer_cmp_fn, timer_update_fn);
timer_active = (struct heap *)timer_heap;
heap_init(timer_active, MAX_NUM_TMR);
}
38 changes: 19 additions & 19 deletions src/components/lib/slm/quantum.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,23 @@
/***
* Quantum-based time management. Wooo. Periodic timer FTW.
*/
static int
__slm_timeout_compare_min(void *a, void *b)
{
/* FIXME: logic for wraparound in either timeout_cycs */
return slm_thd_timer_policy((struct slm_thd *)a)->abs_wakeup <= slm_thd_timer_policy((struct slm_thd *)b)->abs_wakeup;
}

static void
__slm_timeout_update_idx(void *e, int pos)
{ slm_thd_timer_policy((struct slm_thd *)e)->timeout_idx = pos; }

DECLARE_HEAP(timer, __slm_timeout_compare_min, __slm_timeout_update_idx);
struct timer_global {
struct heap h;
void *data[MAX_NUM_THREADS];
cycles_t period;
cycles_t current_timeout;
struct heap h;
void *data[MAX_NUM_THREADS];
cycles_t period;
cycles_t current_timeout;
} CACHE_ALIGNED;

static struct timer_global __timer_globals[NUM_CPU];
Expand Down Expand Up @@ -43,7 +54,7 @@ quantum_wakeup_expired(cycles_t now)
if (cycles_greater_than(tt->abs_wakeup, now)) break;

/* Dequeue thread with closest wakeup */
th = heap_highest(&g->h);
th = timer_heap_highest(&g->h);
assert(th == tp);

tt->timeout_idx = -1;
Expand Down Expand Up @@ -94,7 +105,7 @@ slm_timer_quantum_add(struct slm_thd *t, cycles_t absolute_timeout)
assert(heap_size(&g->h) < MAX_NUM_THREADS);

tt->abs_wakeup = absolute_timeout;
heap_add(&g->h, t);
timer_heap_add(&g->h, t);

return 0;
}
Expand All @@ -110,7 +121,7 @@ slm_timer_quantum_cancel(struct slm_thd *t)
assert(heap_size(&g->h));
assert(tt->timeout_idx > 0);

heap_remove(&g->h, tt->timeout_idx);
timer_heap_remove(&g->h, tt->timeout_idx);
tt->timeout_idx = -1;

return 0;
Expand All @@ -135,17 +146,6 @@ slm_timer_quantum_thd_deinit(struct slm_thd *t)
return;
}

static int
__slm_timeout_compare_min(void *a, void *b)
{
/* FIXME: logic for wraparound in either timeout_cycs */
return slm_thd_timer_policy((struct slm_thd *)a)->abs_wakeup <= slm_thd_timer_policy((struct slm_thd *)b)->abs_wakeup;
}

static void
__slm_timeout_update_idx(void *e, int pos)
{ slm_thd_timer_policy((struct slm_thd *)e)->timeout_idx = pos; }

static void
slm_policy_timer_init(microsec_t period)
{
Expand All @@ -154,7 +154,7 @@ slm_policy_timer_init(microsec_t period)

memset(g, 0, sizeof(struct timer_global));
g->period = slm_usec2cyc(period);
heap_init(&g->h, MAX_NUM_THREADS, __slm_timeout_compare_min, __slm_timeout_update_idx);
heap_init(&g->h, MAX_NUM_THREADS);

next_timeout = slm_now() + g->period;
g->current_timeout = next_timeout;
Expand Down
Loading

0 comments on commit 99a8118

Please sign in to comment.