hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/kernel/time/alarmtimer.c
....@@ -33,6 +33,8 @@
3333 #define CREATE_TRACE_POINTS
3434 #include <trace/events/alarmtimer.h>
3535
36
+#undef CREATE_TRACE_POINTS
37
+#include <trace/hooks/wakeupbypass.h>
3638 /**
3739 * struct alarm_base - Alarm timer bases
3840 * @lock: Lock for syncrhonized access to the base
....@@ -246,6 +248,7 @@
246248 struct rtc_device *rtc;
247249 unsigned long flags;
248250 struct rtc_time tm;
251
+ int wakeup_bypass_enabled = 0;
249252
250253 spin_lock_irqsave(&freezer_delta_lock, flags);
251254 min = freezer_delta;
....@@ -253,6 +256,10 @@
253256 type = freezer_alarmtype;
254257 freezer_delta = 0;
255258 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;
256263
257264 rtc = alarmtimer_get_rtcdev();
258265 /* If we have no rtcdev, just return */
....@@ -470,11 +477,35 @@
470477 }
471478 EXPORT_SYMBOL_GPL(alarm_forward);
472479
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)
474481 {
475482 struct alarm_base *base = &alarm_bases[alarm->type];
483
+ ktime_t now = base->get_ktime();
476484
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);
478509 }
479510 EXPORT_SYMBOL_GPL(alarm_forward_now);
480511
....@@ -548,9 +579,10 @@
548579 if (posix_timer_event(ptr, si_private) && ptr->it_interval) {
549580 /*
550581 * 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.
552584 */
553
- ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval);
585
+ ptr->it_overrun += __alarm_forward_now(alarm, ptr->it_interval, true);
554586 ++ptr->it_requeue_pending;
555587 ptr->it_active = 1;
556588 result = ALARMTIMER_RESTART;