windows-nt/Source/XPSP1/NT/sdktools/cpustres/stresdlg.cpp
2020-09-26 16:20:57 +08:00

721 lines
18 KiB
C++

// StresDlg.cpp : implementation file
//
#include "stdafx.h"
#include "CpuStres.h"
#include "StresDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CStressDlg dialog
CStressDlg::CStressDlg(CWnd* pParent /*=NULL*/)
: CDialog(CStressDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CStressDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_dwProcessPriority = NORMAL_PRIORITY_CLASS;
m_ActivityValue[0] = SLOW_ACTIVITY;
m_ActivityValue[1] = SLOW_ACTIVITY;
m_ActivityValue[2] = SLOW_ACTIVITY;
m_ActivityValue[3] = SLOW_ACTIVITY;
m_PriorityValue[0] = THREAD_PRIORITY_NORMAL;
m_PriorityValue[1] = THREAD_PRIORITY_NORMAL;
m_PriorityValue[2] = THREAD_PRIORITY_NORMAL;
m_PriorityValue[3] = THREAD_PRIORITY_NORMAL;
m_Active[0] = TRUE;
m_Active[1] = FALSE;
m_Active[2] = FALSE;
m_Active[3] = FALSE;
m_ThreadHandle[0] = NULL;
m_ThreadHandle[1] = NULL;
m_ThreadHandle[2] = NULL;
m_ThreadHandle[3] = NULL;
m_dwLoopValue = 0x00010000;
m_pMemory = NULL;
m_dwVASize = 0;
m_dwRandomScale = 1;
}
void CStressDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CStressDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CStressDlg, CDialog)
//{{AFX_MSG_MAP(CStressDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_1_ACTIVE, On1Active)
ON_CBN_SELCHANGE(IDC_1_ACTIVITY, OnSelchange1Activity)
ON_CBN_SELCHANGE(IDC_1_PRIORITY, OnSelchange1Priority)
ON_BN_CLICKED(IDC_2_ACTIVE, On2Active)
ON_CBN_SELCHANGE(IDC_2_ACTIVITY, OnSelchange2Activity)
ON_CBN_SELCHANGE(IDC_2_PRIORITY, OnSelchange2Priority)
ON_BN_CLICKED(IDC_3_ACTIVE, On3Active)
ON_CBN_SELCHANGE(IDC_3_ACTIVITY, OnSelchange3Activity)
ON_CBN_SELCHANGE(IDC_3_PRIORITY, OnSelchange3Priority)
ON_BN_CLICKED(IDC_4_ACTIVE, On4Active)
ON_CBN_SELCHANGE(IDC_4_ACTIVITY, OnSelchange4Activity)
ON_CBN_SELCHANGE(IDC_4_PRIORITY, OnSelchange4Priority)
ON_CBN_SELCHANGE(IDC_PROCESS_PRIORITY, OnSelchangeProcessPriority)
ON_EN_KILLFOCUS(IDC_SHARED_MEM_SIZE, OnKillfocusSharedMemSize)
ON_EN_CHANGE(IDC_SHARED_MEM_SIZE, OnChangeSharedMemSize)
ON_BN_CLICKED(IDC_USE_MEMORY, OnUseMemory)
ON_WM_CLOSE()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// disable optimization since it will remove the "do-nothing" loops
#pragma optimize ("", off)
DWORD CStressDlg::OnePercentCalibration(DWORD dwLoopValue)
{
// find how many loops consume 10% of this processor
LARGE_INTEGER liPerfFreq;
LONGLONG llOnePercent;
LARGE_INTEGER liStartTime;
LARGE_INTEGER liEndTime;
LONGLONG llDiff;
LONGLONG llMinDiff;
DWORD dwPriorityClass;
DWORD dwThreadPriority;
HANDLE hProcess;
HANDLE hThread;
DWORD dwLoopCounter;
DWORD dwReturn;
LONGLONG llResult;
BOOL bGoodSample = FALSE;
DWORD dwAttemptCount = 5;
dwReturn = dwLoopValue;
QueryPerformanceFrequency (&liPerfFreq);
llOnePercent = liPerfFreq.QuadPart / 100;
// the calibration run must take at least 50 ms
llMinDiff = liPerfFreq.QuadPart / 20;
hProcess = GetCurrentProcess();
hThread = GetCurrentThread();
dwPriorityClass = GetPriorityClass (hProcess);
dwThreadPriority = GetThreadPriority (hThread);
SetPriorityClass (hProcess, HIGH_PRIORITY_CLASS);
SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST);
while (!bGoodSample && dwAttemptCount) {
// start timing
QueryPerformanceCounter (&liStartTime);
// do a trial loop
for (dwLoopCounter = dwLoopValue; dwLoopCounter; dwLoopCounter--);
// end timing
QueryPerformanceCounter (&liEndTime);
llDiff = liEndTime.QuadPart - liStartTime.QuadPart;
if (llDiff > llMinDiff) {
bGoodSample = TRUE;
} else {
// increase the loop counter value by a factor of 10
dwLoopValue *= 10;
dwAttemptCount--;
}
}
// restore the priority since we're done with the critical part
SetPriorityClass (hProcess, dwPriorityClass);
SetThreadPriority (hThread, dwThreadPriority);
if (!bGoodSample) {
MessageBox("Unable to calibrate delay loop");
} else {
// findout what the 1% count is
if (llDiff != llOnePercent) {
// then adjust the initial loop value was too big so reduce
llResult = llOnePercent * dwLoopValue / llDiff;
if (llResult & 0xFFFFFFFF00000000) {
// this processor is TOO FAST! so don't change.
} else {
dwReturn = (DWORD)(llResult & 0x00000000FFFFFFFF);
}
}
}
return dwReturn;
}
DWORD WorkerProc (LPDWORD dwArg)
{
DWORD dwLoopCounter;
LPTHREAD_INFO_BLOCK pInfo;
DWORD dwStartingValue;
DWORD dwLocalValue;
DWORD dwLocalIndex;
pInfo = (LPTHREAD_INFO_BLOCK)dwArg;
dwStartingValue = pInfo->Dlg->m_dwLoopValue;
srand( (unsigned)time( NULL ) );
while (pInfo->Dlg->m_Active[pInfo->dwId]) {
for (dwLoopCounter = dwStartingValue; dwLoopCounter; dwLoopCounter--) {
if (pInfo->Dlg->m_pMemory != NULL) {
do {
dwLocalIndex = rand();
dwLocalIndex *= pInfo->Dlg->m_dwRandomScale;
} while (dwLocalIndex >= pInfo->Dlg->m_dwVASize);
pInfo->Dlg->m_pMemory[dwLocalIndex] = dwLocalIndex;
dwLocalValue = pInfo->Dlg->m_pMemory[dwLocalIndex];
// reduce loop iterations to account for
// accessing memory
if (pInfo->Dlg->m_Active[pInfo->dwId]) {
if (dwLoopCounter > 20) {
dwLoopCounter -= 20;
} else {
dwLoopCounter = 1;
}
} else {
break; // out of loop
}
}
}
if (pInfo->Dlg->m_ActivityValue[pInfo->dwId] > 0) {
Sleep (pInfo->Dlg->m_ActivityValue[pInfo->dwId]);
}
}
pInfo->Dlg->m_ThreadHandle[pInfo->dwId] = NULL;
delete pInfo;
return 0;
}
#pragma optimize ("", on)
void CStressDlg::CreateWorkerThread (DWORD dwId)
{
DWORD dwThreadId;
LPTHREAD_INFO_BLOCK pInfo;
// then start a new thread
pInfo = new THREAD_INFO_BLOCK;
if (!pInfo) {
return;
}
pInfo->Dlg = this;
pInfo->dwId = dwId;
m_Active[dwId] = TRUE;
m_ThreadHandle[dwId] = CreateThread (
NULL, 0,
(LPTHREAD_START_ROUTINE)WorkerProc,
(LPVOID)pInfo, 0, &dwThreadId);
if (m_ThreadHandle[dwId] == NULL) {
m_Active[dwId] = FALSE;
delete pInfo;
} else {
// establish thread priority
SetThreadPriority (
m_ThreadHandle[dwId],
m_PriorityValue[dwId]);
}
}
void CStressDlg::SetThreadActivity (CComboBox * cActivityCombo, DWORD dwId)
{
switch (cActivityCombo->GetCurSel()) {
case 0:
m_ActivityValue[dwId] = SLOW_ACTIVITY;
break;
case 1:
m_ActivityValue[dwId] = MEDIUM_ACTIVITY;
break;
case 2:
m_ActivityValue[dwId] = HIGH_ACTIVITY;
break;
case 3:
m_ActivityValue[dwId] = HOG_ACTIVITY;
break;
}
}
void CStressDlg::SetThreadPriorityLevel (CComboBox * cPriorityCombo, DWORD dwId)
{
LONG lLastError = ERROR_SUCCESS;
switch (cPriorityCombo->GetCurSel()) {
case 0:
m_PriorityValue[dwId] = (DWORD)THREAD_PRIORITY_IDLE;
break;
case 1:
m_PriorityValue[dwId] = (DWORD)THREAD_PRIORITY_LOWEST;
break;
case 2:
m_PriorityValue[dwId] = (DWORD)THREAD_PRIORITY_BELOW_NORMAL;
break;
case 3:
m_PriorityValue[dwId] = (DWORD)THREAD_PRIORITY_NORMAL;
break;
case 4:
m_PriorityValue[dwId] = (DWORD)THREAD_PRIORITY_ABOVE_NORMAL;
break;
case 5:
m_PriorityValue[dwId] = (DWORD)THREAD_PRIORITY_HIGHEST;
break;
case 6:
m_PriorityValue[dwId] = (DWORD)THREAD_PRIORITY_TIME_CRITICAL;
break;
}
if (m_ThreadHandle[dwId] != NULL) {
if (!SetThreadPriority (m_ThreadHandle[dwId], m_PriorityValue[dwId])) {
lLastError = GetLastError ();
}
} // else no thread open
}
/////////////////////////////////////////////////////////////////////////////
// CStressDlg message handlers
BOOL CStressDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
// calibrate loop counter
m_dwLoopValue = OnePercentCalibration (m_dwLoopValue) * 10;
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// set the priority of this thread to "highest" so the UI will be
// responsive
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
// enable thread 1 & disable all others
((CComboBox *)GetDlgItem(IDC_PROCESS_PRIORITY))->SetCurSel(1);
CheckDlgButton (IDC_1_ACTIVE, 1);
((CComboBox *)GetDlgItem(IDC_1_PRIORITY))->SetCurSel(3);
((CComboBox *)GetDlgItem(IDC_1_ACTIVITY))->SetCurSel(0);
CheckDlgButton (IDC_2_ACTIVE, 0);
((CComboBox *)GetDlgItem(IDC_2_PRIORITY))->SetCurSel(3);
((CComboBox *)GetDlgItem(IDC_2_ACTIVITY))->SetCurSel(0);
CheckDlgButton (IDC_3_ACTIVE, 0);
((CComboBox *)GetDlgItem(IDC_3_PRIORITY))->SetCurSel(3);
((CComboBox *)GetDlgItem(IDC_3_ACTIVITY))->SetCurSel(0);
CheckDlgButton (IDC_4_ACTIVE, 0);
((CComboBox *)GetDlgItem(IDC_4_PRIORITY))->SetCurSel(3);
((CComboBox *)GetDlgItem(IDC_4_ACTIVITY))->SetCurSel(0);
// set the process priority
OnSelchangeProcessPriority();
// start the first thread
On1Active();
// don't access memory by default
CheckDlgButton (IDC_USE_MEMORY, 0);
(GetDlgItem (IDC_SHARED_MEM_SIZE))->EnableWindow (FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CStressDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CStressDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CStressDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CStressDlg::On1Active()
{
DWORD dwId = 0;
if (IsDlgButtonChecked(IDC_1_ACTIVE)) {
if (m_ThreadHandle[dwId] == NULL) {
CreateWorkerThread (dwId);
} else {
// thread is already running
}
} else {
m_Active[dwId] = FALSE;
m_ThreadHandle[dwId] = NULL;
}
}
void CStressDlg::OnSelchange1Activity()
{
CComboBox * cActivityCombo;
DWORD dwId = 0;
cActivityCombo = (CComboBox *)GetDlgItem (IDC_1_ACTIVITY);
SetThreadActivity (cActivityCombo, dwId);
}
void CStressDlg::OnSelchange1Priority()
{
CComboBox * cPriorityCombo;
DWORD dwId = 0;
cPriorityCombo = (CComboBox *)GetDlgItem (IDC_1_PRIORITY);
SetThreadPriorityLevel (cPriorityCombo, dwId);
}
void CStressDlg::On2Active()
{
DWORD dwId = 1;
if (IsDlgButtonChecked(IDC_2_ACTIVE)) {
if (m_ThreadHandle[dwId] == NULL) {
CreateWorkerThread (dwId);
} else {
// thread is already running
}
} else {
m_Active[dwId] = FALSE;
m_ThreadHandle[dwId] = NULL;
}
}
void CStressDlg::OnSelchange2Activity()
{
CComboBox * cActivityCombo;
DWORD dwId = 1;
cActivityCombo = (CComboBox *)GetDlgItem (IDC_2_ACTIVITY);
SetThreadActivity (cActivityCombo, dwId);
}
void CStressDlg::OnSelchange2Priority()
{
CComboBox * cPriorityCombo;
DWORD dwId = 1;
cPriorityCombo = (CComboBox *)GetDlgItem (IDC_2_PRIORITY);
SetThreadPriorityLevel (cPriorityCombo, dwId);
}
void CStressDlg::On3Active()
{
DWORD dwId = 2;
if (IsDlgButtonChecked(IDC_3_ACTIVE)) {
if (m_ThreadHandle[dwId] == NULL) {
CreateWorkerThread (dwId);
} else {
// thread is already running
}
} else {
m_Active[dwId] = FALSE;
m_ThreadHandle[dwId] = NULL;
}
}
void CStressDlg::OnSelchange3Activity()
{
CComboBox * cActivityCombo;
DWORD dwId = 2;
cActivityCombo = (CComboBox *)GetDlgItem (IDC_3_ACTIVITY);
SetThreadActivity (cActivityCombo, dwId);
}
void CStressDlg::OnSelchange3Priority()
{
CComboBox * cPriorityCombo;
DWORD dwId = 2;
cPriorityCombo = (CComboBox *)GetDlgItem (IDC_3_PRIORITY);
SetThreadPriorityLevel (cPriorityCombo, dwId);
}
void CStressDlg::On4Active()
{
DWORD dwId = 3;
if (IsDlgButtonChecked(IDC_4_ACTIVE)) {
if (m_ThreadHandle[dwId] == NULL) {
CreateWorkerThread (dwId);
} else {
// thread is already running
}
} else {
m_Active[dwId] = FALSE;
CloseHandle (m_ThreadHandle[dwId]);
m_ThreadHandle[dwId] = NULL;
}
}
void CStressDlg::OnSelchange4Activity()
{
CComboBox * cActivityCombo;
DWORD dwId = 3;
cActivityCombo = (CComboBox *)GetDlgItem (IDC_4_ACTIVITY);
SetThreadActivity (cActivityCombo, dwId);
}
void CStressDlg::OnSelchange4Priority()
{
CComboBox * cPriorityCombo;
DWORD dwId = 3;
cPriorityCombo = (CComboBox *)GetDlgItem (IDC_4_PRIORITY);
SetThreadPriorityLevel (cPriorityCombo, dwId);
}
void CStressDlg::OnOK()
{
CDialog::OnOK();
}
void CStressDlg::OnSelchangeProcessPriority()
{
CComboBox * cPriorityCombo;
DWORD dwPriorityClass;
cPriorityCombo = (CComboBox *)GetDlgItem (IDC_PROCESS_PRIORITY);
switch (cPriorityCombo->GetCurSel()) {
case 0:
dwPriorityClass = IDLE_PRIORITY_CLASS;
break;
case 1:
dwPriorityClass = NORMAL_PRIORITY_CLASS;
break;
case 2:
dwPriorityClass = HIGH_PRIORITY_CLASS;
break;
}
SetPriorityClass (GetCurrentProcess(), dwPriorityClass);
}
void CStressDlg::OnKillfocusSharedMemSize()
{
return;
}
void CStressDlg::OnChangeSharedMemSize()
{
CString csMemSize;
TCHAR szOldValue[MAX_PATH];
DWORD dwMemSize;
csMemSize.Empty();
GetDlgItemText (IDC_SHARED_MEM_SIZE, csMemSize);
dwMemSize = _tcstoul ((LPCTSTR)csMemSize, NULL, 10);
dwMemSize *= 1024 / sizeof(DWORD);
if (dwMemSize != m_dwVASize) {
// threads must be stopped to change memory size
if (m_Active[0] || m_Active[1] || m_Active[2] || m_Active[3]) {
MessageBox (
TEXT("All threads must be stopped before this value can be changed"));
_stprintf (szOldValue, TEXT("%d"), ((m_dwVASize * sizeof(DWORD))/1024));
(GetDlgItem(IDC_SHARED_MEM_SIZE))->SetWindowText(szOldValue);
return;
} else {
if (m_pMemory != NULL) {
delete (m_pMemory);
m_pMemory = NULL;
m_dwVASize = 0;
}
m_dwVASize = dwMemSize;
m_pMemory = new DWORD[m_dwVASize];
if (m_pMemory == NULL) {
m_dwVASize = 0;
}
}
}
}
void CStressDlg::OnUseMemory()
{
CString csMemSize;
DWORD dwMemSize;
BOOL bState;
if (m_Active[0] || m_Active[1] || m_Active[2] || m_Active[3]) {
MessageBox (TEXT("All threads must be stopped before this value can be changed"));
bState = !IsDlgButtonChecked(IDC_USE_MEMORY); //revert state
} else {
if (IsDlgButtonChecked(IDC_USE_MEMORY)) {
// if no memory is allocated, then allocate it
if (m_pMemory != NULL) {
delete (m_pMemory);
m_pMemory = NULL;
m_dwVASize = 0;
}
//get va size
csMemSize.Empty();
GetDlgItemText (IDC_SHARED_MEM_SIZE, csMemSize);
dwMemSize = _tcstoul ((LPCTSTR)csMemSize, NULL, 10);
m_dwVASize = dwMemSize * 1024 / sizeof(DWORD);
m_pMemory = new DWORD[m_dwVASize];
if (m_pMemory == NULL) {
m_dwVASize = 0;
} else {
m_dwRandomScale = (m_dwVASize / RAND_MAX) + 1;
}
bState = TRUE;
} else {
// button is unchecked so free memory
if (m_pMemory != NULL) {
delete (m_pMemory);
m_pMemory = NULL;
m_dwVASize = 0;
}
bState = FALSE;
}
}
CheckDlgButton (IDC_USE_MEMORY, bState);
(GetDlgItem (IDC_SHARED_MEM_SIZE))->EnableWindow (bState);
}
void CStressDlg::OnClose()
{
// stop threads first
m_Active[0] = FALSE;
m_Active[1] = FALSE;
m_Active[2] = FALSE;
m_Active[3] = FALSE;
// wait for the threads to finish
while (m_ThreadHandle[0] || m_ThreadHandle[1] ||
m_ThreadHandle[2] || m_ThreadHandle[3]) {
Sleep(100);
}
// free memory block
if (m_pMemory != NULL) {
delete (m_pMemory);
m_pMemory = NULL;
m_dwVASize = 0;
}
CDialog::OnClose();
}
void CStressDlg::OnDestroy()
{
CDialog::OnDestroy();
}