summaryrefslogtreecommitdiff
path: root/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp
diff options
context:
space:
mode:
authorLuke <[email protected]>2017-11-28 00:22:11 -0800
committerGitHub <[email protected]>2017-11-28 00:22:11 -0800
commit79bbbca2f6e37d94fbbbd60d12c5c1e7dde650da (patch)
tree793ff943b8b641f95d05401156badd42da4a0f12 /general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp
parented1df9a8b80b154b71b79635e40af75f4f19001c (diff)
parent2817004092cee784d4aaf36c045fdb5b0bc09f7e (diff)
Merge pull request #1 from Microsoft/master
Updating Local
Diffstat (limited to 'general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp')
-rw-r--r--general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp
new file mode 100644
index 00000000..1766b37c
--- /dev/null
+++ b/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp
@@ -0,0 +1,148 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "stdafx.h"
+#include "Metering.h"
+#include <assert.h>
+#include "RpcInterface_h.h"
+
+using namespace RpcServer;
+
+//
+// Thread pool callback method for metering worker
+//
+void CALLBACK MeteringWorkerTpCallback(
+ _In_ PTP_CALLBACK_INSTANCE /*iTimerInstance*/,
+ _In_ PVOID pContext,
+ _In_ PTP_TIMER /*pTimer*/)
+{
+ Metering *metering = static_cast<Metering *>(pContext);
+
+ if (metering != nullptr)
+ {
+ // Run the metering worker for this instance of metering
+ metering->MeteringWorker();
+ }
+}
+
+//
+// ctor for Metering
+//
+Metering::Metering(
+ _In_ __int64 period)
+{
+ tpTimer = CreateThreadpoolTimer(::MeteringWorkerTpCallback, this, nullptr);
+ // TODO: Handle if CreateThreadpoolTimer fails i.e tpTimer == nullptr
+
+ samplePeriod = period;
+ event = CreateEvent(
+ nullptr, // default security attributes
+ FALSE, // auto-reset event object
+ FALSE, // initial state is nonsignaled
+ nullptr); // unnamed object
+}
+
+//
+// dtor for Metering
+//
+Metering::~Metering()
+{
+ if (tpTimer != nullptr)
+ {
+ // How to close threadpool timer when there are outstanding callbacks:
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682040(v=vs.85).aspx
+ SetThreadpoolTimer(tpTimer, nullptr, 0, 0);
+ WaitForThreadpoolTimerCallbacks(tpTimer, true);
+ CloseThreadpoolTimer(tpTimer);
+ tpTimer = nullptr;
+ }
+ CloseHandle(event);
+}
+
+//
+// Set the lowest sample period
+//
+void Metering::SetSamplePeriod(_In_ __int64 period)
+{
+ if (period < 1)
+ {
+ // Don't allow 0 (too fast) or negative numbers.
+ period = 1;
+ }
+ if (period > 1000)
+ {
+ // Don't let the period be too long, or we will be
+ // slow to shut down.
+ period = 1000;
+ }
+ samplePeriod = period;
+}
+
+//
+// Get last known metering data
+//
+__int64 Metering::GetMeteringData() const
+{
+ return _data;
+}
+
+//
+// Metering worker that updates metering data
+//
+void Metering::MeteringWorker()
+{
+ // Get the value from the imaginary driver and update the data
+ _data = GetTickCount();
+ SetEvent(event);
+}
+
+//
+// Set the thread poot timer and wait for metering data.
+//
+void Metering::WaitForMeteringData() const
+{
+ ULARGE_INTEGER ulDueTime;
+ FILETIME FileDueTime;
+ ulDueTime.QuadPart = static_cast<ULONGLONG>(-(1 * 10 * 1000 * samplePeriod));
+ FileDueTime.dwHighDateTime = ulDueTime.HighPart;
+ FileDueTime.dwLowDateTime = ulDueTime.LowPart;
+
+ SetThreadpoolTimer(tpTimer,
+ &FileDueTime,
+ 0,
+ 0);
+
+ WaitForSingleObject(event, INFINITE);
+}
+
+void Metering::StartMetering(
+ _In_ __int64 samplePeriod,
+ _In_ __int64 context)
+{
+ stopMeteringRequested = false;
+ SetSamplePeriod(samplePeriod);
+
+ while (true)
+ {
+ WaitForMeteringData();
+ if (stopMeteringRequested || ShutdownRequested)
+ {
+ break;
+ }
+ MeteringDataEvent(GetMeteringData(), context);
+ }
+}
+
+void Metering::StopMetering()
+{
+ stopMeteringRequested = true;
+}
+