@@ -12,6 +12,7 @@ extern crate alloc;
12
12
use alloc:: vec;
13
13
use alloc:: vec:: Vec ;
14
14
use zephyr:: time:: NoWait ;
15
+ use zephyr:: work:: futures:: work_size;
15
16
use zephyr:: {
16
17
kconfig:: CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC ,
17
18
kio:: { spawn, yield_now} ,
@@ -49,7 +50,20 @@ extern "C" fn rust_main() {
49
50
tester. run ( Command :: SemHigh ( 10_000 ) ) ;
50
51
tester. run ( Command :: SemPingPong ( 10_000 ) ) ;
51
52
tester. run ( Command :: SemPingPongAsync ( 10_000 ) ) ;
53
+ tester. run ( Command :: SemOnePingPong ( 10_000 ) ) ;
54
+ /*
55
+ tester.run(Command::SemOnePingPongAsync(NUM_THREADS, 10_000 / 6));
56
+ tester.run(Command::SemOnePingPongAsync(20, 10_000 / 20));
57
+ tester.run(Command::SemOnePingPongAsync(50, 10_000 / 50));
58
+ tester.run(Command::SemOnePingPongAsync(100, 10_000 / 100));
59
+ tester.run(Command::SemOnePingPongAsync(500, 10_000 / 500));
52
60
tester.run(Command::Empty);
61
+ */
62
+ let mut num = 6 ;
63
+ while num < 500 {
64
+ tester. run ( Command :: SemOnePingPongAsync ( num, 10_000 / num) ) ;
65
+ num = num * 13 / 10 ;
66
+ }
53
67
54
68
printkln ! ( "Done with all tests\n " ) ;
55
69
tester. leak ( ) ;
@@ -167,6 +181,16 @@ impl ThreadTests {
167
181
Self :: high_runner ( result2, high_recv) ;
168
182
} ) ;
169
183
184
+ // Calculate a size to show.
185
+ printkln ! ( "worker size: {} bytes" ,
186
+ work_size(
187
+ Self :: ping_pong_worker_async(
188
+ result. clone( ) ,
189
+ 0 ,
190
+ result. sems[ 0 ] . clone( ) ,
191
+ result. back_sems[ 0 ] . clone( ) ,
192
+ 6 ) ) ) ;
193
+
170
194
result
171
195
}
172
196
@@ -287,6 +311,10 @@ impl ThreadTests {
287
311
this. ping_pong_worker ( id, & this. sems [ id] , & this. back_sems [ id] , count, & mut total) ;
288
312
}
289
313
314
+ Command :: SemOnePingPong ( count) => {
315
+ this. ping_pong_worker ( id, & this. sems [ 0 ] , & this. back_sems [ 0 ] , count, & mut total) ;
316
+ }
317
+
290
318
// For the async commands, spawn this on the worker thread and don't reply
291
319
// ourselves.
292
320
Command :: SimpleSemAsync ( count) => {
@@ -362,6 +390,39 @@ impl ThreadTests {
362
390
363
391
continue ;
364
392
}
393
+
394
+ Command :: SemOnePingPongAsync ( nthread, count) => {
395
+ if id == 0 {
396
+ for th in 0 ..nthread {
397
+ spawn (
398
+ Self :: ping_pong_worker_async (
399
+ this. clone ( ) ,
400
+ th,
401
+ this. sems [ 0 ] . clone ( ) ,
402
+ this. back_sems [ 0 ] . clone ( ) ,
403
+ count,
404
+ ) ,
405
+ & this. workq ,
406
+ c"worker" ,
407
+ ) ;
408
+ }
409
+ spawn (
410
+ Self :: one_ping_pong_replier_async (
411
+ this. clone ( ) ,
412
+ nthread,
413
+ count,
414
+ ) ,
415
+ & this. workq ,
416
+ c"giver" ,
417
+ ) ;
418
+ }
419
+
420
+ // Avoid the reply for the number of workers that are within the range. This
421
+ // does assume that nthread will always be >= the number configured.
422
+ if id < this. sems . len ( ) {
423
+ continue ;
424
+ }
425
+ }
365
426
}
366
427
367
428
this. results
@@ -475,11 +536,14 @@ impl ThreadTests {
475
536
back_sem. give ( ) ;
476
537
}
477
538
478
- this. results
479
- . sender
480
- . send_async ( Result :: Worker { id, count } )
481
- . await
482
- . unwrap ( ) ;
539
+ // Only send for an ID in range.
540
+ if id < this. sems . len ( ) {
541
+ this. results
542
+ . sender
543
+ . send_async ( Result :: Worker { id, count } )
544
+ . await
545
+ . unwrap ( ) ;
546
+ }
483
547
}
484
548
485
549
fn ping_pong_replier ( & self , count : usize ) {
@@ -491,6 +555,15 @@ impl ThreadTests {
491
555
}
492
556
}
493
557
558
+ fn one_ping_pong_replier ( & self , count : usize ) {
559
+ for _ in 0 ..count {
560
+ for _ in 0 ..self . sems . len ( ) {
561
+ self . sems [ 0 ] . give ( ) ;
562
+ self . back_sems [ 0 ] . take ( Forever ) . unwrap ( ) ;
563
+ }
564
+ }
565
+ }
566
+
494
567
async fn ping_pong_replier_async ( this : Arc < Self > , count : usize ) {
495
568
for _ in 0 ..count {
496
569
for ( sem, back) in this. sems . iter ( ) . zip ( & this. back_sems ) {
@@ -502,6 +575,17 @@ impl ThreadTests {
502
575
// No reply.
503
576
}
504
577
578
+ async fn one_ping_pong_replier_async ( this : Arc < Self > , nthread : usize , count : usize ) {
579
+ for _ in 0 ..count {
580
+ for _ in 0 ..nthread {
581
+ this. sems [ 0 ] . give ( ) ;
582
+ this. back_sems [ 0 ] . take_async ( Forever ) . await . unwrap ( ) ;
583
+ }
584
+ }
585
+
586
+ // No reply.
587
+ }
588
+
505
589
async fn sem_giver_async ( this : Arc < Self > , sems : Vec < Arc < Semaphore > > , count : usize ) {
506
590
for _ in 0 ..count {
507
591
for sem in & sems {
@@ -541,7 +625,11 @@ impl ThreadTests {
541
625
Command :: SemPingPong ( count) => {
542
626
this. ping_pong_replier ( count) ;
543
627
}
628
+ Command :: SemOnePingPong ( count) => {
629
+ this. one_ping_pong_replier ( count) ;
630
+ }
544
631
Command :: SemPingPongAsync ( _) => ( ) ,
632
+ Command :: SemOnePingPongAsync ( _, _) => ( ) ,
545
633
}
546
634
// printkln!("low command: {:?}", cmd);
547
635
@@ -562,6 +650,7 @@ impl ThreadTests {
562
650
Command :: SemWaitAsync ( _) => ( ) ,
563
651
Command :: SemWaitSameAsync ( _) => ( ) ,
564
652
Command :: SemPingPong ( _) => ( ) ,
653
+ Command :: SemOnePingPong ( _) => ( ) ,
565
654
Command :: SemHigh ( count) => {
566
655
// The high-priority thread does all of the gives, this should cause every single
567
656
// semaphore operation to be ready.
@@ -572,6 +661,7 @@ impl ThreadTests {
572
661
}
573
662
}
574
663
Command :: SemPingPongAsync ( _) => ( ) ,
664
+ Command :: SemOnePingPongAsync ( _, _) => ( ) ,
575
665
}
576
666
// printkln!("high command: {:?}", cmd);
577
667
@@ -625,6 +715,11 @@ enum Command {
625
715
SemPingPong ( usize ) ,
626
716
/// SemPingPong, but async
627
717
SemPingPongAsync ( usize ) ,
718
+ /// PingPong but with a single shared semaphore. Demonstrates multiple threads queued on the
719
+ /// same object.
720
+ SemOnePingPong ( usize ) ,
721
+ /// Same as SemOnePingPong, but async. The first parameter is the number of async tasks.
722
+ SemOnePingPongAsync ( usize , usize ) ,
628
723
}
629
724
630
725
enum Result {
0 commit comments