Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
FlightOS
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Armin Luntzer
FlightOS
Commits
88c53c0a
Commit
88c53c0a
authored
5 years ago
by
Armin Luntzer
Browse files
Options
Downloads
Patches
Plain Diff
EDF in working condition
parent
0ada692d
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
kernel/sched/edf.c
+43
-866
43 additions, 866 deletions
kernel/sched/edf.c
tools/testing/unittest/edf/edf_test.c
+100
-14
100 additions, 14 deletions
tools/testing/unittest/edf/edf_test.c
with
143 additions
and
880 deletions
kernel/sched/edf.c
+
43
−
866
View file @
88c53c0a
...
@@ -12,7 +12,6 @@
...
@@ -12,7 +12,6 @@
#include
<kernel/tick.h>
#include
<kernel/tick.h>
#if 1
void
sched_print_edf_list_internal
(
struct
task_queue
*
tq
,
ktime
now
)
void
sched_print_edf_list_internal
(
struct
task_queue
*
tq
,
ktime
now
)
{
{
...
@@ -62,13 +61,8 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
...
@@ -62,13 +61,8 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
printk
(
"
\n\n
"
);
printk
(
"
\n\n
"
);
}
}
ktime
total
;
ktime
times
;
void
sched_print_edf_list
(
void
)
{
printk
(
"avg: %lld
\n
"
,
ktime_to_us
(
total
/
times
));
}
#endif
/**
/**
* Our EDF task scheduling timeline:
* Our EDF task scheduling timeline:
*
*
...
@@ -160,443 +154,8 @@ static inline void schedule_edf_reinit_task(struct task_struct *tsk, ktime now)
...
@@ -160,443 +154,8 @@ static inline void schedule_edf_reinit_task(struct task_struct *tsk, ktime now)
tsk
->
runtime
=
tsk
->
attr
.
wcet
;
tsk
->
runtime
=
tsk
->
attr
.
wcet
;
}
}
#if 0
#define SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE 10000000LL
/* stupidly sort EDFs */
/*static*/ int64_t schedule_edf(ktime now)
{
// ktime now;
int64_t delta;
int64_t slot = SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE;
struct task_struct *tsk;
struct task_struct *tmp;
ktime wake;
list_for_each_entry_safe(tsk, tmp, &_kthreads.run, node) {
if (tsk->attr.policy != SCHED_EDF)
continue;
/* time to wake up yet? */
delta = ktime_delta(tsk->wakeup, now);
if (delta >= 0) {
/* nope, just update minimum runtime for this slot */
if (delta < slot)
slot = delta;
continue;
}
/* if it's already running, see if there is time remaining */
if (tsk->state == TASK_RUN) {
if (!schedule_edf_can_execute(tsk, now)) {
schedule_edf_reinit_task(tsk, now);
/* nope, update minimum runtime for this slot */
delta = ktime_delta(tsk->wakeup, now);
if (delta < slot)
slot = delta;
continue;
}
/* move to top */
list_move(&tsk->node, &_kthreads.run);
continue;
}
/* time to wake up */
if (tsk->state == TASK_IDLE) {
tsk->state = TASK_RUN;
/* move to top */
list_move(&tsk->node, &_kthreads.run);
}
}
/* now find the closest relative deadline */
wake = ktime_add(now, slot);
list_for_each_entry_safe(tsk, tmp, &_kthreads.run, node) {
if (tsk->attr.policy != SCHED_EDF)
break;
/* all currently runnable task are at the top of the list */
if (tsk->state != TASK_RUN)
break;
if (ktime_before(wake, tsk->deadline))
continue;
delta = ktime_delta(wake, tsk->deadline);
if (delta < 0) {
delta = ktime_delta(now, tsk->deadline);
printk("\n [%lld] %s deadline violated by %lld us\n", ktime_to_ms(now), tsk->name, ktime_to_us(delta));
}
if (delta < slot) {
if (delta)
slot = delta;
else
delta = tsk->runtime;
wake = ktime_add(now, slot); /* update next wakeup */
/* move to top */
list_move(&tsk->node, &_kthreads.run);
BUG_ON(slot <= 0);
}
}
#if 1
total = ktime_add(total, ktime_delta(ktime_get(), now));
times++;
#endif
#if 0
printk("%3.d %3.lld\n", cnt, ktime_to_us(total / times) );
#endif
BUG_ON(slot < 0);
return slot;
}
#endif
/**
*
* we allow online task admission, so we need to be able to determine
* schedulability on the fly:
*
* EDF schedulability
*
*
* # comp time
* | deadline (== unused slot)
* _ unused slot
* > wakeup (== deadline if D == P)
* o free slots (deadline - wcet)
*
* simplest case: one long period task, one or more short period tasks
*
* W D W
* >oooooooooo##########|_____________________________> (P=50, D=20, R=10) (T1)
* >o#|_> (P= 4, D= 2, R= 1) (T2)
* >o#> (P= 2, D= 2, R= 1) (T3)
* >#> (P= 1, D= 1, R= 1) (T4)
* >ooooooo#####|_______> (P=20, D=12, R= 5) (T5)
* >oooooooooooooooooooooooooo####|__> (P=33, D=30, R= 4) (T6)
* >oooooooooooooooooooooooooooooooooooooooo######|___> (P=50, D=46, R= 6) (T7)
*
* If we map the short period task into the long period tasks "free" slots,
* we see that tasks with periods shorter than the deadline of the task
* of the longest period can only be scheduled, if their utilisation
* or "time density" R / D is smaller that the utilisation of the longest
* period task
*
*
* easily schedulable:
* ____________________________________________________________________________________________________
* .... . .. ......... . . . . . . ..... . ... ....... . . . . . . .
* >o###oooooo#oo####o##|_____________________________###oooooo##oo##o###o|_____________________________
* >#o|_o#|_o#|_#o|_o#|_#o|_o#|_o#|_#o|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_o#|_
*
*
* R/D R/P
* T1: (P=50, D=20, R=10) 10/20 = 1/2 10/50 = 20/100
* T2: (P= 4, D= 2, R= 1) 1/2 = 1/2 100% 1/4 = 25/100 45% (== number of used slots)
*
*
* correct analysis sum(R_i/P_i)
*
* T1 (D-R) / D = 1/2
* T1 (D-R) / P = 1/5
*
* T2 (D-R) / P = 1/4 T1DRD > T2DRP -> R/P (correct)
*
*
*
* just schedulable:
* ____________________________________________________________________________________________________
* .................... . . . . . . . . . . . . . . ..................... . . . . . . . . . . . . . . .
* >#o#o#o#o#o#o#o#o#o#o|_____________________________#o#o#o#o#o#o#o#o#o#o|_____________________________
* >o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#o#
*
* R/D R/P
* T1: (P=50, D=20, R=10) 10/20 = 1/2 10/50 = 2/10
* T3: (P= 2, D= 2, R= 1) 1/2 = 1/2 100% 1/2 = 5/10 70% (== number of used slots)
*
* -> this must be 100%, impossible to fit more slots into relative deadline of
* long task
*
* correct analysis sum(R_i/D_i)
*
* T1 (D-R) / D = 1/2
* T1 (D-R) / P = 1/5
*
* T3 (D-R) / P = 1/2 T1DRD <= T3DRP -> R/D (correct)
*
* not schedulable:
* ____________________________________________________________________________________________________
* ..........::::::::::........................................::::::::::..............................
* >oooooooooo##########|_____________________________oooooooooo##########|_____________________________
* >####################################################################################################
*
* R/D R/P
* T1: (P=50, D=20, R=10) 10/20 = 1/2 10/50 = 1/5
* T4: (P= 1, D= 1, R= 1) 1/1 = 1/1 150% 1/1 = 1/1 120%
*
* both correct, but R/P "more correct" -> actual slot usage
*
* T1 (D-R) / D = 1/2
* T1 (D-R) / P = 1/5
*
* T4 (D-R) / P = 0 T1DRD > T4DRD -> R/P (correct)
*
*
* schedulable:
*
* ____________________________________________________________________________________________________
* .................................................................................................xxx
* >o###oooooo#oo###o###|_____________________________##o###o#ooooooo###o#|_____________________________
* >#o|_#o|_o#|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_
* >ooooo####oo#|_______o###oooooo##|_______o#ooo###o#oo|_______o###oooooo##|_______o###oooooo##|_______
* >ooooooooooooooooooooooooo###o#|__ooooooooo##ooppoooooooooo##ooo|__ooooooooooooooooooo###o#oooooo|__x
* >ooooooooooooooooooooooooooooooooo###o###oooooo|___ooooooooooooooooooooooo###o###ooooooooooooo###|___
*
* R/D R/P
* T1: (P=50, D=20, R=10) 10/20 50% 10/50 20%
* T2: (P= 4, D= 2, R= 1) 1/2 100% 1/4 45%
* T5: (P=20, D=12, R= 5) 5/12 142% 5/20 70%
* T6: (P=33, D=30, R= 4) 4/30 155% 4/33 82%
* T7: (P=50, D=46, R= 6) 6/46 168% 6/50 94%
*
*
*
* sum(R_i/P_i) correct, sum(R_i/D_i) absolutely incorrect!
*
* thread(p_max):
* T1 (D-R) / D = 1/2
* T1 (D-R) / P = 1/5
* ------------------
* T2 (D-R) / P = 1/4 T1DRD > T2DRP -> R/P (correct)
* T5 (D-R) / P = 7/20 T1DRD > T5DRP -> R/P (correct)
* T6 (D-R) / P = 26/33 T1RD <= T6DRP -> R/D (correct? looks ok)
* T7 (D-R) / P = 40/50 T1RD <= T6DRP -> R/D (correct? looks ok)
*
* usage: 96.4%
*
*
*
*
*
* try 1:
*
* T1: (P=50, D=20, R=10) (20%) T1DRP = 0.2 (0.95)
* TX: (P=10, D= 8, R=6) -> (D-R)/P = 0.2 T1DRD > T2DRP -> R/P (incorrect, should be R/D at least) (0.75)
* ................::..
* >##oooooo####oooo####|_____________________________
* >oo######|_oo######|_
*
* 22/20 slots used = 110%
*
* free T1 slots before deadline: D-R = 10
*
* TX runtime slots cannot be larger than that!
*
* TX runtime slots for T1 deadline periods:
*
*
* (D_x - R_x) / D_x * D_1 = 12.5 < 10 -> not schedulable
*
* sum((D_i - R_i) / D_i) * D_1 < 10 -> schedulable?
*
*
*
* i != D_1 && P_i < D_1
* sum((D_1 / P_i) * R_i) < (D_1 - R_1) ?
*
* i != D1 && P_i >
*
* (T1: 4 < 10 ok)
*
* T2: 5
* T5: 5
* T6 2.42
*
*
*
*
* new test:
*
* if (P_x < D_1) :
* if ((R_x - D_x) > 0) // otherwise we are at 100% slot usage within deadline
* (D_x - R_x) / D_x * (D_1 - R_1) = 12.5 > (D_1 - R_1) -> not schedulable
* else ?
* R_x / P_x * D_1 < (D_1 - R_1)
*
* (schedulable):
* ____________________________________________________________________________________________________
* .................................................................................................xxx
* >o###oooooo#oo###o###|_____________________________##o###o#ooooooo###o#|_____________________________
* >#o|_#o|_o#|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_
* >ooooo####oo#|_______o###oooooo##|_______o#ooo###o#oo|_______o###oooooo##|_______o###oooooo##|_______
* >ooooooooooooooooooooooooo###o#|__ooooooooo##ooppoooooooooo##ooo|__ooooooooooooooooooo###o#oooooo|__x
* >ooooooooooooooooooooooooooooooooo###o###oooooo|___ooooooooooooooooooooooo###o###oooooooooooooooo|___
*
*
* T1: (P=50, D=20, R=10) -> max P -> D_1 = 20, D_1 - R_1 = 10 = F_1
*
* T2: (P= 4, D= 2, R= 1) F2 = 1 F2D = 1/2
* T5: (P=20, D=12, R= 5) F5 = 7 F5D = 7/12
* T6: (P=33, D=30, R= 4) F6 = 26 F6D = 26/30
* T7: (P=50, D=46, R= 6) F7 = 40 F7D = 40/46
*
*
* Utilisation: U1 = D_1 - R_1 = 10; U2 = P_1 - D_1 = 30
*
* check T2:
* f2 > 0 -> f2d * F1 = 5 <= U1 -> schedulable
* f2d * U2 = 10
* -> U1 = 5, U2 = 20
*
* check t5:
* f5 > 0 -> int(f5d * F1) = 5; 5 <= U1 -> schedulable
* f5d * U2 = int(11) ->
* U1 = 0, U2 = 9
*
*
* 1) determine task with longest period
*
* T1: (P=50, D=20, R=10)
*
* 2) calculate unused head and tail (before and after deadline)
*
* UH = D1 - R1 (= 20) (Hyperperiod)
* UT = P1 - D1 (= 60)
*
* 3) loop over other tasks (Period < Deadline of Task 1)
*
* calculate slots usage before deadline of Task 1:
*
* H * Ri * D1 / Pi (T2: 10, T5: 10)
*
* update head slots UH = UH - 20 = 0 -> all used
*
*
* calculate slot usage after deadline of Task2:
*
* H * Ri * F1 / Pi (T2: 15, T5: 15)
*
* update tail slots: UT = UT - 30 = 30
*
* -> need hyperperiod factor H = 2
*
*
*
* if (DEADLINE >
* ____________________________________________________________________________________________________
* ......................... . ............ .............. ......................... . ... .
* >o###oooooo#oo###o###|_____________________________##o###o#ooooooo###o#|_____________________________
* >#o|_#o|_o#|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_#o|_
* >ooooo####oo#|_______o###oooooo##|_______o#ooo###o#oo|_______o###oooooo##|_______o###oooooo##|_______
* >ooooooooooooooooooooooooooooooooo###o###oooooo|___ooooooooooooooooooooooo###o###oooooooooooooooo|___
*
*
*
*/
static
ktime
edf_hyperperiod
(
struct
task_queue
*
tq
)
{
ktime
lcm
=
0
;
ktime
a
,
b
;
struct
task_struct
*
t0
;
struct
task_struct
*
tsk
;
struct
task_struct
*
tmp
;
if
(
list_empty
(
&
tq
->
new
))
return
0
;
t0
=
list_entry
(
tq
->
new
.
next
,
struct
task_struct
,
node
);
lcm
=
t0
->
attr
.
period
;
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
new
,
node
)
{
if
(
tsk
==
t0
)
continue
;
a
=
lcm
;
b
=
tsk
->
attr
.
period
;
/* already a multiple? */
if
(
a
%
b
==
0
)
continue
;
while
(
a
!=
b
)
{
if
(
a
>
b
)
a
-=
b
;
else
b
-=
a
;
}
lcm
=
lcm
*
(
tsk
->
attr
.
period
/
a
);
}
/* argh, need to consider everything */
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
a
=
lcm
;
b
=
tsk
->
attr
.
period
;
/* already a multiple? */
if
(
a
%
b
==
0
)
continue
;
while
(
a
!=
b
)
{
if
(
a
>
b
)
a
-=
b
;
else
b
-=
a
;
}
lcm
=
lcm
*
(
tsk
->
attr
.
period
/
a
);
}
/* meh ... */
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
wake
,
node
)
{
a
=
lcm
;
b
=
tsk
->
attr
.
period
;
/* already a multiple? */
if
(
a
%
b
==
0
)
continue
;
while
(
a
!=
b
)
{
if
(
a
>
b
)
a
-=
b
;
else
b
-=
a
;
}
lcm
=
lcm
*
(
tsk
->
attr
.
period
/
a
);
}
return
lcm
;
}
/**** NEW EDF ****/
#include
<kernel/init.h>
#include
<kernel/init.h>
#define MSG "SCHED_EDF: "
#define MSG "SCHED_EDF: "
...
@@ -638,145 +197,17 @@ static ktime edf_hyperperiod(struct task_queue *tq)
...
@@ -638,145 +197,17 @@ static ktime edf_hyperperiod(struct task_queue *tq)
static
int
edf_schedulable
(
struct
task_queue
*
tq
,
const
struct
task_struct
*
task
)
static
int
edf_schedulable
(
struct
task_queue
*
tq
,
const
struct
task_struct
*
task
)
{
{
ktime
p
=
edf_hyperperiod
(
tq
);
ktime
h
;
ktime
max
=
0
;
ktime
uh
,
ut
,
f1
;
ktime
sh
=
0
,
st
=
0
;
ktime
stmin
=
0x7fffffffffffffULL
;
ktime
shmin
=
0x7fffffffffffffULL
;
struct
task_struct
*
t0
=
NULL
;
struct
task_struct
*
tsk
=
NULL
;
struct
task_struct
*
tsk
=
NULL
;
struct
task_struct
*
tmp
;
struct
task_struct
*
tmp
;
double
u
=
0
.
0
;
/* utilisation */
double
u
=
0
.
0
;
/* utilisation */
static
int64_t
dmin
=
0x7fffffffffffffLL
;
// printk("\nvvvv EDF analysis vvvv (%lld us) \n\n", ktime_to_us(p));
/* list_empty(....) */
if
(
p
<=
0
)
printk
(
"appears to be empty
\n
"
);
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
new
,
node
)
{
if
(
tsk
->
attr
.
period
>
max
)
{
t0
=
tsk
;
max
=
tsk
->
attr
.
period
;
}
if
(
dmin
>
tsk
->
attr
.
deadline_rel
)
dmin
=
tsk
->
attr
.
deadline_rel
;
}
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
wake
,
node
)
{
if
(
tsk
->
attr
.
period
>
max
)
{
t0
=
tsk
;
max
=
tsk
->
attr
.
period
;
}
if
(
dmin
>
tsk
->
attr
.
deadline_rel
)
dmin
=
tsk
->
attr
.
deadline_rel
;
}
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
if
(
tsk
->
attr
.
period
>
max
)
{
t0
=
tsk
;
max
=
tsk
->
attr
.
period
;
}
if
(
dmin
>
tsk
->
attr
.
deadline_rel
)
dmin
=
tsk
->
attr
.
deadline_rel
;
}
BUG_ON
(
!
t0
);
BUG_ON
(
p
<
t0
->
attr
.
period
);
h
=
p
/
t0
->
attr
.
period
;
printk
(
"Period factor %lld, duration %lld actual period: %lld
\n
"
,
h
,
ktime_to_us
(
p
),
ktime_to_us
(
t0
->
attr
.
period
));
uh
=
h
*
(
t0
->
attr
.
deadline_rel
-
t0
->
attr
.
wcet
);
ut
=
h
*
(
t0
->
attr
.
period
-
t0
->
attr
.
deadline_rel
);
f1
=
ut
/
h
;
printk
(
"max UH: %lld, UT: %lld
\n
"
,
ktime_to_us
(
uh
),
ktime_to_us
(
ut
));
/* subtract longest period thread from head, its slices must always
* be used before the deadline
*/
sh
=
h
*
t0
->
attr
.
wcet
*
t0
->
attr
.
deadline_rel
/
t0
->
attr
.
period
;
if
(
sh
<
shmin
)
shmin
=
sh
;
uh
=
uh
-
sh
;
printk
(
"%s UH: %lld, UT: %lld
\n
"
,
t0
->
name
,
ktime_to_us
(
uh
),
ktime_to_us
(
ut
));
printk
(
"%s SH: %lld, ST: %lld
\n
"
,
t0
->
name
,
ktime_to_us
(
sh
),
ktime_to_us
(
st
));
/* add all in new */
/* add all in new */
if
(
!
list_empty
(
&
tq
->
new
))
{
if
(
!
list_empty
(
&
tq
->
new
))
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
new
,
node
)
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
new
,
node
)
if
(
tsk
==
t0
)
continue
;
if
(
tsk
->
attr
.
policy
!=
SCHED_EDF
)
continue
;
u
+=
(
double
)
(
int32_t
)
tsk
->
attr
.
wcet
/
(
double
)
(
int32_t
)
tsk
->
attr
.
period
;
u
+=
(
double
)
(
int32_t
)
tsk
->
attr
.
wcet
/
(
double
)
(
int32_t
)
tsk
->
attr
.
period
;
if
(
tsk
->
attr
.
deadline_rel
<=
t0
->
attr
.
deadline_rel
)
{
/* slots before deadline of T0 */
sh
=
h
*
tsk
->
attr
.
wcet
*
t0
->
attr
.
deadline_rel
/
tsk
->
attr
.
period
;
if
(
sh
<
shmin
)
shmin
=
sh
;
#if 0
if (sh > uh) {
printk("NOT SCHEDULABLE in head: %s\n", tsk->name);
BUG();
}
#endif
uh
=
uh
-
sh
;
}
/* slots after deadline of T0 */
st
=
h
*
tsk
->
attr
.
wcet
*
f1
/
tsk
->
attr
.
period
;
if
(
st
<
stmin
)
stmin
=
st
;
// printk("%s tail usage: %lld\n", tsk->name, ktime_to_ms(st));
#if 0
if (st > ut) {
printk("NOT SCHEDULABLE in tail: %s\n", tsk->name);
BUG();
}
#endif
ut
=
ut
-
st
;
printk
(
"w %s UH: %lld, UT: %lld
\n
"
,
tsk
->
name
,
ktime_to_us
(
uh
),
ktime_to_us
(
ut
));
printk
(
"w %s SH: %lld, ST: %lld
\n
"
,
tsk
->
name
,
ktime_to_us
(
sh
),
ktime_to_us
(
st
));
}
}
}
...
@@ -784,204 +215,35 @@ static int edf_schedulable(struct task_queue *tq, const struct task_struct *task
...
@@ -784,204 +215,35 @@ static int edf_schedulable(struct task_queue *tq, const struct task_struct *task
/* add all in wakeup */
/* add all in wakeup */
struct
task_struct
*
tmp2
;
struct
task_struct
*
tmp2
;
if
(
!
list_empty
(
&
tq
->
wake
))
{
if
(
!
list_empty
(
&
tq
->
wake
))
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
wake
,
node
)
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
wake
,
node
)
if
(
tsk
==
t0
)
continue
;
if
(
tsk
->
attr
.
policy
!=
SCHED_EDF
)
continue
;
u
+=
(
double
)
(
int32_t
)
tsk
->
attr
.
wcet
/
(
double
)
(
int32_t
)
tsk
->
attr
.
period
;
u
+=
(
double
)
(
int32_t
)
tsk
->
attr
.
wcet
/
(
double
)
(
int32_t
)
tsk
->
attr
.
period
;
if
(
tsk
->
attr
.
deadline_rel
<=
t0
->
attr
.
deadline_rel
)
{
/* slots before deadline of T0 */
sh
=
h
*
tsk
->
attr
.
wcet
*
t0
->
attr
.
deadline_rel
/
tsk
->
attr
.
period
;
if
(
sh
<
shmin
)
shmin
=
sh
;
#if 0
if (sh > uh) {
printk("NOT SCHEDULABLE in head: %s\n", tsk->name);
BUG();
}
#endif
uh
=
uh
-
sh
;
}
/* slots after deadline of T0 */
st
=
h
*
tsk
->
attr
.
wcet
*
f1
/
tsk
->
attr
.
period
;
if
(
st
<
stmin
)
stmin
=
st
;
// printk("%s tail usage: %lld\n", tsk->name, ktime_to_ms(st));
#if 0
if (st > ut) {
printk("NOT SCHEDULABLE in tail: %s\n", tsk->name);
BUG();
}
#endif
ut
=
ut
-
st
;
printk
(
"w %s UH: %lld, UT: %lld
\n
"
,
tsk
->
name
,
ktime_to_us
(
uh
),
ktime_to_us
(
ut
));
printk
(
"w %s SH: %lld, ST: %lld
\n
"
,
tsk
->
name
,
ktime_to_us
(
sh
),
ktime_to_us
(
st
));
}
}
}
/* add all running */
/* add all running */
if
(
!
list_empty
(
&
tq
->
run
))
{
if
(
!
list_empty
(
&
tq
->
run
))
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
if
(
tsk
==
t0
)
continue
;
if
(
tsk
->
attr
.
policy
!=
SCHED_EDF
)
continue
;
u
+=
(
double
)
(
int32_t
)
tsk
->
attr
.
wcet
/
(
double
)
(
int32_t
)
tsk
->
attr
.
period
;
u
+=
(
double
)
(
int32_t
)
tsk
->
attr
.
wcet
/
(
double
)
(
int32_t
)
tsk
->
attr
.
period
;
if
(
tsk
->
attr
.
deadline_rel
<=
t0
->
attr
.
deadline_rel
)
{
/* slots before deadline of T0 */
sh
=
h
*
tsk
->
attr
.
wcet
*
t0
->
attr
.
deadline_rel
/
tsk
->
attr
.
period
;
if
(
sh
<
shmin
)
shmin
=
sh
;
#if 0
if (sh > uh) {
printk("NOT SCHEDULABLE in head: %s\n", tsk->name);
BUG();
}
#endif
uh
=
uh
-
sh
;
}
}
/* slots after deadline of T0 */
st
=
h
*
tsk
->
attr
.
wcet
*
f1
/
tsk
->
attr
.
period
;
if
(
st
<
stmin
)
stmin
=
st
;
// printk("%s tail usage: %lld\n", tsk->name, ktime_to_ms(st));
//
#if 0
if (st > ut) {
printk("NOT SCHEDULABLE in tail: %s\n", tsk->name);
BUG();
}
#endif
ut
=
ut
-
st
;
printk
(
"r UH: %lld, UT: %lld
\n
"
,
ktime_to_us
(
uh
),
ktime_to_us
(
ut
));
printk
(
"r SH: %lld, ST: %lld
\n
"
,
ktime_to_us
(
sh
),
ktime_to_us
(
st
));
}
}
printk
(
"r SH: %lld (%lld), ST: %lld (%lld)
\n
"
,
ktime_to_us
(
uh
/
h
),
uh
,
ktime_to_us
(
ut
/
h
),
ut
);
if
(
ut
<=
0
)
{
printk
(
"NOT SCHEDULABLE in tail: %s %lld
\n
"
,
task
->
name
,
ut
);
BUG
();
}
if
(
uh
<=
0
)
{
printk
(
"NOT SCHEDULABLE in head: %s %lld
\n
"
,
task
->
name
,
uh
);
BUG
();
}
static
int
cnt
;
if
(
cnt
)
{
#if 1
if
(
ut
<=
stmin
)
{
printk
(
"xx NOT SCHEDULABLE in tail: %s %lld vs %lld
\n
"
,
task
->
name
,
ut
,
stmin
);
// BUG();
}
#endif
#if 0
if (uh <= shmin) {
printk("xx NOT SCHEDULABLE in head: %s %lld vs %lld \n", task->name, uh, shmin);
// BUG();
}
#endif
}
cnt
++
;
#if 0
//list_for_each_entry_safe(tsk, tmp, &tq->new, node)
{
tsk = t0;
ktime sh, st;
// if (tsk == t0)
// continue;
if (tsk->attr.deadline_rel < t0->attr.deadline_rel) {
/* slots before deadline of T0 */
sh = h * tsk->attr.wcet * t0->attr.deadline_rel / tsk->attr.period;
if (sh > uh) {
printk("NOT SCHEDULABLE in head: %s\n", tsk->name);
BUG();
}
uh = uh - sh;
}
/* slots after deadline of T0 */
st = h * tsk->attr.wcet * f1 / tsk->attr.period;
// printk("%s tail usage: %lld\n", tsk->name, ktime_to_ms(st));
if (st > ut) {
printk("NOT SCHEDULABLE in tail: %s\n", tsk->name);
BUG();
}
ut = ut - st;
printk("UH: %lld, UT: %lld\n", ktime_to_us(uh), ktime_to_us(ut));
printk("SH: %lld, ST: %lld\n", ktime_to_us(sh), ktime_to_us(st));
if (dmin > task->attr.deadline_rel)
dmin = task->attr.deadline_rel;
u += (double) (int32_t) task->attr.wcet / (double) (int32_t) task->attr.period;
#endif
if
(
u
>
1
.
0
)
{
if
(
u
>
1
.
0
)
{
printk
(
"I am NOT schedul-ableh: %f "
,
u
);
printk
(
"I am NOT schedul-ableh: %f "
,
u
);
BUG
();
return
-
EINVAL
;
return
-
EINVAL
;
printk
(
"changed task mode to RR
\n
"
,
u
);
printk
(
"changed task mode to RR
\n
"
,
u
);
}
else
{
}
else
{
printk
(
"Utilisation: %g
\n
"
,
u
);
printk
(
"Utilisation: %g
\n
"
,
u
);
return
0
;
return
0
;
}
}
// }
u
=
(
double
)
(
int32_t
)
task
->
attr
.
wcet
/
(
double
)
(
int32_t
)
task
->
attr
.
period
;
u
=
(
double
)
(
int32_t
)
task
->
attr
.
wcet
/
(
double
)
(
int32_t
)
task
->
attr
.
period
;
// printk("was the first task, utilisation: %g\n", u);
return
0
;
return
0
;
}
}
...
@@ -1007,18 +269,16 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
...
@@ -1007,18 +269,16 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
// printk("checking %s\n", tsk->name);
/* time to wake up yet? */
/* time to wake up yet? */
delta
=
ktime_delta
(
tsk
->
wakeup
,
now
);
delta
=
ktime_delta
(
tsk
->
wakeup
,
now
);
if
(
delta
>
0
)
{
if
(
delta
>
0
)
{
/* nope,
just update minimum runtime for this slot
*/
/* nope,
optionally adjust slice
*/
if
(
delta
<
slot
)
if
(
delta
<
slot
)
slot
=
delta
;
slot
=
delta
;
continue
;
continue
;
}
}
...
@@ -1028,39 +288,34 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
...
@@ -1028,39 +288,34 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
if
(
!
schedule_edf_can_execute
(
tsk
,
now
))
{
if
(
!
schedule_edf_can_execute
(
tsk
,
now
))
{
schedule_edf_reinit_task
(
tsk
,
now
);
schedule_edf_reinit_task
(
tsk
,
now
);
/* nope, update minimum runtime for this slot */
delta
=
ktime_delta
(
tsk
->
wakeup
,
now
);
delta
=
ktime_delta
(
tsk
->
wakeup
,
now
);
/* if wakeup must happen earlier than the next
/* if wakeup must happen earlier than the next
* scheduling event, adjust the sl
ot timeout
* scheduling event, adjust the sl
ice
*/
*/
if
(
delta
<
slot
)
if
(
delta
<
slot
)
slot
=
delta
;
slot
=
delta
;
BUG_ON
(
delta
<
0
);
BUG_ON
(
delta
<
0
);
/* always queue it up at the tail */
list_move_tail
(
&
tsk
->
node
,
&
tq
->
run
);
list_move_tail
(
&
tsk
->
node
,
&
tq
->
run
);
// continue;
}
}
// if (tsk->runtime < tsk->attr.wcet)
/* if our deadline is earlier than the deadline of the
// printk("VVV %s %lld %lld\n", tsk->name, tsk->runtime, tsk->attr.wcet);
* head of the list, we become the new head
*/
/* if our deadline is earlier than the deadline at the
* head of the list, move us to top */
first
=
list_first_entry
(
&
tq
->
run
,
struct
task_struct
,
node
);
first
=
list_first_entry
(
&
tq
->
run
,
struct
task_struct
,
node
);
if
(
ktime_before
(
tsk
->
wakeup
,
now
))
{
if
(
ktime_before
(
tsk
->
wakeup
,
now
))
{
if
(
ktime_before
(
tsk
->
deadline
-
tsk
->
runtime
,
first
->
deadline
))
{
if
(
ktime_before
(
tsk
->
deadline
-
tsk
->
runtime
,
first
->
deadline
))
{
tsk
->
state
=
TASK_RUN
;
tsk
->
state
=
TASK_RUN
;
// go = tsk;
list_move
(
&
tsk
->
node
,
&
tq
->
run
);
list_move
(
&
tsk
->
node
,
&
tq
->
run
);
// printk("1 to top! %s\n", tsk->name);
}
}
}
}
// printk("1 nope %s\n", tsk->name);
continue
;
continue
;
}
}
...
@@ -1068,23 +323,14 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
...
@@ -1068,23 +323,14 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
/* time to wake up */
/* time to wake up */
if
(
tsk
->
state
==
TASK_IDLE
)
{
if
(
tsk
->
state
==
TASK_IDLE
)
{
tsk
->
state
=
TASK_RUN
;
tsk
->
state
=
TASK_RUN
;
/* move to top */
// printk("%s now in state RUN\n", tsk->name);
/* if our deadline is earlier than the deadline at the
/* if our deadline is earlier than the deadline at the
* head of the list, move us to top */
* head of the list, move us to top */
first
=
list_first_entry
(
&
tq
->
run
,
struct
task_struct
,
node
);
first
=
list_first_entry
(
&
tq
->
run
,
struct
task_struct
,
node
);
//if (ktime_before (tsk->deadline, first->deadline)) {
if
(
ktime_before
(
tsk
->
deadline
-
tsk
->
runtime
,
first
->
deadline
))
if
(
ktime_before
(
tsk
->
deadline
-
tsk
->
runtime
,
first
->
deadline
))
{
// go = tsk;
list_move
(
&
tsk
->
node
,
&
tq
->
run
);
list_move
(
&
tsk
->
node
,
&
tq
->
run
);
// printk("%s has earlier deadline, moved to top\n", tsk->name);
}
// printk("2 nope %s\n", tsk->name);
continue
;
continue
;
}
}
...
@@ -1093,13 +339,14 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
...
@@ -1093,13 +339,14 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
first
=
list_first_entry
(
&
tq
->
run
,
struct
task_struct
,
node
);
first
=
list_first_entry
(
&
tq
->
run
,
struct
task_struct
,
node
);
delta
=
ktime_delta
(
first
->
wakeup
,
now
);
delta
=
ktime_delta
(
first
->
wakeup
,
now
);
// if (delta <= 0)
if
(
first
->
state
==
TASK_RUN
)
{
if
(
first
->
state
==
TASK_RUN
)
{
go
=
first
;
go
=
first
;
slot
=
first
->
runtime
;
slot
=
first
->
runtime
;
}
}
#if
1
#if
0 /* XXX should not be needed, but needs verification! */
if (!go) {
if (!go) {
list_for_each_entry_safe(tsk, tmp, &tq->run, node) {
list_for_each_entry_safe(tsk, tmp, &tq->run, node) {
...
@@ -1115,65 +362,42 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
...
@@ -1115,65 +362,42 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
}
}
}
}
#endif
#endif
// if (!go)
// printk("NULL\n");
// printk("in %llu\n", ktime_to_ms(slot));
#if 0
/** XXX **/
tsk = list_entry(tq->run.next, struct task_struct, node);
if (tsk->state == TASK_RUN)
return tsk;
else
#endif
return
go
;
return
go
;
}
}
static
void
edf_wake_next
(
struct
task_queue
*
tq
)
static
void
edf_wake_next
(
struct
task_queue
*
tq
)
{
{
struct
task_struct
*
tsk
;
ktime
last
;
struct
task_struct
*
tmp
;
struct
task_struct
*
tmp
;
struct
task_struct
*
task
;
struct
task_struct
*
task
;
struct
task_struct
*
l
;
ktime
last
=
0
;
ktime
per
=
0
;
ktime
wcet
=
0
;
if
(
list_empty
(
&
tq
->
wake
))
if
(
list_empty
(
&
tq
->
wake
))
return
;
return
;
task
=
list_entry
(
tq
->
wake
.
next
,
struct
task_struct
,
node
);
last
=
ktime_get
();
last
=
ktime_get
();
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
list_for_each_entry_safe
(
task
,
tmp
,
&
tq
->
run
,
node
)
{
if
(
tsk
->
deadline
>
last
)
{
if
(
last
<
task
->
deadline
)
last
=
tsk
->
deadline
;
last
=
task
->
deadline
;
l
=
tsk
;
}
}
}
// if (next->attr.policy == SCHED_EDF)
task
=
list_entry
(
tq
->
wake
.
next
,
struct
task_struct
,
node
);
// return;
//
task
->
state
=
TASK_IDLE
;
/* initially furthest deadline as wakeup */
task
->
wakeup
=
l
->
deadline
,
task
->
attr
.
period
;
// task->wakeup = ktime_add(l->deadline, task->attr.period);
/* add overhead */
// task->wakeup = ktime_add(task->wakeup, 50000UL);
#if 0
task->wakeup = ktime_add(task->wakeup, per);
#endif
/* initially furthest deadline as wakeup */
task
->
wakeup
=
ktime_add
(
last
,
task
->
attr
.
period
);
task
->
deadline
=
ktime_add
(
task
->
wakeup
,
task
->
attr
.
deadline_rel
);
task
->
deadline
=
ktime_add
(
task
->
wakeup
,
task
->
attr
.
deadline_rel
);
/* XXX unneeded, remove */
task
->
first_wake
=
task
->
wakeup
;
task
->
first_wake
=
task
->
wakeup
;
task
->
first_dead
=
task
->
deadline
;
task
->
first_dead
=
task
->
deadline
;
task
->
state
=
TASK_IDLE
;
// printk("---- %s %llu\n", task->name, task->first_wake);
list_move_tail
(
&
task
->
node
,
&
tq
->
run
);
list_move_tail
(
&
task
->
node
,
&
tq
->
run
);
}
}
...
@@ -1268,75 +492,28 @@ ktime edf_task_ready_ns(struct task_queue *tq)
...
@@ -1268,75 +492,28 @@ ktime edf_task_ready_ns(struct task_queue *tq)
{
{
int64_t
delta
;
int64_t
delta
;
struct
task_struct
*
tsk
;
struct
task_struct
*
tsk
;
struct
task_struct
*
tmp
;
struct
task_struct
*
tmp
;
ktime
now
=
ktime_get
();
ktime
wake
=
123456789123LL
;
ktime
wake
=
123456789123LL
;
ktime
now
=
ktime_get
();
// wake = ktime_add(now, slot);
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
list_for_each_entry_safe
(
tsk
,
tmp
,
&
tq
->
run
,
node
)
{
#if 0
if (tsk->state == TASK_IDLE)
continue;
#endif
delta
=
ktime_delta
(
tsk
->
wakeup
,
now
);
delta
=
ktime_delta
(
tsk
->
wakeup
,
now
);
if
(
delta
<=
0
)
if
(
delta
<=
0
)
continue
;
continue
;
if
(
wake
>
delta
)
{
if
(
wake
>
delta
)
wake
=
delta
;
wake
=
delta
;
printk
(
"delta for %s is %lld because now: %lld wake %lld
\n
"
,
tsk
->
name
,
ktime_to_us
(
delta
),
ktime_to_us
(
now
),
ktime_to_us
(
tsk
->
wakeup
));
}
}
if
(
slot
>
wake
)
#if 0
/* all currently runnable task are at the top of the list */
if (tsk->state != TASK_RUN)
break;
#endif
#if 0
if (ktime_before(wake, tsk->wakeup))
continue;
delta = ktime_delta(wake, tsk->wakeup);
if (delta < 0) {
delta = ktime_delta(now, tsk->wakeup);
printk("\n [%lld] %s wakeup violated by %lld us\n", ktime_to_ms(now), tsk->name, ktime_to_us(delta));
}
if (delta < slot) {
if (delta)
slot = delta;
else
delta = tsk->runtime;
// wake = ktime_add(now, slot); /* update next wakeup */
/* move to top */
// list_move(&tsk->node, &tq->run);
BUG_ON(slot <= 0);
}
#endif
}
/* subtract call overhead */
// slot = wake;
//slot = ktime_sub(slot, 10000ULL);
//slot = ktime_sub(slot, 2000ULL);
//
if
(
slot
>
wake
)
{
printk
(
"
\n
vvvvvvvvvvvvvvv
\n
"
);
printk
(
"Slice adjusted from %lld to %lld (%lld)
\n
"
,
ktime_to_us
(
slot
),
ktime_to_us
(
wake
),
ktime_to_us
(
wake
-
slot
));
printk
(
"
\n
^^^^^^^^^^^^^^^
\n
"
);
slot
=
wake
;
slot
=
wake
;
}
BUG_ON
(
slot
<=
0
);
BUG_ON
(
slot
<=
0
);
return
slot
;
return
slot
;
...
...
This diff is collapsed.
Click to expand it.
tools/testing/unittest/edf/edf_test.c
+
100
−
14
View file @
88c53c0a
...
@@ -59,7 +59,7 @@ static void sched_edf_create_tasks_test(void)
...
@@ -59,7 +59,7 @@ static void sched_edf_create_tasks_test(void)
struct
task_struct
*
t
;
struct
task_struct
*
t
;
struct
sched_attr
attr
;
struct
sched_attr
attr
;
#if 0
/* create task 1 */
/* create task 1 */
t = kmalloc(sizeof(struct task_struct));
t = kmalloc(sizeof(struct task_struct));
KSFT_ASSERT_PTR_NOT_NULL(t);
KSFT_ASSERT_PTR_NOT_NULL(t);
...
@@ -73,7 +73,7 @@ static void sched_edf_create_tasks_test(void)
...
@@ -73,7 +73,7 @@ static void sched_edf_create_tasks_test(void)
t->attr.policy = SCHED_EDF;
t->attr.policy = SCHED_EDF;
t->attr.period = us_to_ktime(1000);
t->attr.period = us_to_ktime(1000);
t->attr.deadline_rel = us_to_ktime(900);
t->attr.deadline_rel = us_to_ktime(900);
t
->
attr
.
wcet
=
us_to_ktime
(
25
5
);
t->attr.wcet = us_to_ktime(25
0
);
edf_enqueue(&t->sched->tq, t);
edf_enqueue(&t->sched->tq, t);
...
@@ -90,7 +90,7 @@ static void sched_edf_create_tasks_test(void)
...
@@ -90,7 +90,7 @@ static void sched_edf_create_tasks_test(void)
t->attr.policy = SCHED_EDF;
t->attr.policy = SCHED_EDF;
t->attr.period = us_to_ktime(800);
t->attr.period = us_to_ktime(800);
t->attr.deadline_rel = us_to_ktime(700);
t->attr.deadline_rel = us_to_ktime(700);
t
->
attr
.
wcet
=
us_to_ktime
(
8
9
);
t->attr.wcet = us_to_ktime(9
0
);
edf_enqueue(&t->sched->tq, t);
edf_enqueue(&t->sched->tq, t);
...
@@ -124,7 +124,7 @@ static void sched_edf_create_tasks_test(void)
...
@@ -124,7 +124,7 @@ static void sched_edf_create_tasks_test(void)
t->attr.policy = SCHED_EDF;
t->attr.policy = SCHED_EDF;
t->attr.period = us_to_ktime(2000);
t->attr.period = us_to_ktime(2000);
t->attr.deadline_rel = us_to_ktime(900);
t->attr.deadline_rel = us_to_ktime(900);
t
->
attr
.
wcet
=
us_to_ktime
(
125
);
t->attr.wcet = us_to_ktime(
202
);
edf_enqueue(&t->sched->tq, t);
edf_enqueue(&t->sched->tq, t);
...
@@ -142,8 +142,94 @@ static void sched_edf_create_tasks_test(void)
...
@@ -142,8 +142,94 @@ static void sched_edf_create_tasks_test(void)
t->attr.policy = SCHED_EDF;
t->attr.policy = SCHED_EDF;
t->attr.period = us_to_ktime(1000);
t->attr.period = us_to_ktime(1000);
t->attr.deadline_rel = us_to_ktime(900);
t->attr.deadline_rel = us_to_ktime(900);
t
->
attr
.
wcet
=
us_to_ktime
(
99
);
t->attr.wcet = us_to_ktime(199);
edf_enqueue(&t->sched->tq, t);
/* create task 6 */
t = kmalloc(sizeof(struct task_struct));
KSFT_ASSERT_PTR_NOT_NULL(t);
t->name = kmalloc(32);
KSFT_ASSERT_PTR_NOT_NULL(t->name);
snprintf(t->name, 32, "task_6");
t->sched = &sched_edf;
t->attr.policy = SCHED_EDF;
t->attr.period = us_to_ktime(24960);
t->attr.deadline_rel = us_to_ktime(11000);
t->attr.wcet = us_to_ktime(104);
edf_enqueue(&t->sched->tq, t);
#else
/* create task 1 */
t
=
kmalloc
(
sizeof
(
struct
task_struct
));
KSFT_ASSERT_PTR_NOT_NULL
(
t
);
t
->
name
=
kmalloc
(
32
);
KSFT_ASSERT_PTR_NOT_NULL
(
t
->
name
);
snprintf
(
t
->
name
,
32
,
"task_1"
);
t
->
sched
=
&
sched_edf
;
t
->
attr
.
policy
=
SCHED_EDF
;
t
->
attr
.
period
=
us_to_ktime
(
1000
);
t
->
attr
.
deadline_rel
=
us_to_ktime
(
900
);
t
->
attr
.
wcet
=
us_to_ktime
(
250
);
edf_enqueue
(
&
t
->
sched
->
tq
,
t
);
/* create task 2 */
t
=
kmalloc
(
sizeof
(
struct
task_struct
));
KSFT_ASSERT_PTR_NOT_NULL
(
t
);
t
->
name
=
kmalloc
(
32
);
KSFT_ASSERT_PTR_NOT_NULL
(
t
->
name
);
snprintf
(
t
->
name
,
32
,
"task_2"
);
t
->
sched
=
&
sched_edf
;
t
->
attr
.
policy
=
SCHED_EDF
;
t
->
attr
.
period
=
us_to_ktime
(
1500
);
t
->
attr
.
deadline_rel
=
us_to_ktime
(
400
);
t
->
attr
.
wcet
=
us_to_ktime
(
300
);
edf_enqueue
(
&
t
->
sched
->
tq
,
t
);
/* create task 3 */
t
=
kmalloc
(
sizeof
(
struct
task_struct
));
KSFT_ASSERT_PTR_NOT_NULL
(
t
);
t
->
name
=
kmalloc
(
32
);
KSFT_ASSERT_PTR_NOT_NULL
(
t
->
name
);
snprintf
(
t
->
name
,
32
,
"task_3"
);
t
->
sched
=
&
sched_edf
;
t
->
attr
.
policy
=
SCHED_EDF
;
t
->
attr
.
period
=
us_to_ktime
(
30
);
t
->
attr
.
deadline_rel
=
us_to_ktime
(
20
);
t
->
attr
.
wcet
=
us_to_ktime
(
10
);
edf_enqueue
(
&
t
->
sched
->
tq
,
t
);
/* create task 4 */
t
=
kmalloc
(
sizeof
(
struct
task_struct
));
KSFT_ASSERT_PTR_NOT_NULL
(
t
);
t
->
name
=
kmalloc
(
32
);
KSFT_ASSERT_PTR_NOT_NULL
(
t
->
name
);
snprintf
(
t
->
name
,
32
,
"task_3"
);
t
->
sched
=
&
sched_edf
;
t
->
attr
.
policy
=
SCHED_EDF
;
t
->
attr
.
period
=
us_to_ktime
(
3000
);
t
->
attr
.
deadline_rel
=
us_to_ktime
(
900
);
t
->
attr
.
wcet
=
us_to_ktime
(
100
);
edf_enqueue
(
&
t
->
sched
->
tq
,
t
);
edf_enqueue
(
&
t
->
sched
->
tq
,
t
);
#endif
}
}
...
@@ -152,7 +238,7 @@ static void sched_edf_create_tasks_test(void)
...
@@ -152,7 +238,7 @@ static void sched_edf_create_tasks_test(void)
* @test sched_edf_create_tasks_test
* @test sched_edf_create_tasks_test
*/
*/
#define CYCLES 20000
#define CYCLES 20000
00
static
void
sched_edf_schedule_test
(
void
)
static
void
sched_edf_schedule_test
(
void
)
{
{
...
@@ -169,31 +255,31 @@ static void sched_edf_schedule_test(void)
...
@@ -169,31 +255,31 @@ static void sched_edf_schedule_test(void)
curr
=
next
;
curr
=
next
;
if
(
curr
)
{
if
(
curr
)
{
printk
(
"started: %lld now %lld
\n
"
,
curr
->
exec_start
,
ktime_get
());
//
printk("started: %lld now %lld\n", curr->exec_start, ktime_get());
/* remove runtime of slice from curr */
/* remove runtime of slice from curr */
curr
->
runtime
=
ktime_sub
(
curr
->
runtime
,
ktime_sub
(
ktime_get
(),
curr
->
exec_start
));
curr
->
runtime
=
ktime_sub
(
curr
->
runtime
,
ktime_sub
(
ktime_get
(),
curr
->
exec_start
));
}
}
edf_wake_next
(
&
sched_edf
.
tq
);
edf_wake_next
(
&
sched_edf
.
tq
);
sched_print_edf_list_internal
(
&
sched_edf
.
tq
,
ktime_get
());
//
sched_print_edf_list_internal(&sched_edf.tq, ktime_get());
next
=
edf_pick_next
(
&
sched_edf
.
tq
);
next
=
edf_pick_next
(
&
sched_edf
.
tq
);
sched_print_edf_list_internal
(
&
sched_edf
.
tq
,
ktime_get
());
//
sched_print_edf_list_internal(&sched_edf.tq, ktime_get());
if
(
next
)
{
if
(
next
)
{
slice
=
next
->
runtime
;
slice
=
next
->
runtime
;
printk
(
"Next: %s slice %lld
\n
"
,
next
->
name
,
ktime_to_us
(
slice
));
//
printk("Next: %s slice %lld\n", next->name, ktime_to_us(slice));
}
else
{
}
else
{
slice
=
1000000000
;
/* retry in 1 second */
slice
=
1000000000
;
/* retry in 1 second */
printk
(
"Next: NONE
\n
"
);
//
printk("Next: NONE\n");
}
}
wake
=
edf_task_ready_ns
(
&
sched_edf
.
tq
);
wake
=
edf_task_ready_ns
(
&
sched_edf
.
tq
);
printk
(
"New task ready in %llu
\n
"
,
ktime_to_us
(
wake
));
//
printk("New task ready in %llu\n", ktime_to_us(wake));
if
(
wake
<
slice
)
{
if
(
wake
<
slice
)
{
printk
(
"reducing slice from %lld to %lld (%lld)
\n
"
,
ktime_to_us
(
slice
),
ktime_to_us
(
wake
),
ktime_to_us
(
wake
-
slice
));
//
printk("reducing slice from %lld to %lld (%lld)\n", ktime_to_us(slice), ktime_to_us(wake), ktime_to_us(wake - slice));
slice
=
wake
;
slice
=
wake
;
}
}
...
@@ -206,7 +292,7 @@ static void sched_edf_schedule_test(void)
...
@@ -206,7 +292,7 @@ static void sched_edf_schedule_test(void)
/* our timeslice has passed: assume we return in time */
/* our timeslice has passed: assume we return in time */
kernel_time
+=
slice
;
kernel_time
+=
slice
;
printk
(
"
\n
pretending slice of %lld
\n
"
,
ktime_to_us
(
slice
));
//
printk("\npretending slice of %lld\n", ktime_to_us(slice));
ktime_wrap_set_time
(
kernel_time
);
ktime_wrap_set_time
(
kernel_time
);
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment