Serenity Operating System
at hosted 102 lines 3.2 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/Function.h> 28#include <AK/NonnullOwnPtr.h> 29#include <AK/OwnPtr.h> 30#include <Kernel/Scheduler.h> 31#include <Kernel/TimerQueue.h> 32 33namespace Kernel { 34 35static TimerQueue* s_the; 36 37TimerQueue& TimerQueue::the() 38{ 39 if (!s_the) 40 s_the = new TimerQueue; 41 return *s_the; 42} 43 44u64 TimerQueue::add_timer(NonnullOwnPtr<Timer>&& timer) 45{ 46 ASSERT(timer->expires > g_uptime); 47 48 timer->id = ++m_timer_id_count; 49 50 auto following_timer = m_timer_queue.find([&timer](auto& other) { return other->expires > timer->expires; }); 51 if (following_timer.is_end()) 52 m_timer_queue.append(move(timer)); 53 else 54 m_timer_queue.insert_before(following_timer, move(timer)); 55 56 update_next_timer_due(); 57 58 return m_timer_id_count; 59} 60 61u64 TimerQueue::add_timer(u64 duration, TimeUnit unit, Function<void()>&& callback) 62{ 63 NonnullOwnPtr timer = make<Timer>(); 64 timer->expires = g_uptime + duration * unit; 65 timer->callback = move(callback); 66 return add_timer(move(timer)); 67} 68 69bool TimerQueue::cancel_timer(u64 id) 70{ 71 auto it = m_timer_queue.find([id](auto& timer) { return timer->id == id; }); 72 if (it.is_end()) 73 return false; 74 m_timer_queue.remove(it); 75 update_next_timer_due(); 76 return true; 77} 78 79void TimerQueue::fire() 80{ 81 if (m_timer_queue.is_empty()) 82 return; 83 84 ASSERT(m_next_timer_due == m_timer_queue.first()->expires); 85 86 while (!m_timer_queue.is_empty() && g_uptime > m_timer_queue.first()->expires) { 87 auto timer = m_timer_queue.take_first(); 88 timer->callback(); 89 } 90 91 update_next_timer_due(); 92} 93 94void TimerQueue::update_next_timer_due() 95{ 96 if (m_timer_queue.is_empty()) 97 m_next_timer_due = 0; 98 else 99 m_next_timer_due = m_timer_queue.first()->expires; 100} 101 102}