.. | .. |
---|
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; |
---|