Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed function pointers from heap implementation #482

Merged
merged 3 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
155 changes: 155 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,155 @@
#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 ((hentry_t *)a)->value <= ((hentry_t *)b)->value;
}
int
c_max(void *a, void *b)
{
return ((hentry_t *)a)->value >= ((hentry_t *)b)->value;
}
void
u(void *e, int pos)
{
((hentry_t *)e)->index = pos;
}

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

static void
entries_validate(heap_t *h, hentry_t *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;
hentry_t *prev, *es;
heap_t * h;

h = heap_alloc(amnt);
es = malloc(sizeof(hentry_t) * 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++) {
hentry_t *curr = type == MIN ? min_heap_highest(h) : max_heap_highest(h);
printc("highest:%d\n", curr->value);
if (type == MIN) {
if (!c_min((hentry_t *)prev, (hentry_t *)curr)) assert(0);
} else {
if (!c_max((hentry_t *)prev, (hentry_t *)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;
hentry_t *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
esmakokten marked this conversation as resolved.
Show resolved Hide resolved
#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;
}
46 changes: 24 additions & 22 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;
esmakokten marked this conversation as resolved.
Show resolved Hide resolved
unsigned int timer_heap[sizeof(struct heap) / sizeof(unsigned int) + MAX_NUM_TMR];
heap_t * timer_active;
unsigned int timer_heap[sizeof(heap_t) / 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 @@ -174,24 +188,24 @@ main(void)
}

wakeup = time_now();
t = heap_peek((struct heap *)timer_heap);
t = heap_peek((heap_t *)timer_heap);

if (t != NULL) {
/* At least one timer expired. Process all of them. */
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((heap_t *)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((heap_t *)timer_heap, t) == 0);
} else {
t->timeout_cyc = 0;
}

t = heap_peek((struct heap *)timer_heap);
t = heap_peek((heap_t *)timer_heap);
if (t == NULL) break;
}
}
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 = (heap_t *)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;
heap_t 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