-
Notifications
You must be signed in to change notification settings - Fork 0
/
rtsk_task.ks
125 lines (108 loc) · 3.18 KB
/
rtsk_task.ks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
////////////////////////////////////////////////////////////////////////////////
// RTSK TASKS AND SCHEDULING
////////////////////////////////////////////////////////////////////////////////
//
// TASK PRIORITIES
// ## FRAME TIME
// 1 1 0.1 SEC
// 2 2 0.2 SEC
// 3 3 0.3 SEC
// 4 5 0.5 SEC
// 5 11 1.1 SEC
// 6 23 2.3 SEC
// 7 47 4.7 SEC
// 8 89 8.9 SEC
// 9 157 15.7 SEC
// 10 307 30.7 SEC
// 11 601 60.1 SEC (1 MIN)
// 12 1201 120.1 SEC (2 MIN)
// 13 2399 239.9 SEC (4 MIN)
// 14 4801 480.1 SEC (8 MIN)
// 15 9601 960.1 SEC (16 MIN)
// 16 19001 1900.1 SEC (32 MIN)
// 17 9 0.9 SEC ( SPECIAL PRIORITY )
//
//
// LIST OF TASKS
// TASKS ARE ORDERED BY THEIR NEXT EXECUTION TIME
// [0] REMAINING NUMBER OF FRAMES
// [1] TIME AT WHICH TASK WAS ADDED
// [2] INITIAL PRIORITY
// [3] TASK DELEGATE
//
GLOBAL TASK_LIST TO LIST().
// LIST OF TASKS BY THEIR DELEGATES (TO CHECK FOR MULTIPLE TASK SCHEDULING)
GLOBAL TASK_LIST_LOOKUP TO LEXICON().
// INDICATES HOW MANY FRAMES CORRESPOND TO EACH PRIORITY (STARTING FROM 1)
GLOBAL TASK_PRIORITIES TO LIST(1,1,2,3,5,11,23,47,89,157,307,601,1201,2399,4801,9601,19001,9).
// NUMBER OF MINOR FRAMES SINCE OS STARTUP
GLOBAL FRAME TO 0.
// NORMAL MINOR LOOP DURATION
GLOBAL MINOR_LOOP TO 0.100.
// MAXIMUM ALLOWED MINOR LOOP DURATION
GLOBAL MINOR_LOOP_THRESHOLD TO 0.200.
// CPU USAGE (%)
GLOBAL CPU_LOAD TO 0.
// CONSTANT USED TO DETECT TASK INITIALIZATION
GLOBAL INIT TO 0.
////////////////////////////////////////////////////////////////////////////////
//
// SCHEDULE A TASK. FOR EXAMPLE:
// FUNCTION TASK { PARAMETER DT. ... TASK_SCHEDULE(5, TASK@). }
// TASK(INIT).
//
FUNCTION TASK_SCHEDULE {
PARAMETER PRIORITY, NEW_TASK.
// CHECK IF TASK IS ALREADY SCHEDULED
IF TASK_LIST_LOOKUP:HASKEY(NEW_TASK) {
// TASK WAS SCHEDULED, FIND IT AND UPDATE
LOCAL INDEX IS 0.
UNTIL INDEX >= TASK_LIST:LENGTH {
LOCAL TASK IS TASK_LIST[INDEX].
IF TASK[3] = NEW_TASK {
SET TASK[0] TO MIN(TASK[0], TASK_PRIORITIES[PRIORITY]).
BREAK.
}
SET INDEX TO INDEX + 1.
}
} ELSE {
TASK_LIST_LOOKUP:ADD(NEW_TASK, TRUE).
TASK_LIST:ADD(LIST(TASK_PRIORITIES[PRIORITY], TIME:SECONDS, PRIORITY, NEW_TASK)).
}
}
//
// PERFORM A SINGLE MINOR FRAME AND RUN ALL TASKS THAT NEED TO BE RAN
//
FUNCTION TASK_FRAME {
LOCAL FRAME_TIME IS TIME:SECONDS.
// LOOP THROUGH ALL TASKS
LOCAL INDEX IS 0.
UNTIL INDEX >= TASK_LIST:LENGTH {
LOCAL TASK IS TASK_LIST[INDEX].
IF TASK[0] = 0 {
// REMOVE TASK FROM ACTIVE LIST
TASK_LIST:REMOVE(INDEX).
TASK_LIST_LOOKUP:REMOVE(TASK[3]).
// SHOULD RUN THE TASK
TASK[3]:CALL(MAX(0.010, TIME:SECONDS - TASK[1])).
} ELSE {
// TASK DOES NOT HAVE TO BE RAN
SET TASK[0] TO TASK[0] - 1.
SET INDEX TO INDEX + 1.
}
}
// ENSURE CONSTANT MINOR LOOPS
LOCAL ELAPSED_TIME IS TIME:SECONDS - FRAME_TIME.
IF ELAPSED_TIME < MINOR_LOOP {
WAIT MINOR_LOOP - ELAPSED_TIME.
} ELSE {
WAIT 0.001.
IF ELAPSED_TIME > MINOR_LOOP_THRESHOLD {
// FIXME: ERROR
}
}
// CPU USAGE
SET CPU_LOAD TO CPU_LOAD*0.85 + 0.15*(ELAPSED_TIME / MINOR_LOOP).
// MOVE TO THE NEXT FRAME
SET FRAME TO FRAME + 1.
}