Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

521 lines
11 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
npxstres.c
Abstract:
This test validates Npx state management and Npx exception handling.
Author:
Environment:
User mode only.
Revision History:
--*/
#include "pch.h"
int
_cdecl
main(
int argc,
char **argv
)
/*++
Routine Description:
Main function for npxstres.exe
Arguments:
argc - Argument count
argv - Argument array
Return Value:
zero for success, nonzero for non low resource failures.
--*/
{
HANDLE *hThreadArray;
DWORD dwThreadId, i, threadCount;
TEST_INFO testInfo;
FILE *handle;
printf("Npxstres.exe <threads>\n (returns errmask, zero if none)\n\n");
if (argc > 1) {
threadCount = atoi(argv[1]);
} else {
threadCount = DEF_NUM_THREADS;
}
hThreadArray = (HANDLE *) malloc(sizeof(HANDLE)*threadCount);
if (hThreadArray == NULL) {
printf("Insufficient memory to test\n");
return 0;
}
__try {
InitializeCriticalSection(&testInfo.Crit);
} __except(EXCEPTION_EXECUTE_HANDLER) {
printf("Insufficient memory to test\n");
return 0;
}
printf("Running FPU tests using %d threads", threadCount);
testInfo.FailureFlags = 0;
DoFpPreinitTest(&testInfo, 0);
for(i=0; i<threadCount; i++) {
hThreadArray[i] = CreateThread(
NULL,
0,
FpThread,
(LPVOID) &testInfo,
0,
&dwThreadId
);
}
WaitForMultipleObjects(threadCount, hThreadArray, TRUE, INFINITE);
DeleteCriticalSection(&testInfo.Crit);
for (i=0; i<threadCount; i++) {
CloseHandle(hThreadArray[i]);
}
handle = testInfo.FailureFlags ? stderr : stdout;
fprintf(handle, "\n\n\n");
fprintf(handle, "Test Summary:\n");
fprintf(handle, "-------------\n");
PrintResult(handle, "Dirty preinit test:", &testInfo, FAILURECASE_DIRTY_PREINIT);
PrintResult(handle, "Clean preinit test:", &testInfo, FAILURECASE_CLEAN_PREINIT);
PrintResult(handle, "Control test:", &testInfo, FAILURECASE_CONTROL_CORRUPTION);
PrintResult(handle, "Status test:", &testInfo, FAILURECASE_STATUS_CORRUPTION);
PrintResult(handle, "STx test:", &testInfo, FAILURECASE_STX_CORRUPTION);
PrintResult(handle, "Pending thrash test:", &testInfo, FAILURECASE_SPIN_PEND);
PrintResult(handle, "Pending sleep test:", &testInfo, FAILURECASE_SLEEP_PEND);
PrintResult(handle, "Pending API test:", &testInfo, FAILURECASE_API_PEND);
free(hThreadArray);
exit(testInfo.FailureFlags);
}
VOID
PrintResult(
IN FILE *Handle,
IN LPTSTR TestText,
IN PTEST_INFO TestInfo,
IN ULONG FailureFlags
)
{
fprintf(Handle, "%20s", TestText);
if (TestInfo->FailureFlags & FailureFlags) {
fprintf(Handle, "FAILED\n");
} else {
fprintf(Handle, "Pass\n");
}
}
VOID
SetFailureFlag(
IN OUT PTEST_INFO TestInfo,
IN ULONG FailureFlags
)
{
EnterCriticalSection(&TestInfo->Crit);
TestInfo->FailureFlags |= FailureFlags;
LeaveCriticalSection(&TestInfo->Crit);
}
DWORD
WINAPI
FpThread(
LPVOID Parameter
)
{
DWORD i;
PTEST_INFO pTestInfo;
pTestInfo = (PTEST_INFO) Parameter;
printf(".");
DoFpPreinitTest(pTestInfo, PREINIT_FLAG_CLEANTHREAD);
printf(".");
DoFpControlCorruptionTest(pTestInfo);
printf(".");
DoFpStatusCorruptionTest(pTestInfo);
printf(".");
DoFpSt0CorruptionTest(pTestInfo);
printf(".");
DoPendingExceptionTest(pTestInfo, EXCEPTIONTEST_FLAG_SPIN, FAILURECASE_SPIN_PEND);
printf(".");
DoPendingExceptionTest(pTestInfo, EXCEPTIONTEST_FLAG_SLEEP, FAILURECASE_SLEEP_PEND);
printf(".");
DoPendingExceptionTest(pTestInfo, EXCEPTIONTEST_FLAG_CALL_KERNEL_FP, FAILURECASE_API_PEND);
return 0;
}
VOID
DoPendingExceptionTest(
IN PTEST_INFO TestInfo,
IN ULONG ExceptionTestFlags,
IN ULONG FailureCode
)
{
unsigned int i, count;
FPXERR status;
FP_THREAD_DATA fpThreadData;
count = (ExceptionTestFlags & EXCEPTIONTEST_FLAG_SPIN) ? 200000 : 20000;
FPxInit(&fpThreadData);
for (i = 0; i < count; ++i) {
status = FPxTestExceptions(i,
FPxTestCallback,
&fpThreadData,
&ExceptionTestFlags);
if (status != stOK) {
fprintf(stderr, "\n\nNpx Exception Test Failed:\n");
switch (status) {
case stMISSING_EXCEPTION:
fprintf(stderr, "Missing exception\n");
break;
case stMISSING_EXCEPTION_FOUND:
fprintf(stderr, "Exception delayed unexpectedly\n");
break;
case stBAD_EIP:
fprintf(stderr, "Unexpected exception at %08x (expected: %08x)\n", fpThreadData.BadEip, fpThreadData.ExpectedExceptionEIP);
break;
case stBAD_TAG:
fprintf(stderr, "Bad tag value. Expected: %e Received: %e\n", fpThreadData.Ftag, fpThreadData.FtagBad);
break;
case stSPURIOUS_EXCEPTION:
fprintf(stderr, "Unexpected Exception at: %08x\n", fpThreadData.ExceptionEIP);
break;
case stEXCEPTION_IN_HANDLER:
fprintf(stderr, "Exception in exception handler at: %08x\n", fpThreadData.ExceptionEIP);
break;
default:
fprintf(stderr, "Unknown status\n");
break;
}
SetFailureFlag(TestInfo, FailureCode);
return;
}
}
}
VOID
DoFpControlCorruptionTest(
IN OUT PTEST_INFO TestInfo
)
{
int i;
unsigned short cw1, cw2;
int troubledetected;
troubledetected = 0;
for(i = 0; i < 250; i++) {
// unmask zero divide exception
_asm {
fnstcw [cw1]
xor [cw1], 4
fldcw [cw1]
}
KModeTouchNpx();
_asm {
fnstcw [cw2]
}
if (cw1 != cw2) {
troubledetected = 1;
break;
}
//fprintf(stderr, "Control pass %d.\n", i);
}
if (troubledetected) {
fprintf(stderr, "\n\nFP control corruption detected.\n");
SetFailureFlag(TestInfo, FAILURECASE_CONTROL_CORRUPTION);
}
}
VOID
DoFpStatusCorruptionTest(
IN OUT PTEST_INFO TestInfo
)
{
int i;
unsigned short sw1, sw2;
int troubledetected;
troubledetected = 0;
for(i = 0; i < 250; i++) {
_asm {
fnstsw [sw1]
}
KModeTouchNpx();
_asm {
fnstsw [sw2]
}
if (sw1 != sw2) {
troubledetected = 1;
break;
}
//fprintf(stderr, "Status pass %d.\n", i);
}
if (troubledetected) {
fprintf(stderr, "\n\nFP status corruption detected.\n");
SetFailureFlag(TestInfo, FAILURECASE_STATUS_CORRUPTION);
}
}
VOID
DoFpSt0CorruptionTest(
IN OUT PTEST_INFO TestInfo
)
{
int i;
unsigned short sw;
int troubledetected;
troubledetected = 0;
//
// This particular test is somewhat hoaky is in theory ST0 isn't callee
// save. However, we know exactly what the below API does, so in this case
// it's valid.
//
for(i = 0; i < 250; i++) {
switch(i%3) {
case 0:
_asm {
fld1
fld1
}
break;
case 1:
_asm {
fldpi
fldpi
}
break;
case 2:
_asm {
fldz
fldz
}
break;
}
KModeTouchNpx();
_asm {
fucom
fstsw [sw]
}
if (!(sw & 0x4000)) {
troubledetected = 1;
}
switch(i%3) {
case 0:
_asm fld1
break;
case 1:
_asm fldpi
break;
case 2:
_asm fldz
break;
}
_asm {
fucom
fstsw [sw]
}
if (!(sw & 0x4000)) {
troubledetected = 1;
}
if (troubledetected) {
break;
}
//fprintf(stderr, "STx pass %d.\n", i);
}
if (troubledetected) {
fprintf(stderr, "\n\nFP register corruption detected.\n");
SetFailureFlag(TestInfo, FAILURECASE_STX_CORRUPTION);
}
}
VOID
DoFpPreinitTest(
IN OUT PTEST_INFO TestInfo,
IN ULONG PreInitTestFlags
)
{
unsigned short cw, sw;
ULONG failureCode;
failureCode = (PreInitTestFlags & PREINIT_FLAG_CLEANTHREAD) ?
FAILURECASE_CLEAN_PREINIT : FAILURECASE_DIRTY_PREINIT;
//
// No FP should be used at this point.
//
KModeTouchNpx();
_asm {
fnstcw [cw]
fnstsw [sw]
}
if (cw != 0x27F) {
fprintf(
stderr,
"\n\nPre-init corruption detected, incorrect precision in control word (cw = %x)\n",
cw
);
SetFailureFlag(TestInfo, failureCode);
return;
}
if ((PreInitTestFlags&PREINIT_FLAG_CLEANTHREAD) && (sw != 0)) {
fprintf(
stderr,
"\n\nPre-init corruption detected, status word should be zero on a clean thread (sw = %x)\n",
sw
);
SetFailureFlag(TestInfo, failureCode);
return;
}
}
VOID
FPxTestCallback(
IN PVOID Context
)
{
ULONG exceptionTestFlags;
unsigned int j;
exceptionTestFlags = *((PULONG) Context);
if (exceptionTestFlags & EXCEPTIONTEST_FLAG_SLEEP) {
//
// Release time slice
//
Sleep(0);
}
if (exceptionTestFlags & EXCEPTIONTEST_FLAG_CALL_KERNEL_FP) {
//
// Use FP in K-Mode
//
KModeTouchNpx();
}
if (exceptionTestFlags & EXCEPTIONTEST_FLAG_SPIN) {
j=0x1000;
while(j) j--;
}
}