/*
Copyright (c) 2006, Intel Corporation.

This Intel Laptop Gaming TDK ("Software") is furnished under license and may 
only be used or copied in accordance with the terms of that license. No license, 
express or implied, by estoppel or otherwise, to any intellectual property rights 
is granted by this document. The Software is subject to change without notice, 
and should not be construed as a commitment by Intel Corporation to market, 
license, sell or support any product or technology. Unless otherwise provided 
for in the license under which this Software is provided, the Software is 
provided AS IS, with no warranties of any kind, express or implied. 
Except as expressly permitted by the Software license, neither Intel Corporation 
nor its suppliers assumes any responsibility or liability for any errors or 
inaccuracies that may appear herein. Except as expressly permitted by the 
Software license, no part of the Software may be reproduced, stored in a 
retrieval system, transmitted in any form, or distributed by any means 
without the express written consent of Intel Corporation.
*/

/**
* This class provides methods to access various properties in the Processor system
* resource. This class provides access to methods like number of cores, number of 
* processors, CPU utilization, current freq and max freq. Some of the properties are
* available by event driven model as well. In this case, the TDK will spawn additional
* threads and send notification back to caller 
*/

#ifndef ILGPROCESSORINFO_H
#define ILGPROCESSORINFO_H

#define _WIN32_DCOM
#include <comdef.h>
#include <Wbemidl.h>
#include <atlstr.h>
#include "ILGAbstractEventInfo.h"

#pragma warning( disable : 4275 )

#define NUM_CORE_BITS    0xfc000000  //(or (0xFC << 26) )
#define MAXPATH 255

typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)(LPVOID lParam);
typedef unsigned *PBEGINTHREADEX_THAREDID;

class  ProcessorInfo : public AbstractEventInfo
{

public:
	// Constructor
	ProcessorInfo();
	
	/**
	* Destructor
	*/
	~ProcessorInfo();

	/**
	* This function gets number of cores per processor
	*/
	unsigned int GetNumCoresPerProcessor();

	/**
	* This function gets total number of processors on the system
	* including logical and physical
	*/
	unsigned int GetNumProcessors();

	/** 
	* This function takes in process name such as "iexplore" and returns
	* number of active threads for the process. If the function fails, it 
	* returns -1, if the input is invalid it returns -2
	*/
	int GetNumActiveThreadsForProcess(const char* ProcessName);

	/**
	* This function returns total current CPU utilization averaging each CPU
	*/
	int GetCurrentCPUUtilization(int CpuNum = -1);

	/**
	* This function returns current freq at which the CPU is running
	*/
	unsigned long GetCurrentCPUFrequency();
	
	/**
	* This returns max freq at which CPU could run
	*/
	unsigned long GetMaxCPUFrequency();

	/**
	* This function starts a monitoring thread of a desired event. This function is
	* defined in base class and the 3rd parameter is by default turned off. This
	* is used in cases where there an event needs to watch for a certain threshold 
	* value
	*/
	void Start(int event, Notifiable* m_pNot, int lpThreshold = -1, int UpdateFreq = 2000);

	/**
	* This function stops a monitoring thread of a desired event
	*/
	void Stop(int event);

private:
	typedef struct _PROCESSOR_POWER_INFORMATION {
      ULONG Number;
      ULONG MaxMhz;
      ULONG CurrentMhz;
      ULONG MhzLimit;
      ULONG MaxIdleState;
      ULONG CurrentIdleState;
	} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;

	unsigned long max_frequency_Mhz;
	unsigned long current_frequency_Mhz;
 
	PROCESSOR_POWER_INFORMATION ppi;
	bool bCheckCores;
	bool bCheckProcessor;

	unsigned int m_numCores;
	unsigned int m_numProcessors;

	CRITICAL_SECTION m_cs;

	// Thread function for polling CPU utilization
	static DWORD WINAPI ThreadFuncCPUUtil(LPVOID ThreadParam);

	// non-static function that the thread function calls to poll CPU utilization
	void ThreadMonitorCPUUtil(Notifiable* pNotif, int frequency, int ProcNum);

	// Thread function for polling CPU frequency
	static DWORD WINAPI ThreadFuncCPUFreq(LPVOID ThreadParam);

	// non-static function that the thread function calls to poll CPU frequency
	void ThreadMonitorCPUFreq(Notifiable* pNotif, int frequency);

	// parameters for two threads. Defined in base file
	// structure to pass to thread functions including this pointer for the class 
	// pointer to call back observer and threshold paramater.
	ThreadParamStruct pStruct[2];

	// Bool variable to poll CPU utilization
	bool bMonitorCPUUtil;

	// Bool variable to poll CPU Frequency
	bool bMonitorCPUFreq;

	// Thread handle
	HANDLE h[2];

	// Bool variables to check if the threads are already running
	bool bThread0Running, bThread1Running;

	// Bool variables to end the thread when objects are destroyed.
	bool bEndThread0, bEndThread1;

	// Bool variable to make sure COM initialization is successful before
	// calling methods
	static bool bInitSuccessful;

	// Bool variable to keep track if the initial COM model was used
	static bool bOrigCOMUsed;
};

#endif 