From b9e9a5ee3dd2e01b72b009f46fef5a13ba31e5dd Mon Sep 17 00:00:00 2001
From: spxtr <spextear@gmail.com>
Date: Thu, 28 Apr 2016 21:28:15 -0700
Subject: [PATCH] Use CoreTiming for MemoryWatcher.

---
 Source/Core/Core/Core.cpp          |  8 +---
 Source/Core/Core/MemoryWatcher.cpp | 75 +++++++++++++++++++-----------
 Source/Core/Core/MemoryWatcher.h   | 11 ++---
 3 files changed, 55 insertions(+), 39 deletions(-)

diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp
index d8af296679..5c0258c37f 100644
--- a/Source/Core/Core/Core.cpp
+++ b/Source/Core/Core/Core.cpp
@@ -112,10 +112,6 @@ static bool s_request_refresh_info = false;
 static int s_pause_and_lock_depth = 0;
 static bool s_is_throttler_temp_disabled = false;
 
-#ifdef USE_MEMORYWATCHER
-static std::unique_ptr<MemoryWatcher> s_memory_watcher;
-#endif
-
 #ifdef ThreadLocalStorage
 static ThreadLocalStorage bool tls_is_cpu_thread = false;
 #else
@@ -289,7 +285,7 @@ void Stop()  // - Hammertime!
 #endif
 
 #ifdef USE_MEMORYWATCHER
-	s_memory_watcher.reset();
+	MemoryWatcher::Shutdown();
 #endif
 }
 
@@ -361,7 +357,7 @@ static void CpuThread()
 	#endif
 
 #ifdef USE_MEMORYWATCHER
-	s_memory_watcher = std::make_unique<MemoryWatcher>();
+	MemoryWatcher::Init();
 #endif
 
 	// Enter CPU run loop. When we leave it - we are done.
diff --git a/Source/Core/Core/MemoryWatcher.cpp b/Source/Core/Core/MemoryWatcher.cpp
index f16fcfd12b..66f0eef2b7 100644
--- a/Source/Core/Core/MemoryWatcher.cpp
+++ b/Source/Core/Core/MemoryWatcher.cpp
@@ -4,25 +4,48 @@
 
 #include <fstream>
 #include <iostream>
+#include <memory>
 #include <sstream>
 #include <unistd.h>
 
 #include "Common/FileUtil.h"
-#include "Common/Thread.h"
+#include "Core/CoreTiming.h"
 #include "Core/MemoryWatcher.h"
 #include "Core/HW/Memmap.h"
+#include "Core/HW/SystemTimers.h"
 
-// We don't want to kill the cpu, so sleep for this long after polling.
-static const int SLEEP_DURATION = 2; // ms
+static std::unique_ptr<MemoryWatcher> s_memory_watcher;
+static int s_event;
+static const int MW_RATE = 600; // Steps per second
+
+static void MWCallback(u64 userdata, s64 cyclesLate)
+{
+	s_memory_watcher->Step();
+	CoreTiming::ScheduleEvent(
+	    (SystemTimers::GetTicksPerSecond() / MW_RATE) - cyclesLate, s_event);
+}
+
+void MemoryWatcher::Init()
+{
+	s_memory_watcher = std::make_unique<MemoryWatcher>();
+	s_event = CoreTiming::RegisterEvent("MemoryWatcher", MWCallback);
+	CoreTiming::ScheduleEvent(0, s_event);
+}
+
+void MemoryWatcher::Shutdown()
+{
+	CoreTiming::RemoveEvent(s_event);
+	s_memory_watcher.reset();
+}
 
 MemoryWatcher::MemoryWatcher()
 {
+	m_running = false;
 	if (!LoadAddresses(File::GetUserPath(F_MEMORYWATCHERLOCATIONS_IDX)))
 		return;
 	if (!OpenSocket(File::GetUserPath(F_MEMORYWATCHERSOCKET_IDX)))
 		return;
 	m_running = true;
-	m_watcher_thread = std::thread(&MemoryWatcher::WatcherThread, this);
 }
 
 MemoryWatcher::~MemoryWatcher()
@@ -31,7 +54,6 @@ MemoryWatcher::~MemoryWatcher()
 		return;
 
 	m_running = false;
-	m_watcher_thread.join();
 	close(m_fd);
 }
 
@@ -85,30 +107,29 @@ std::string MemoryWatcher::ComposeMessage(const std::string& line, u32 value)
 	return message_stream.str();
 }
 
-void MemoryWatcher::WatcherThread()
+void MemoryWatcher::Step()
 {
-	while (m_running)
-	{
-		for (auto& entry : m_values)
-		{
-			std::string address = entry.first;
-			u32& current_value = entry.second;
+	if (!m_running)
+		return;
 
-			u32 new_value = ChasePointer(address);
-			if (new_value != current_value)
-			{
-				// Update the value
-				current_value = new_value;
-				std::string message = ComposeMessage(address, new_value);
-				sendto(
-					m_fd,
-					message.c_str(),
-					message.size() + 1,
-					0,
-					reinterpret_cast<sockaddr*>(&m_addr),
-					sizeof(m_addr));
-			}
+	for (auto& entry : m_values)
+	{
+		std::string address = entry.first;
+		u32& current_value = entry.second;
+
+		u32 new_value = ChasePointer(address);
+		if (new_value != current_value)
+		{
+			// Update the value
+			current_value = new_value;
+			std::string message = ComposeMessage(address, new_value);
+			sendto(
+				m_fd,
+				message.c_str(),
+				message.size() + 1,
+				0,
+				reinterpret_cast<sockaddr*>(&m_addr),
+				sizeof(m_addr));
 		}
-		Common::SleepCurrentThread(SLEEP_DURATION);
 	}
 }
diff --git a/Source/Core/Core/MemoryWatcher.h b/Source/Core/Core/MemoryWatcher.h
index e49a647aa5..7ea38ff354 100644
--- a/Source/Core/Core/MemoryWatcher.h
+++ b/Source/Core/Core/MemoryWatcher.h
@@ -4,9 +4,7 @@
 
 #pragma once
 
-#include <atomic>
 #include <map>
-#include <thread>
 #include <vector>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -24,6 +22,10 @@ class MemoryWatcher final
 public:
 	MemoryWatcher();
 	~MemoryWatcher();
+	void Step();
+
+	static void Init();
+	static void Shutdown();
 
 private:
 	bool LoadAddresses(const std::string& path);
@@ -33,10 +35,7 @@ private:
 	u32 ChasePointer(const std::string& line);
 	std::string ComposeMessage(const std::string& line, u32 value);
 
-	void WatcherThread();
-
-	std::thread m_watcher_thread;
-	std::atomic_bool m_running{false};
+	bool m_running;
 
 	int m_fd;
 	sockaddr_un m_addr;