1#include <mem/alloc.h>
2#include <mem/nofail.h>
3#include <sch/irql.h>
4#include <sch/rt_sched.h>
5#include <sync/spinlock.h>
6
7#include "internal.h"
8
9static struct rt_slot_db slot_db;
10
11static struct rt_slot *rt_slot_allocate(struct rt_scheduler_static *for_whom) {
12 enum irql irql = spin_lock_high(&slot_db.lock);
13
14 struct rt_slot *got = NULL;
15 for (size_t i = 0; i < slot_db.num_slots; i++) {
16 struct rt_slot *try = &slot_db.slots[i];
17 if (!try->in_use) {
18 got = try;
19 try->in_use = for_whom;
20 break;
21 }
22 }
23
24 spin_unlock(&slot_db.lock, irql);
25 return got;
26}
27
28size_t rt_slot_get_num_available(void) {
29 size_t count = 0;
30 enum irql irql = spin_lock_high(&slot_db.lock);
31
32 for (size_t i = 0; i < slot_db.num_slots; i++) {
33 if (!slot_db.slots[i].in_use)
34 count++;
35 }
36
37 spin_unlock(&slot_db.lock, irql);
38 return count;
39}
40
41static void rt_slot_free(size_t slot) {
42 enum irql irql = spin_lock_high(&slot_db.lock);
43
44 slot_db.slots[slot].in_use = NULL;
45
46 spin_unlock(&slot_db.lock, irql);
47}
48
49void rt_slot_init(size_t num_slots) {
50 slot_db.num_slots = num_slots;
51 spinlock_init(&slot_db.lock);
52 slot_db.slots = nofail_vnews(slot_db.slots, num_slots, ALLOC_ZERO);
53
54 for (size_t i = 0; i < num_slots; i++)
55 slot_db.slots[i].slot_index = i;
56}
57
58static void free_all_slots(struct rt_scheduler_static *rts) {
59 for (size_t i = 0; i < rts->num_slot_requests; i++) {
60 struct rt_slot_request *rq = &rts->slot_requests[i];
61 if (rq->mapped_to != -1)
62 rt_slot_free(slot: rq->mapped_to);
63
64 rq->mapped_to = -1;
65 }
66}
67
68enum rt_scheduler_error
69rt_slots_init_for_scheduler(struct rt_scheduler_static *rts) {
70 rt_sched_trace("Initializing slots for %s (%p)", rts->name, rts);
71 for (size_t i = 0; i < rts->num_slot_requests; i++) {
72 struct rt_slot_request *rq = &rts->slot_requests[i];
73 struct rt_slot *got = rt_slot_allocate(for_whom: rts);
74
75 if (got) {
76 rq->mapped_to = got->slot_index;
77 } else if (rq->prio == RT_SLOT_REQUIRED) {
78 free_all_slots(rts);
79 return RT_SCHEDULER_ERR_OOR;
80 }
81 }
82
83 return RT_SCHEDULER_ERR_OK;
84}
85
86void rt_slots_dealloc_for_scheduler(struct rt_scheduler_static *rts) {
87 rt_sched_trace("Deallocating slots for %s (%p)", rts->name, rts);
88 for (size_t i = 0; i < rts->num_slot_requests; i++) {
89 if (rts->slot_requests[i].mapped_to != -1)
90 rt_slot_free(slot: rts->slot_requests[i].mapped_to);
91
92 rts->slot_requests[i].mapped_to = -1;
93 }
94}
95