1/* @title: Scheduler Periodic Work */
2#pragma once
3#include <compiler.h>
4#include <linker/symbols.h>
5#include <structures/list.h>
6#include <structures/pairing_heap.h>
7#include <types/types.h>
8
9enum scheduler_periodic_work_prio {
10 PERIODIC_WORK_HIGH,
11 PERIODIC_WORK_MID,
12 PERIODIC_WORK_LOW,
13 PERIODIC_WORK_MAX,
14};
15
16enum scheduler_periodic_work_type {
17 PERIODIC_WORK_PERIOD_BASED,
18 PERIODIC_WORK_TIME_BASED,
19};
20
21struct scheduler_periodic_work_linker_object {
22 char *name;
23 void (*fn)();
24
25 union {
26 time_t time_interval;
27 size_t period_interval; /* overloaded */
28 size_t interval;
29 };
30
31 enum scheduler_periodic_work_type type;
32 enum scheduler_periodic_work_prio prio;
33};
34
35struct scheduler_periodic_work {
36 enum scheduler_periodic_work_type type;
37 enum scheduler_periodic_work_prio prio;
38 char *name;
39 void (*fn)();
40 cpu_id_t cpu; /* for which CPU? */
41
42 union {
43 struct {
44 uint64_t last_period_ran;
45 uint64_t period_interval;
46 uint64_t expected_period;
47 };
48
49 struct {
50 time_t last_time_ran;
51 time_t time_interval;
52 time_t expected_next_time;
53 };
54
55 /* generic struct - do not reorder members */
56 struct {
57 size_t last_occurrence;
58 size_t interval;
59 size_t expected_next;
60 };
61 };
62
63 size_t executed_times;
64
65 /* irrelevant for non-time based work */
66 time_t interval_total_loss; /* all time lost from misses */
67 size_t interval_latency; /* total_loss / executed_times */
68
69 struct pairing_node pnode; /* ordered by expected_next */
70};
71
72struct scheduler_periodic_work_limits {
73 /* per_call here is each time the works are invoked (together) */
74 size_t max_execs_per_call;
75 time_t max_duration_per_call_ns;
76};
77
78struct scheduler_periodic_work_percpu {
79 struct pairing_heap period_based_works[PERIODIC_WORK_MAX];
80 struct pairing_heap time_based_works[PERIODIC_WORK_MAX];
81
82 size_t period_based_work_count[PERIODIC_WORK_MAX];
83 size_t time_based_work_count[PERIODIC_WORK_MAX];
84
85 struct scheduler_periodic_work_limits limits;
86 cpu_id_t cpu;
87 bool executing;
88};
89
90LINKER_SECTION_DEFINE(struct scheduler_periodic_work_linker_object,
91 sched_periodic_work);
92
93#define SCHEDULER_PERIODIC_WORK_REGISTER(_fn, _type, _prio, _interval) \
94 LINKER_SECTION_OBJECT(struct scheduler_periodic_work_linker_object, \
95 sched_periodic_work) \
96 __spw_##_fn = {.name = #_fn, \
97 .fn = _fn, \
98 .type = _type, \
99 .interval = _interval, \
100 .prio = _prio}
101
102#define SCHEDULER_PERIODIC_WORK_REGISTER_PER_PERIOD(_fn, _prio) \
103 SCHEDULER_PERIODIC_WORK_REGISTER(_fn, PERIODIC_WORK_PERIOD_BASED, _prio, 1)
104
105void scheduler_periodic_work_init(void);
106void scheduler_periodic_work_execute(enum scheduler_periodic_work_type type);
107
108/* prevent irql_lower work execution recursion */
109bool scheduler_in_periodic_work();
110