)]}'
{
  "commit": "3f5a9e1b5ebd7f2b7bb3c4055d6016082a5f672f",
  "tree": "d7b3da6950c291fec2c7e830edf6cd512011c70e",
  "parents": [
    "95f3df43a99d32dc17938f245c27cb80466d9071"
  ],
  "author": {
    "name": "Nicolas Saenz Julienne",
    "email": "nsaenzju@redhat.com",
    "time": "Thu Jul 08 12:29:50 2021 +0200"
  },
  "committer": {
    "name": "Nicolas Saenz Julienne",
    "email": "nsaenz@kernel.org",
    "time": "Fri Jul 09 13:47:36 2021 +0200"
  },
  "message": "timers: Fix get_next_timer_interrupt() with no timers pending\n\n31cd0e119d50 (\"timers: Recalculate next timer interrupt only when\nnecessary\") subtly altered get_next_timer_interrupt()\u0027s behaviour. The\nfunction no longer consistently returns KTIME_MAX with no timers\npending.\n\nIn order to decide if there are any timers pending we check whether the\nnext expiry will happen NEXT_TIMER_MAX_DELTA jiffies from now.\nUnfortunately, the next expiry time and the timer base clock are no\nlonger updated in unison. The former changes upon certain timer\noperations (enqueue, expire, detach), whereas the latter keeps track of\njiffies as they move forward. Ultimately breaking the logic above.\n\nA simplified example:\n\n- Upon entering get_next_timer_interrupt() with:\n\n\tjiffies \u003d 1\n\tbase-\u003eclk \u003d 0;\n\tbase-\u003enext_expiry \u003d NEXT_TIMER_MAX_DELTA;\n\n  \u0027base-\u003enext_expiry \u003d\u003d base-\u003eclk + NEXT_TIMER_MAX_DELTA\u0027, the function\n  returns KTIME_MAX.\n\n- \u0027base-\u003eclk\u0027 is updated to the jiffies value.\n\n- The next time we enter get_next_timer_interrupt(), taking into account\n  no timer operations happened:\n\n\tbase-\u003eclk \u003d 1;\n\tbase-\u003enext_expiry \u003d NEXT_TIMER_MAX_DELTA;\n\n  \u0027base-\u003enext_expiry !\u003d base-\u003eclk + NEXT_TIMER_MAX_DELTA\u0027, the function\n  returns a valid expire time, which is incorrect.\n\nThis, ultimately might unnecessarily rearm sched\u0027s timer on nohz_full\nsetups, and add latency to the system[1].\n\nSo, introduce \u0027base-\u003etimers_pending\u0027[2], update it every time\n\u0027base-\u003enext_expiry\u0027 changes, and use it in get_next_timer_interrupt().\n\n[1] See tick_nohz_stop_tick().\n[2] A quick check in x86_64 and arm64 with pahole shows it doesn\u0027t make\n   \u0027struct timer_base\u0027 any bigger.\n\nFixes: 31cd0e119d50 (\"timers: Recalculate next timer interrupt only when necessary\")\nSigned-off-by: Nicolas Saenz Julienne \u003cnsaenzju@redhat.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "3fadb58fc9d7b1c7a273b59a48b8dc82c47a1b22",
      "old_mode": 33188,
      "old_path": "kernel/time/timer.c",
      "new_id": "9eb11c2209e56b663a9b326c682e18f8c289f49a",
      "new_mode": 33188,
      "new_path": "kernel/time/timer.c"
    }
  ]
}
