1#include <mem/alloc.h>
2#include <mem/alloc_or_die.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
11struct rt_slot *rt_slot_allocate(struct rt_scheduler_static *for_whom) {
12 enum irql irql = spin_lock_irq_disable(lock: &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(lock: &slot_db.lock, old: 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_irq_disable(lock: &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(lock: &slot_db.lock, old: irql);
38 return count;
39}
40
41void rt_slot_free(size_t slot) {
42 enum irql irql = spin_lock_irq_disable(lock: &slot_db.lock);
43
44 slot_db.slots[slot].in_use = NULL;
45
46 spin_unlock(lock: &slot_db.lock, old: irql);
47}
48
49void rt_slot_init(size_t num_slots) {
50 slot_db.num_slots = num_slots;
51 spinlock_init(lock: &slot_db.lock);
52 slot_db.slots = alloc_or_die(
53 kmalloc(sizeof(struct rt_slot) * num_slots, ALLOC_FLAGS_ZERO));
54
55 for (size_t i = 0; i < num_slots; i++)
56 slot_db.slots[i].slot_index = i;
57}
58
59static void free_all_slots(struct rt_scheduler_static *rts) {
60 for (size_t i = 0; i < rts->num_slot_requests; i++) {
61 struct rt_slot_request *rq = &rts->slot_requests[i];
62 if (rq->mapped_to != -1)
63 rt_slot_free(slot: rq->mapped_to);
64
65 rq->mapped_to = -1;
66 }
67}
68
69enum rt_scheduler_error
70rt_slots_init_for_scheduler(struct rt_scheduler_static *rts) {
71 rt_sched_trace("Initializing slots for %s (%p)", rts->name, rts);
72 for (size_t i = 0; i < rts->num_slot_requests; i++) {
73 struct rt_slot_request *rq = &rts->slot_requests[i];
74 struct rt_slot *got = rt_slot_allocate(for_whom: rts);
75
76 if (got) {
77 rq->mapped_to = got->slot_index;
78 } else if (rq->prio == RT_SLOT_REQUIRED) {
79 free_all_slots(rts);
80 return RT_SCHEDULER_ERR_OOR;
81 }
82 }
83
84 return RT_SCHEDULER_ERR_OK;
85}
86
87void rt_slots_dealloc_for_scheduler(struct rt_scheduler_static *rts) {
88 rt_sched_trace("Deallocating slots for %s (%p)", rts->name, rts);
89 for (size_t i = 0; i < rts->num_slot_requests; i++) {
90 if (rts->slot_requests[i].mapped_to != -1)
91 rt_slot_free(slot: rts->slot_requests[i].mapped_to);
92
93 rts->slot_requests[i].mapped_to = -1;
94 }
95}
96