@@ -306,15 +306,10 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
306
306
cpu_data -> total += PULSE ;
307
307
}
308
308
309
- static bool teo_time_ok ( u64 interval_ns )
309
+ static bool teo_state_ok ( int i , struct cpuidle_driver * drv )
310
310
{
311
- return !tick_nohz_tick_stopped () || interval_ns >= TICK_NSEC ;
312
- }
313
-
314
- static s64 teo_middle_of_bin (int idx , struct cpuidle_driver * drv )
315
- {
316
- return (drv -> states [idx ].target_residency_ns +
317
- drv -> states [idx + 1 ].target_residency_ns ) / 2 ;
311
+ return !tick_nohz_tick_stopped () ||
312
+ drv -> states [i ].target_residency_ns >= TICK_NSEC ;
318
313
}
319
314
320
315
/**
@@ -354,6 +349,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
354
349
{
355
350
struct teo_cpu * cpu_data = per_cpu_ptr (& teo_cpus , dev -> cpu );
356
351
s64 latency_req = cpuidle_governor_latency_req (dev -> cpu );
352
+ ktime_t delta_tick = TICK_NSEC / 2 ;
357
353
unsigned int idx_intercept_sum = 0 ;
358
354
unsigned int intercept_sum = 0 ;
359
355
unsigned int idx_recent_sum = 0 ;
@@ -363,7 +359,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
363
359
int constraint_idx = 0 ;
364
360
int idx0 = 0 , idx = -1 ;
365
361
bool alt_intercepts , alt_recent ;
366
- ktime_t delta_tick ;
367
362
bool cpu_utilized ;
368
363
s64 duration_ns ;
369
364
int i ;
@@ -374,21 +369,20 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
374
369
}
375
370
376
371
cpu_data -> time_span_ns = local_clock ();
377
-
378
- duration_ns = tick_nohz_get_sleep_length (& delta_tick );
379
- cpu_data -> sleep_length_ns = duration_ns ;
372
+ /*
373
+ * Set the expected sleep length to infinity in case of an early
374
+ * return.
375
+ */
376
+ cpu_data -> sleep_length_ns = KTIME_MAX ;
380
377
381
378
/* Check if there is any choice in the first place. */
382
379
if (drv -> state_count < 2 ) {
383
380
idx = 0 ;
384
381
goto out_tick ;
385
382
}
386
383
387
- if (!dev -> states_usage [0 ].disable ) {
384
+ if (!dev -> states_usage [0 ].disable )
388
385
idx = 0 ;
389
- if (drv -> states [1 ].target_residency_ns > duration_ns )
390
- goto out_tick ;
391
- }
392
386
393
387
cpu_utilized = teo_cpu_is_utilized (dev -> cpu , cpu_data );
394
388
/*
@@ -397,8 +391,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
397
391
* the shallowest non-polling state and exit.
398
392
*/
399
393
if (drv -> state_count < 3 && cpu_utilized ) {
400
- /* The CPU is utilized, so assume a short idle duration. */
401
- duration_ns = teo_middle_of_bin (0 , drv );
402
394
/*
403
395
* If state 0 is enabled and it is not a polling one, select it
404
396
* right away unless the scheduler tick has been stopped, in
@@ -408,22 +400,17 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
408
400
* anyway.
409
401
*/
410
402
if ((!idx && !(drv -> states [0 ].flags & CPUIDLE_FLAG_POLLING ) &&
411
- teo_time_ok ( duration_ns )) || dev -> states_usage [1 ].disable ) {
403
+ teo_state_ok ( 0 , drv )) || dev -> states_usage [1 ].disable ) {
412
404
idx = 0 ;
413
405
goto out_tick ;
414
406
}
415
407
/* Assume that state 1 is not a polling one and use it. */
416
408
idx = 1 ;
409
+ duration_ns = drv -> states [1 ].target_residency_ns ;
417
410
goto end ;
418
411
}
419
412
420
- /*
421
- * Find the deepest idle state whose target residency does not exceed
422
- * the current sleep length and the deepest idle state not deeper than
423
- * the former whose exit latency does not exceed the current latency
424
- * constraint. Compute the sums of metrics for early wakeup pattern
425
- * detection.
426
- */
413
+ /* Compute the sums of metrics for early wakeup pattern detection. */
427
414
for (i = 1 ; i < drv -> state_count ; i ++ ) {
428
415
struct teo_bin * prev_bin = & cpu_data -> state_bins [i - 1 ];
429
416
struct cpuidle_state * s = & drv -> states [i ];
@@ -439,19 +426,15 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
439
426
if (dev -> states_usage [i ].disable )
440
427
continue ;
441
428
442
- if (idx < 0 ) {
443
- idx = i ; /* first enabled state */
444
- idx0 = i ;
445
- }
446
-
447
- if (s -> target_residency_ns > duration_ns )
448
- break ;
429
+ if (idx < 0 )
430
+ idx0 = i ; /* first enabled state */
449
431
450
432
idx = i ;
451
433
452
434
if (s -> exit_latency_ns <= latency_req )
453
435
constraint_idx = i ;
454
436
437
+ /* Save the sums for the current state. */
455
438
idx_intercept_sum = intercept_sum ;
456
439
idx_hit_sum = hit_sum ;
457
440
idx_recent_sum = recent_sum ;
@@ -465,7 +448,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
465
448
466
449
if (idx == idx0 ) {
467
450
/*
468
- * This is the first enabled idle state, so use it, but do not
451
+ * Only one idle state is enabled , so use it, but do not
469
452
* allow the tick to be stopped it is shallow enough.
470
453
*/
471
454
duration_ns = drv -> states [idx ].target_residency_ns ;
@@ -479,13 +462,11 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
479
462
* all of the deeper states, or the sum of the numbers of recent
480
463
* intercepts over all of the states shallower than the candidate one
481
464
* is greater than a half of the number of recent events taken into
482
- * account, the CPU is likely to wake up early, so find an alternative
483
- * idle state to select.
465
+ * account, a shallower idle state is likely to be a better choice.
484
466
*/
485
467
alt_intercepts = 2 * idx_intercept_sum > cpu_data -> total - idx_hit_sum ;
486
468
alt_recent = idx_recent_sum > NR_RECENT / 2 ;
487
469
if (alt_recent || alt_intercepts ) {
488
- s64 first_suitable_span_ns = duration_ns ;
489
470
int first_suitable_idx = idx ;
490
471
491
472
/*
@@ -494,44 +475,39 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
494
475
* cases (both with respect to intercepts overall and with
495
476
* respect to the recent intercepts only) in the past.
496
477
*
497
- * Take the possible latency constraint and duration limitation
498
- * present if the tick has been stopped already into account.
478
+ * Take the possible duration limitation present if the tick
479
+ * has been stopped already into account.
499
480
*/
500
481
intercept_sum = 0 ;
501
482
recent_sum = 0 ;
502
483
503
484
for (i = idx - 1 ; i >= 0 ; i -- ) {
504
485
struct teo_bin * bin = & cpu_data -> state_bins [i ];
505
- s64 span_ns ;
506
486
507
487
intercept_sum += bin -> intercepts ;
508
488
recent_sum += bin -> recent ;
509
489
510
- span_ns = teo_middle_of_bin (i , drv );
511
-
512
490
if ((!alt_recent || 2 * recent_sum > idx_recent_sum ) &&
513
491
(!alt_intercepts ||
514
492
2 * intercept_sum > idx_intercept_sum )) {
515
- if (teo_time_ok (span_ns ) &&
516
- !dev -> states_usage [i ].disable ) {
493
+ /*
494
+ * Use the current state unless it is too
495
+ * shallow or disabled, in which case take the
496
+ * first enabled state that is deep enough.
497
+ */
498
+ if (teo_state_ok (i , drv ) &&
499
+ !dev -> states_usage [i ].disable )
517
500
idx = i ;
518
- duration_ns = span_ns ;
519
- } else {
520
- /*
521
- * The current state is too shallow or
522
- * disabled, so take the first enabled
523
- * deeper state with suitable time span.
524
- */
501
+ else
525
502
idx = first_suitable_idx ;
526
- duration_ns = first_suitable_span_ns ;
527
- }
503
+
528
504
break ;
529
505
}
530
506
531
507
if (dev -> states_usage [i ].disable )
532
508
continue ;
533
509
534
- if (!teo_time_ok ( span_ns )) {
510
+ if (!teo_state_ok ( i , drv )) {
535
511
/*
536
512
* The current state is too shallow, but if an
537
513
* alternative candidate state has been found,
@@ -543,7 +519,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
543
519
break ;
544
520
}
545
521
546
- first_suitable_span_ns = span_ns ;
547
522
first_suitable_idx = i ;
548
523
}
549
524
}
@@ -562,14 +537,22 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
562
537
* not sufficiently large.
563
538
*/
564
539
if (cpu_utilized ) {
565
- s64 span_ns ;
540
+ i = teo_find_shallower_state (drv , dev , idx , KTIME_MAX , true);
541
+ if (teo_state_ok (i , drv ))
542
+ idx = i ;
543
+ }
566
544
567
- i = teo_find_shallower_state (drv , dev , idx , duration_ns , true);
568
- span_ns = teo_middle_of_bin (i , drv );
569
- if (teo_time_ok (span_ns )) {
545
+ duration_ns = tick_nohz_get_sleep_length (& delta_tick );
546
+ cpu_data -> sleep_length_ns = duration_ns ;
547
+
548
+ /*
549
+ * If the closest expected timer is before the terget residency of the
550
+ * candidate state, a shallower one needs to be found.
551
+ */
552
+ if (drv -> states [idx ].target_residency_ns > duration_ns ) {
553
+ i = teo_find_shallower_state (drv , dev , idx , duration_ns , false);
554
+ if (teo_state_ok (i , drv ))
570
555
idx = i ;
571
- duration_ns = span_ns ;
572
- }
573
556
}
574
557
575
558
end :
0 commit comments