aos/kernel/kcb.c
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

119 lines
3.6 KiB
C

/**
* \file
* \brief Kernel control block declarations.
*/
/*
* Copyright (c) 2014, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
* ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
*/
#include <kernel.h>
#include <kcb.h>
#include <dispatch.h>
#include <systime.h>
// this is used to pin a kcb for critical sections
bool kcb_sched_suspended = false;
void kcb_add(struct kcb* new_kcb)
{
if (kcb_current->next) {
// Insert new KCB in ring
assert(kcb_current->prev);
new_kcb->next = kcb_current->next;
new_kcb->prev = kcb_current;
new_kcb->next->prev = new_kcb;
new_kcb->prev->next = new_kcb;
} else {
// Only one KCB currently dispatching
kcb_current->next = kcb_current->prev = new_kcb;
new_kcb->next = new_kcb->prev = kcb_current;
}
}
errval_t kcb_remove(struct kcb *to_remove)
{
if (to_remove == kcb_current) {
if (to_remove->next->next == to_remove) {
assert(to_remove->next->prev == to_remove);
to_remove->next->next = to_remove->next->prev = NULL;
}
else {
to_remove->prev->next = to_remove->next;
to_remove->next->prev = to_remove->prev;
}
// intentionally leaving to_remove->next alone
// so switch_kcb doesn't break
to_remove->prev = NULL;
to_remove->kernel_off = systime_now();
return SYS_ERR_OK;
}
// This probably failes atm.
for (struct kcb* k = kcb_current->next; k != kcb_current; k = k->next) {
if (k == to_remove) {
// remove KCB from ring
k->prev->next = k->next;
k->next->prev = k->prev;
// Clear ring to disable switching mechanism
if (k->next->next == k->next) {
k->next->next = k->next->prev = NULL;
}
// Clear next and prev of removed kcb
k->next = k->prev = NULL;
// Update kernel_off & break out if we're done
k->kernel_off = systime_now();
return SYS_ERR_OK;
}
}
return SYS_ERR_KCB_NOT_FOUND;
}
void kcb_update_core_id(struct kcb *kcb)
{
#ifdef CONFIG_SCHEDULER_RBED
for (struct dcb *d = kcb->queue_head; d; d = d->next) {
printk(LOG_NOTE, "[sched] updating current core id to %d for %s\n",
my_core_id, get_disp_name(d));
struct dispatcher_shared_generic *disp =
get_dispatcher_shared_generic(d->disp);
disp->curr_core_id = my_core_id;
}
#elif CONFIG_SCHEDULER_RR
#error NYI!
#else
#error must define scheduler policy in Config.hs
#endif
// do it for dcbs in wakeup queue
for (struct dcb *d = kcb->wakeup_queue_head; d; d=d->wakeup_next) {
printk(LOG_NOTE, "[wakeup] updating current core id to %d for %s\n",
my_core_id, get_disp_name(d));
struct dispatcher_shared_generic *disp =
get_dispatcher_shared_generic(d->disp);
disp->curr_core_id = my_core_id;
}
for (int i = 0; i < NDISPATCH; i++) {
struct capability *cap = &kcb->irq_dispatch[i].cap;
if (cap->type == ObjType_EndPointLMP) {
printk(LOG_NOTE, "[irq] updating current core id to %d for %s\n",
my_core_id, get_disp_name(cap->u.endpointlmp.listener));
struct dispatcher_shared_generic *disp =
get_dispatcher_shared_generic(cap->u.endpointlmp.listener->disp);
disp->curr_core_id = my_core_id;
}
}
}