//Wrapper for CallNtPowerInformation internal static ArrayList GetAllProcessorPowerInfo() { const Int32 processorSpeedInformation = 11; //Used in call to CallNtPowerInformation ArrayList CPUspeeds = new ArrayList(); PROCESSOR_POWER_INFORMATION oneppi = new PROCESSOR_POWER_INFORMATION(); uint ProcessorSpeedArraySize = (UInt32)Environment.ProcessorCount * (UInt32)Marshal.SizeOf(oneppi); IntPtr CPUInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION)) * Environment.ProcessorCount); uint retval = Win32.CallNtPowerInformation( processorSpeedInformation, (IntPtr)null, (UInt32)0, CPUInfo, ProcessorSpeedArraySize); if (retval == 0) { IntPtr currentptr = ((IntPtr)CPUInfo); for (int i = 0; i < Environment.ProcessorCount; i++) { PROCESSOR_POWER_INFORMATION ppi = (PROCESSOR_POWER_INFORMATION)Marshal.PtrToStructure(currentptr, typeof(PROCESSOR_POWER_INFORMATION)); currentptr = (IntPtr)((int)currentptr + Marshal.SizeOf(oneppi)); CPUspeeds.Add(ppi); } } Marshal.FreeCoTaskMem(CPUInfo); return(CPUspeeds); }
// Returns the Processor Spped information for the current processor internal static PROCESSOR_POWER_INFORMATION GetCurrentPowerInfoforProcessor() { PROCESSOR_POWER_INFORMATION ppi = new PROCESSOR_POWER_INFORMATION(); ArrayList currentCPUspeeds; currentCPUspeeds = GetAllProcessorPowerInfo(); uint currentCPUID = Win32.GetCurrentProcessorNumber(); ppi = (PROCESSOR_POWER_INFORMATION)currentCPUspeeds[(int)currentCPUID]; return(ppi); }
public void Stop() { // Calling stop on a stopped Stopwatch is a no-op. if (isRunning) { long endTimeStamp = 0; endTimeStamp = GetTimestamp(); if (CPUTimeIsAvailable) { timerEndThreadHandle = Win32.GetCurrentThread(); long endCPUcycles = GetCPUCycles(); //Get CPU Cycles first if (timerEndThreadHandle != timerStartThreadHandle) { threadSwitchOccurred = true; //A thread switch is a problem, since CPU Cycles are accumulated endCPUcycles = 0; // at the thread level startCPUcycles = 0; } else { if (endCPUcycles > startCPUcycles) { elapsedCPUThisPeriod = endCPUcycles - startCPUcycles; elapsedCPU += elapsedCPUThisPeriod; } //How likely is it for the CPU time accumulator to wrap??? else { elapsedCPU = 0; endCPUcycles = 0; startCPUcycles = 0; } } } long elapsedThisPeriod = endTimeStamp - startTimeStamp; elapsed += elapsedThisPeriod; isRunning = false; if (elapsed < 0) { // When measuring small time periods the StopWatch.Elapsed* // properties can return negative values. This is due to // bugs in the basic input/output system (BIOS) or the hardware // abstraction layer (HAL) on machines with variable-speed CPUs // (e.g. Intel SpeedStep). elapsed = 0; } if (CPUTimeIsAvailable && elapsedCPU > 0) { timerEndCPUID = Win32.GetCurrentProcessorNumber(); if (timerEndCPUID != timerStartCPUID) { // Exposed as the FinishedOnDifferentProcessor property // Stopwatch cannot detect context switches in general, // but we do know at least one context switch occurred in this case // cpuSwitchOccurred = true; } PROCESSOR_POWER_INFORMATION thisppi = CPUPowerWrapper.GetCurrentPowerInfoforProcessor(); timerEndCurrentMHz = thisppi.CurrentMhz; timerEndMaxMHz = thisppi.MaxMhz; if (timerStartCurrentMHz != timerEndCurrentMHz) // CPU speed change detected { // Exposed as the PowerManagementChangeOccurred property // so long as the rdtsc is constant across power management events, // this is no cause for concern cpuspeedChangeOccurred = true; } } } }