IRQ: added irq source capability and make the inthandler setup use it
[barrelfish] / kernel / kcb.c
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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <kernel.h>
16 #include <kcb.h>
17 #include <dispatch.h>
18
19 // this is used to pin a kcb for critical sections
20 bool kcb_sched_suspended = false;
21
22 void kcb_add(struct kcb* new_kcb)
23 {
24     if (kcb_current->next) {
25         // Insert new KCB in ring
26         assert(kcb_current->prev);
27
28         new_kcb->next = kcb_current->next;
29         new_kcb->prev = kcb_current;
30         new_kcb->next->prev = new_kcb;
31         new_kcb->prev->next = new_kcb;
32     } else {
33         // Only one KCB currently dispatching
34         kcb_current->next = kcb_current->prev = new_kcb;
35         new_kcb->next = new_kcb->prev = kcb_current;
36     }
37 }
38
39 errval_t kcb_remove(struct kcb *to_remove)
40 {
41     if (to_remove == kcb_current) {
42         if (to_remove->next->next == to_remove) {
43             assert(to_remove->next->prev == to_remove);
44             to_remove->next->next = to_remove->next->prev = NULL;
45         } 
46         else {
47             to_remove->prev->next = to_remove->next;
48             to_remove->next->prev = to_remove->prev;
49         }
50
51         // intentionally leaving to_remove->next alone
52         // so switch_kcb doesn't break
53         to_remove->prev = NULL;
54         to_remove->kernel_off = kernel_now;
55
56         return SYS_ERR_OK;
57     }
58
59     // This probably failes atm.
60     for (struct kcb* k = kcb_current->next; k != kcb_current; k = k->next) {
61         if (k == to_remove) {
62             // remove KCB from ring
63             k->prev->next = k->next;
64             k->next->prev = k->prev;
65
66             // Clear ring to disable switching mechanism
67             if (k->next->next == k->next) {
68                 k->next->next = k->next->prev = NULL;
69             }
70
71             // Clear next and prev of removed kcb
72             k->next = k->prev = NULL;
73
74             // Update kernel_off & break out if we're done
75             k->kernel_off = kernel_now;
76             return SYS_ERR_OK;
77         }
78     }
79
80     return SYS_ERR_KCB_NOT_FOUND;
81 }
82
83 void kcb_update_core_id(struct kcb *kcb)
84 {
85 #ifdef CONFIG_SCHEDULER_RBED
86     for (struct dcb *d = kcb->queue_head; d; d = d->next) {
87         printk(LOG_NOTE, "[sched] updating current core id to %d for %s\n",
88                 my_core_id, get_disp_name(d));
89         struct dispatcher_shared_generic *disp =
90             get_dispatcher_shared_generic(d->disp);
91         disp->curr_core_id = my_core_id;
92     }
93 #elif CONFIG_SCHEDULER_RR
94 #error NYI!
95 #else
96 #error must define scheduler policy in Config.hs
97 #endif
98     // do it for dcbs in wakeup queue
99     for (struct dcb *d = kcb->wakeup_queue_head; d; d=d->wakeup_next) {
100         printk(LOG_NOTE, "[wakeup] updating current core id to %d for %s\n",
101                 my_core_id, get_disp_name(d));
102         struct dispatcher_shared_generic *disp =
103             get_dispatcher_shared_generic(d->disp);
104         disp->curr_core_id = my_core_id;
105     }
106
107     for (int i = 0; i < NDISPATCH; i++) {
108         struct capability *cap = &kcb->irq_dest_caps[i]->cap;
109         assert(cap->type != ObjType_EndPoint); // Now we store IRQVector caps here
110         if (cap->type == ObjType_IRQVector) {
111             struct capability * ep = cap->u.irqvector.ep;
112             if(ep){
113                 assert(ep->type == ObjType_EndPoint);
114                 printk(LOG_NOTE, "[irq] updating current core id to %d for %s\n",
115                                     my_core_id, get_disp_name(ep->u.endpoint.listener));
116                             struct dispatcher_shared_generic *disp =
117                                 get_dispatcher_shared_generic(ep->u.endpoint.listener->disp);
118                             disp->curr_core_id = my_core_id;
119             }
120
121         }
122     }
123 }