| .. | .. |
|---|
| 33 | 33 | #define CREATE_TRACE_POINTS |
|---|
| 34 | 34 | #include <trace/events/alarmtimer.h> |
|---|
| 35 | 35 | |
|---|
| 36 | +#undef CREATE_TRACE_POINTS |
|---|
| 37 | +#include <trace/hooks/wakeupbypass.h> |
|---|
| 36 | 38 | /** |
|---|
| 37 | 39 | * struct alarm_base - Alarm timer bases |
|---|
| 38 | 40 | * @lock: Lock for syncrhonized access to the base |
|---|
| .. | .. |
|---|
| 246 | 248 | struct rtc_device *rtc; |
|---|
| 247 | 249 | unsigned long flags; |
|---|
| 248 | 250 | struct rtc_time tm; |
|---|
| 251 | + int wakeup_bypass_enabled = 0; |
|---|
| 249 | 252 | |
|---|
| 250 | 253 | spin_lock_irqsave(&freezer_delta_lock, flags); |
|---|
| 251 | 254 | min = freezer_delta; |
|---|
| .. | .. |
|---|
| 253 | 256 | type = freezer_alarmtype; |
|---|
| 254 | 257 | freezer_delta = 0; |
|---|
| 255 | 258 | spin_unlock_irqrestore(&freezer_delta_lock, flags); |
|---|
| 259 | + |
|---|
| 260 | + trace_android_vh_wakeup_bypass(&wakeup_bypass_enabled); |
|---|
| 261 | + if (wakeup_bypass_enabled) |
|---|
| 262 | + return 0; |
|---|
| 256 | 263 | |
|---|
| 257 | 264 | rtc = alarmtimer_get_rtcdev(); |
|---|
| 258 | 265 | /* If we have no rtcdev, just return */ |
|---|
| .. | .. |
|---|
| 470 | 477 | } |
|---|
| 471 | 478 | EXPORT_SYMBOL_GPL(alarm_forward); |
|---|
| 472 | 479 | |
|---|
| 473 | | -u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) |
|---|
| 480 | +static u64 __alarm_forward_now(struct alarm *alarm, ktime_t interval, bool throttle) |
|---|
| 474 | 481 | { |
|---|
| 475 | 482 | struct alarm_base *base = &alarm_bases[alarm->type]; |
|---|
| 483 | + ktime_t now = base->get_ktime(); |
|---|
| 476 | 484 | |
|---|
| 477 | | - return alarm_forward(alarm, base->get_ktime(), interval); |
|---|
| 485 | + if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && throttle) { |
|---|
| 486 | + /* |
|---|
| 487 | + * Same issue as with posix_timer_fn(). Timers which are |
|---|
| 488 | + * periodic but the signal is ignored can starve the system |
|---|
| 489 | + * with a very small interval. The real fix which was |
|---|
| 490 | + * promised in the context of posix_timer_fn() never |
|---|
| 491 | + * materialized, but someone should really work on it. |
|---|
| 492 | + * |
|---|
| 493 | + * To prevent DOS fake @now to be 1 jiffie out which keeps |
|---|
| 494 | + * the overrun accounting correct but creates an |
|---|
| 495 | + * inconsistency vs. timer_gettime(2). |
|---|
| 496 | + */ |
|---|
| 497 | + ktime_t kj = NSEC_PER_SEC / HZ; |
|---|
| 498 | + |
|---|
| 499 | + if (interval < kj) |
|---|
| 500 | + now = ktime_add(now, kj); |
|---|
| 501 | + } |
|---|
| 502 | + |
|---|
| 503 | + return alarm_forward(alarm, now, interval); |
|---|
| 504 | +} |
|---|
| 505 | + |
|---|
| 506 | +u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) |
|---|
| 507 | +{ |
|---|
| 508 | + return __alarm_forward_now(alarm, interval, false); |
|---|
| 478 | 509 | } |
|---|
| 479 | 510 | EXPORT_SYMBOL_GPL(alarm_forward_now); |
|---|
| 480 | 511 | |
|---|
| .. | .. |
|---|
| 548 | 579 | if (posix_timer_event(ptr, si_private) && ptr->it_interval) { |
|---|
| 549 | 580 | /* |
|---|
| 550 | 581 | * Handle ignored signals and rearm the timer. This will go |
|---|
| 551 | | - * away once we handle ignored signals proper. |
|---|
| 582 | + * away once we handle ignored signals proper. Ensure that |
|---|
| 583 | + * small intervals cannot starve the system. |
|---|
| 552 | 584 | */ |
|---|
| 553 | | - ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval); |
|---|
| 585 | + ptr->it_overrun += __alarm_forward_now(alarm, ptr->it_interval, true); |
|---|
| 554 | 586 | ++ptr->it_requeue_pending; |
|---|
| 555 | 587 | ptr->it_active = 1; |
|---|
| 556 | 588 | result = ALARMTIMER_RESTART; |
|---|