1/**
2 * \file
3 * \brief Kernel control block declarations.
4 */
5
6/*
7 * Copyright (c) 2014, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <kernel.h>
16#include <kcb.h>
17#include <dispatch.h>
18#include <systime.h>
19
20// this is used to pin a kcb for critical sections
21bool kcb_sched_suspended = false;
22
23void kcb_add(struct kcb* new_kcb)
24{
25    if (kcb_current->next) {
26        // Insert new KCB in ring
27        assert(kcb_current->prev);
28
29        new_kcb->next = kcb_current->next;
30        new_kcb->prev = kcb_current;
31        new_kcb->next->prev = new_kcb;
32        new_kcb->prev->next = new_kcb;
33    } else {
34        // Only one KCB currently dispatching
35        kcb_current->next = kcb_current->prev = new_kcb;
36        new_kcb->next = new_kcb->prev = kcb_current;
37    }
38}
39
40errval_t kcb_remove(struct kcb *to_remove)
41{
42    if (to_remove == kcb_current) {
43        if (to_remove->next->next == to_remove) {
44            assert(to_remove->next->prev == to_remove);
45            to_remove->next->next = to_remove->next->prev = NULL;
46        }
47        else {
48            to_remove->prev->next = to_remove->next;
49            to_remove->next->prev = to_remove->prev;
50        }
51
52        // intentionally leaving to_remove->next alone
53        // so switch_kcb doesn't break
54        to_remove->prev = NULL;
55        to_remove->kernel_off = systime_now();
56
57        return SYS_ERR_OK;
58    }
59
60    // This probably failes atm.
61    for (struct kcb* k = kcb_current->next; k != kcb_current; k = k->next) {
62        if (k == to_remove) {
63            // remove KCB from ring
64            k->prev->next = k->next;
65            k->next->prev = k->prev;
66
67            // Clear ring to disable switching mechanism
68            if (k->next->next == k->next) {
69                k->next->next = k->next->prev = NULL;
70            }
71
72            // Clear next and prev of removed kcb
73            k->next = k->prev = NULL;
74
75            // Update kernel_off & break out if we're done
76            k->kernel_off = systime_now();
77            return SYS_ERR_OK;
78        }
79    }
80
81    return SYS_ERR_KCB_NOT_FOUND;
82}
83
84void kcb_update_core_id(struct kcb *kcb)
85{
86#ifdef CONFIG_SCHEDULER_RBED
87    for (struct dcb *d = kcb->queue_head; d; d = d->next) {
88        printk(LOG_NOTE, "[sched] updating current core id to %d for %s\n",
89                my_core_id, get_disp_name(d));
90        struct dispatcher_shared_generic *disp =
91            get_dispatcher_shared_generic(d->disp);
92        disp->curr_core_id = my_core_id;
93    }
94#elif CONFIG_SCHEDULER_RR
95#error NYI!
96#else
97#error must define scheduler policy in Config.hs
98#endif
99    // do it for dcbs in wakeup queue
100    for (struct dcb *d = kcb->wakeup_queue_head; d; d=d->wakeup_next) {
101        printk(LOG_NOTE, "[wakeup] updating current core id to %d for %s\n",
102                my_core_id, get_disp_name(d));
103        struct dispatcher_shared_generic *disp =
104            get_dispatcher_shared_generic(d->disp);
105        disp->curr_core_id = my_core_id;
106    }
107
108    for (int i = 0; i < NDISPATCH; i++) {
109        struct capability *cap = &kcb->irq_dispatch[i].cap;
110        if (cap->type == ObjType_EndPointLMP) {
111            printk(LOG_NOTE, "[irq] updating current core id to %d for %s\n",
112                    my_core_id, get_disp_name(cap->u.endpointlmp.listener));
113            struct dispatcher_shared_generic *disp =
114                get_dispatcher_shared_generic(cap->u.endpointlmp.listener->disp);
115            disp->curr_core_id = my_core_id;
116        }
117    }
118}
119