浏览代码

Kernel: Update TimerQueue next due timer only when necessary

Previously we blindly just called update_next_timer_due() when
ever we modified the timer list. Since we know the list is sorted
this is a bit wasteful, and we can do better.

This change refactors the code so we only update the next due time
when necessary. In places where it was possible the code was modified
to directly modify the next due time, instead of having to go to the
front of the list to fetch it.
Brian Gianforcaro 5 年之前
父节点
当前提交
49c438ce32
共有 1 个文件被更改,包括 23 次插入8 次删除
  1. 23 8
      Kernel/TimerQueue.cpp

+ 23 - 8
Kernel/TimerQueue.cpp

@@ -49,17 +49,27 @@ TimerQueue::TimerQueue()
 
 TimerId TimerQueue::add_timer(NonnullOwnPtr<Timer>&& timer)
 {
-    ASSERT(timer->expires >= g_uptime);
+    u64 timer_expiration = timer->expires;
+    ASSERT(timer_expiration >= g_uptime);
 
     timer->id = ++m_timer_id_count;
 
-    auto following_timer = m_timer_queue.find([&timer](auto& other) { return other->expires > timer->expires; });
-    if (following_timer.is_end())
+    if (m_timer_queue.is_empty()) {
         m_timer_queue.append(move(timer));
-    else
-        m_timer_queue.insert_before(following_timer, move(timer));
-
-    update_next_timer_due();
+        m_next_timer_due = timer_expiration;
+    } else {
+        auto following_timer = m_timer_queue.find([&timer_expiration](auto& other) { return other->expires > timer_expiration; });
+
+        if (following_timer.is_end()) {
+            m_timer_queue.append(move(timer));
+        } else {
+            auto next_timer_needs_update = following_timer.is_begin();
+            m_timer_queue.insert_before(following_timer, move(timer));
+
+            if (next_timer_needs_update)
+                m_next_timer_due = timer_expiration;
+        }
+    }
 
     return m_timer_id_count;
 }
@@ -77,8 +87,13 @@ bool TimerQueue::cancel_timer(TimerId id)
     auto it = m_timer_queue.find([id](auto& timer) { return timer->id == id; });
     if (it.is_end())
         return false;
+
+    auto was_next_timer = it.is_begin();
     m_timer_queue.remove(it);
-    update_next_timer_due();
+
+    if (was_next_timer)
+        update_next_timer_due();
+
     return true;
 }