Update CS:GO team score gamedata.
1 // vim: set ts=8 sts=2 sw=2 tw=99 et:
3 // This file is part of SourcePawn.
5 // SourcePawn is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // SourcePawn is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
17 #include "watchdog_timer.h"
18 #include "x86/jit_x86.h"
21 WatchdogTimer g_WatchdogTimer;
23 WatchdogTimer::WatchdogTimer()
25 mainthread_(ke::GetCurrentThreadId()),
27 second_timeout_(false),
32 WatchdogTimer::~WatchdogTimer()
38 WatchdogTimer::Initialize(size_t timeout_ms)
43 timeout_ms_ = timeout_ms;
45 thread_ = new ke::Thread(this, "SM Watchdog");
46 if (!thread_->Succeeded())
53 WatchdogTimer::Shutdown()
55 if (terminate_ || !thread_)
59 ke::AutoLock lock(&cv_);
70 ke::AutoLock lock(&cv_);
72 // Initialize the frame id, so we don't have to wait longer on startup.
73 last_frame_id_ = g_Jit.FrameId();
76 ke::WaitResult rv = cv_.Wait(timeout_ms_ / 2);
80 if (rv == ke::Wait_Error)
83 if (rv != ke::Wait_Timeout)
86 // We reached a timeout. If the current frame is not equal to the last
87 // frame, then we assume the server is still moving enough to process
88 // frames. We also make sure JIT code is actually on the stack, since
89 // our concept of frames won't move if JIT code is not running.
91 // Note that it's okay if these two race: it's just a heuristic, and
92 // worst case, we'll miss something that might have timed out but
94 uintptr_t frame_id = g_Jit.FrameId();
95 if (frame_id != last_frame_id_ || !g_Jit.RunningCode()) {
96 last_frame_id_ = frame_id;
97 second_timeout_ = false;
101 // We woke up with the same frame. We might be timing out. Wait another
102 // time to see if so.
103 if (!second_timeout_) {
104 second_timeout_ = true;
109 // Prevent the JIT from linking or destroying runtimes and functions.
110 ke::AutoLock lock(g_Jit.Mutex());
112 // Set the timeout notification bit. If this is detected before any patched
113 // JIT backedges are reached, the main thread will attempt to acquire the
114 // monitor lock, and block until we call Wait().
117 // Patch all jumps. This can race with the main thread's execution since
118 // all code writes are 32-bit integer instruction operands, which are
119 // guaranteed to be atomic on x86.
120 g_Jit.PatchAllJumpsForTimeout();
123 // The JIT will be free to compile new functions while we wait, but it will
124 // see the timeout bit set above and immediately bail out.
127 second_timeout_ = false;
129 // Reset the last frame ID to something unlikely to be chosen again soon.
132 // It's possible that Shutdown() raced with the timeout, and if so, we
133 // must leave now to prevent a deadlock.
140 WatchdogTimer::NotifyTimeoutReceived()
142 // We are guaranteed that the watchdog thread is waiting for our
143 // notification, and is therefore blocked. We take the JIT lock
144 // anyway for sanity.
146 ke::AutoLock lock(g_Jit.Mutex());
147 g_Jit.UnpatchAllJumpsFromTimeout();
152 // Wake up the watchdog thread, it's okay to keep processing now.
153 ke::AutoLock lock(&cv_);
159 WatchdogTimer::HandleInterrupt()
162 return NotifyTimeoutReceived();