@@ -3,25 +3,28 @@ use alloc::collections::VecDeque;
33use alloc:: sync:: Arc ;
44use alloc:: task:: Wake ;
55use alloc:: vec:: Vec ;
6+ use core:: fmt:: Write ;
67use core:: future:: { poll_fn, Future } ;
78use core:: pin:: Pin ;
89use core:: sync:: atomic:: { AtomicBool , AtomicU64 , Ordering } ;
910use core:: task:: { Context , Poll , Waker } ;
11+
1012use spin:: Mutex ;
1113use uefi:: boot:: { EventType , TimerTrigger , Tpl } ;
14+ use uefi:: proto:: console:: text:: Color ;
1215
16+ use crate :: os:: send_wrapper:: SendWrapper ;
1317use crate :: os:: timer:: Timer ;
18+ use crate :: os:: ui:: DrawArea ;
1419
15- struct BoxFuture ( Pin < Box < dyn Future < Output = ( ) > + ' static > > ) ;
16-
17- // SAFETY: there are no threads.
18- unsafe impl Send for BoxFuture { }
20+ struct BoxFuture ( SendWrapper < Pin < Box < dyn Future < Output = ( ) > + ' static > > > ) ;
1921
2022struct Task {
2123 name : & ' static str ,
2224 in_queue : AtomicBool ,
2325 future : Mutex < BoxFuture > ,
2426 micros : AtomicU64 ,
27+ last_micros : AtomicU64 ,
2528}
2629
2730impl Task {
@@ -31,8 +34,9 @@ impl Task {
3134 {
3235 Arc :: new ( Task {
3336 name,
34- future : Mutex :: new ( BoxFuture ( Box :: pin ( future) ) ) ,
37+ future : Mutex :: new ( BoxFuture ( SendWrapper ( Box :: pin ( future) ) ) ) ,
3538 micros : AtomicU64 :: new ( 0 ) ,
39+ last_micros : AtomicU64 :: new ( 0 ) ,
3640 in_queue : AtomicBool :: new ( false ) ,
3741 } )
3842 }
@@ -57,8 +61,98 @@ pub struct Executor {
5761 tasks : Vec < Arc < Task > > ,
5862}
5963
64+ pub ( super ) const TASK_LEN : usize = 34 ;
65+
6066impl Executor {
67+ async fn draw_tasks ( ) {
68+ let mut draw_area = DrawArea :: tasks ( ) ;
69+ let ( w, h) = draw_area. size ( ) ;
70+ assert ! ( ( w - 1 ) . is_multiple_of( TASK_LEN + 1 ) ) ;
71+ let num_w = ( w - 1 ) / ( TASK_LEN + 1 ) ;
72+ let mut last = Timer :: micros ( ) as u64 ;
73+ Self :: sleep_us ( 100_000 ) . await ;
74+ loop {
75+ draw_area. clear ( ) ;
76+ let cur = Timer :: micros ( ) as u64 ;
77+ let elapsed = cur. saturating_sub ( last) . max ( 1 ) as f64 ;
78+ {
79+ let mut executor = EXECUTOR . lock ( ) ;
80+ let tasks = & mut executor. tasks ;
81+ // Sort by *descending* time used since last draw.
82+ tasks. sort_unstable_by_key ( |f| {
83+ f. last_micros . load ( Ordering :: Relaxed ) as i64
84+ - f. micros . load ( Ordering :: Relaxed ) as i64
85+ } ) ;
86+
87+ write ! ( draw_area, "\u{250C} " ) . unwrap ( ) ;
88+ for x in 0 ..num_w {
89+ for _ in 0 ..TASK_LEN {
90+ write ! ( draw_area, "\u{2500} " ) . unwrap ( ) ;
91+ }
92+ if x + 1 == num_w {
93+ write ! ( draw_area, "\u{2510} " ) . unwrap ( ) ;
94+ } else {
95+ write ! ( draw_area, "\u{252C} " ) . unwrap ( ) ;
96+ }
97+ }
98+ draw_area. newline ( ) ;
99+ for y in 0 ..( h - 2 ) {
100+ write ! ( draw_area, "\u{2502} " ) . unwrap ( ) ;
101+ for x in 0 ..num_w {
102+ let idx = x * h + y;
103+ if idx >= tasks. len ( ) {
104+ draw_area. advance ( TASK_LEN ) ;
105+ } else {
106+ let task = & tasks[ idx] ;
107+ let total_cpu = task. micros . load ( Ordering :: Relaxed ) ;
108+ let last_cpu = task. last_micros . load ( Ordering :: Relaxed ) ;
109+ let frac = ( ( total_cpu - last_cpu) as f64 / elapsed) . min ( 1.0 ) ;
110+ draw_area. write_with_color (
111+ & format ! (
112+ " {:15}{:5.1}%{:10.3}s " ,
113+ & task. name[ ..task. name. len( ) . min( 15 ) ] ,
114+ frac * 100.0 ,
115+ total_cpu as f64 * 0.000_001 ,
116+ ) ,
117+ if frac >= 0.5 {
118+ Color :: Red
119+ } else if frac >= 0.1 {
120+ Color :: Yellow
121+ } else {
122+ Color :: White
123+ } ,
124+ Color :: Black ,
125+ ) ;
126+ }
127+ write ! ( draw_area, "\u{2502} " ) . unwrap ( ) ;
128+ }
129+ draw_area. newline ( ) ;
130+ }
131+ write ! ( draw_area, "\u{2514} " ) . unwrap ( ) ;
132+ for x in 0 ..num_w {
133+ for _ in 0 ..TASK_LEN {
134+ write ! ( draw_area, "\u{2500} " ) . unwrap ( ) ;
135+ }
136+ if x + 1 == num_w {
137+ write ! ( draw_area, "\u{2518} " ) . unwrap ( ) ;
138+ } else {
139+ write ! ( draw_area, "\u{2534} " ) . unwrap ( ) ;
140+ }
141+ }
142+ draw_area. newline ( ) ;
143+
144+ for t in tasks. iter ( ) {
145+ t. last_micros
146+ . store ( t. micros . load ( Ordering :: Relaxed ) , Ordering :: Relaxed ) ;
147+ }
148+ }
149+ last = Timer :: micros ( ) as u64 ;
150+ Self :: sleep_us ( 1_000_000 ) . await ;
151+ }
152+ }
153+
61154 pub fn run ( ) -> ! {
155+ Self :: spawn ( "[show_tasks]" , Self :: draw_tasks ( ) ) ;
62156 loop {
63157 let task = EXECUTOR
64158 . lock ( )
@@ -126,16 +220,4 @@ impl Executor {
126220 executor. tasks . push ( task. clone ( ) ) ;
127221 executor. ready_tasks . push_back ( task) ;
128222 }
129-
130- pub fn top_tasks ( n : usize ) -> Vec < ( u64 , & ' static str ) > {
131- let mut tasks: Vec < _ > = EXECUTOR
132- . lock ( )
133- . tasks
134- . iter ( )
135- . map ( |x| ( x. micros . load ( Ordering :: Relaxed ) , x. name ) )
136- . collect ( ) ;
137- tasks. sort_by_key ( |t| -( t. 0 as i64 ) ) ;
138- tasks. truncate ( n) ;
139- tasks
140- }
141223}
0 commit comments