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

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. npxstres.c
  5. Abstract:
  6. This test validates Npx state management and Npx exception handling.
  7. Author:
  8. Environment:
  9. User mode only.
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. int
  14. _cdecl
  15. main(
  16. int argc,
  17. char **argv
  18. )
  19. /*++
  20. Routine Description:
  21. Main function for npxstres.exe
  22. Arguments:
  23. argc - Argument count
  24. argv - Argument array
  25. Return Value:
  26. zero for success, nonzero for non low resource failures.
  27. --*/
  28. {
  29. HANDLE *hThreadArray;
  30. DWORD dwThreadId, i, threadCount;
  31. TEST_INFO testInfo;
  32. FILE *handle;
  33. printf("Npxstres.exe <threads>\n (returns errmask, zero if none)\n\n");
  34. if (argc > 1) {
  35. threadCount = atoi(argv[1]);
  36. } else {
  37. threadCount = DEF_NUM_THREADS;
  38. }
  39. hThreadArray = (HANDLE *) malloc(sizeof(HANDLE)*threadCount);
  40. if (hThreadArray == NULL) {
  41. printf("Insufficient memory to test\n");
  42. return 0;
  43. }
  44. __try {
  45. InitializeCriticalSection(&testInfo.Crit);
  46. } __except(EXCEPTION_EXECUTE_HANDLER) {
  47. printf("Insufficient memory to test\n");
  48. return 0;
  49. }
  50. printf("Running FPU tests using %d threads", threadCount);
  51. testInfo.FailureFlags = 0;
  52. DoFpPreinitTest(&testInfo, 0);
  53. for(i=0; i<threadCount; i++) {
  54. hThreadArray[i] = CreateThread(
  55. NULL,
  56. 0,
  57. FpThread,
  58. (LPVOID) &testInfo,
  59. 0,
  60. &dwThreadId
  61. );
  62. }
  63. WaitForMultipleObjects(threadCount, hThreadArray, TRUE, INFINITE);
  64. DeleteCriticalSection(&testInfo.Crit);
  65. for (i=0; i<threadCount; i++) {
  66. CloseHandle(hThreadArray[i]);
  67. }
  68. handle = testInfo.FailureFlags ? stderr : stdout;
  69. fprintf(handle, "\n\n\n");
  70. fprintf(handle, "Test Summary:\n");
  71. fprintf(handle, "-------------\n");
  72. PrintResult(handle, "Dirty preinit test:", &testInfo, FAILURECASE_DIRTY_PREINIT);
  73. PrintResult(handle, "Clean preinit test:", &testInfo, FAILURECASE_CLEAN_PREINIT);
  74. PrintResult(handle, "Control test:", &testInfo, FAILURECASE_CONTROL_CORRUPTION);
  75. PrintResult(handle, "Status test:", &testInfo, FAILURECASE_STATUS_CORRUPTION);
  76. PrintResult(handle, "STx test:", &testInfo, FAILURECASE_STX_CORRUPTION);
  77. PrintResult(handle, "Pending thrash test:", &testInfo, FAILURECASE_SPIN_PEND);
  78. PrintResult(handle, "Pending sleep test:", &testInfo, FAILURECASE_SLEEP_PEND);
  79. PrintResult(handle, "Pending API test:", &testInfo, FAILURECASE_API_PEND);
  80. free(hThreadArray);
  81. exit(testInfo.FailureFlags);
  82. }
  83. VOID
  84. PrintResult(
  85. IN FILE *Handle,
  86. IN LPTSTR TestText,
  87. IN PTEST_INFO TestInfo,
  88. IN ULONG FailureFlags
  89. )
  90. {
  91. fprintf(Handle, "%20s", TestText);
  92. if (TestInfo->FailureFlags & FailureFlags) {
  93. fprintf(Handle, "FAILED\n");
  94. } else {
  95. fprintf(Handle, "Pass\n");
  96. }
  97. }
  98. VOID
  99. SetFailureFlag(
  100. IN OUT PTEST_INFO TestInfo,
  101. IN ULONG FailureFlags
  102. )
  103. {
  104. EnterCriticalSection(&TestInfo->Crit);
  105. TestInfo->FailureFlags |= FailureFlags;
  106. LeaveCriticalSection(&TestInfo->Crit);
  107. }
  108. DWORD
  109. WINAPI
  110. FpThread(
  111. LPVOID Parameter
  112. )
  113. {
  114. DWORD i;
  115. PTEST_INFO pTestInfo;
  116. pTestInfo = (PTEST_INFO) Parameter;
  117. printf(".");
  118. DoFpPreinitTest(pTestInfo, PREINIT_FLAG_CLEANTHREAD);
  119. printf(".");
  120. DoFpControlCorruptionTest(pTestInfo);
  121. printf(".");
  122. DoFpStatusCorruptionTest(pTestInfo);
  123. printf(".");
  124. DoFpSt0CorruptionTest(pTestInfo);
  125. printf(".");
  126. DoPendingExceptionTest(pTestInfo, EXCEPTIONTEST_FLAG_SPIN, FAILURECASE_SPIN_PEND);
  127. printf(".");
  128. DoPendingExceptionTest(pTestInfo, EXCEPTIONTEST_FLAG_SLEEP, FAILURECASE_SLEEP_PEND);
  129. printf(".");
  130. DoPendingExceptionTest(pTestInfo, EXCEPTIONTEST_FLAG_CALL_KERNEL_FP, FAILURECASE_API_PEND);
  131. return 0;
  132. }
  133. VOID
  134. DoPendingExceptionTest(
  135. IN PTEST_INFO TestInfo,
  136. IN ULONG ExceptionTestFlags,
  137. IN ULONG FailureCode
  138. )
  139. {
  140. unsigned int i, count;
  141. FPXERR status;
  142. FP_THREAD_DATA fpThreadData;
  143. count = (ExceptionTestFlags & EXCEPTIONTEST_FLAG_SPIN) ? 200000 : 20000;
  144. FPxInit(&fpThreadData);
  145. for (i = 0; i < count; ++i) {
  146. status = FPxTestExceptions(i,
  147. FPxTestCallback,
  148. &fpThreadData,
  149. &ExceptionTestFlags);
  150. if (status != stOK) {
  151. fprintf(stderr, "\n\nNpx Exception Test Failed:\n");
  152. switch (status) {
  153. case stMISSING_EXCEPTION:
  154. fprintf(stderr, "Missing exception\n");
  155. break;
  156. case stMISSING_EXCEPTION_FOUND:
  157. fprintf(stderr, "Exception delayed unexpectedly\n");
  158. break;
  159. case stBAD_EIP:
  160. fprintf(stderr, "Unexpected exception at %08x (expected: %08x)\n", fpThreadData.BadEip, fpThreadData.ExpectedExceptionEIP);
  161. break;
  162. case stBAD_TAG:
  163. fprintf(stderr, "Bad tag value. Expected: %e Received: %e\n", fpThreadData.Ftag, fpThreadData.FtagBad);
  164. break;
  165. case stSPURIOUS_EXCEPTION:
  166. fprintf(stderr, "Unexpected Exception at: %08x\n", fpThreadData.ExceptionEIP);
  167. break;
  168. case stEXCEPTION_IN_HANDLER:
  169. fprintf(stderr, "Exception in exception handler at: %08x\n", fpThreadData.ExceptionEIP);
  170. break;
  171. default:
  172. fprintf(stderr, "Unknown status\n");
  173. break;
  174. }
  175. SetFailureFlag(TestInfo, FailureCode);
  176. return;
  177. }
  178. }
  179. }
  180. VOID
  181. DoFpControlCorruptionTest(
  182. IN OUT PTEST_INFO TestInfo
  183. )
  184. {
  185. int i;
  186. unsigned short cw1, cw2;
  187. int troubledetected;
  188. troubledetected = 0;
  189. for(i = 0; i < 250; i++) {
  190. // unmask zero divide exception
  191. _asm {
  192. fnstcw [cw1]
  193. xor [cw1], 4
  194. fldcw [cw1]
  195. }
  196. KModeTouchNpx();
  197. _asm {
  198. fnstcw [cw2]
  199. }
  200. if (cw1 != cw2) {
  201. troubledetected = 1;
  202. break;
  203. }
  204. //fprintf(stderr, "Control pass %d.\n", i);
  205. }
  206. if (troubledetected) {
  207. fprintf(stderr, "\n\nFP control corruption detected.\n");
  208. SetFailureFlag(TestInfo, FAILURECASE_CONTROL_CORRUPTION);
  209. }
  210. }
  211. VOID
  212. DoFpStatusCorruptionTest(
  213. IN OUT PTEST_INFO TestInfo
  214. )
  215. {
  216. int i;
  217. unsigned short sw1, sw2;
  218. int troubledetected;
  219. troubledetected = 0;
  220. for(i = 0; i < 250; i++) {
  221. _asm {
  222. fnstsw [sw1]
  223. }
  224. KModeTouchNpx();
  225. _asm {
  226. fnstsw [sw2]
  227. }
  228. if (sw1 != sw2) {
  229. troubledetected = 1;
  230. break;
  231. }
  232. //fprintf(stderr, "Status pass %d.\n", i);
  233. }
  234. if (troubledetected) {
  235. fprintf(stderr, "\n\nFP status corruption detected.\n");
  236. SetFailureFlag(TestInfo, FAILURECASE_STATUS_CORRUPTION);
  237. }
  238. }
  239. VOID
  240. DoFpSt0CorruptionTest(
  241. IN OUT PTEST_INFO TestInfo
  242. )
  243. {
  244. int i;
  245. unsigned short sw;
  246. int troubledetected;
  247. troubledetected = 0;
  248. //
  249. // This particular test is somewhat hoaky is in theory ST0 isn't callee
  250. // save. However, we know exactly what the below API does, so in this case
  251. // it's valid.
  252. //
  253. for(i = 0; i < 250; i++) {
  254. switch(i%3) {
  255. case 0:
  256. _asm {
  257. fld1
  258. fld1
  259. }
  260. break;
  261. case 1:
  262. _asm {
  263. fldpi
  264. fldpi
  265. }
  266. break;
  267. case 2:
  268. _asm {
  269. fldz
  270. fldz
  271. }
  272. break;
  273. }
  274. KModeTouchNpx();
  275. _asm {
  276. fucom
  277. fstsw [sw]
  278. }
  279. if (!(sw & 0x4000)) {
  280. troubledetected = 1;
  281. }
  282. switch(i%3) {
  283. case 0:
  284. _asm fld1
  285. break;
  286. case 1:
  287. _asm fldpi
  288. break;
  289. case 2:
  290. _asm fldz
  291. break;
  292. }
  293. _asm {
  294. fucom
  295. fstsw [sw]
  296. }
  297. if (!(sw & 0x4000)) {
  298. troubledetected = 1;
  299. }
  300. if (troubledetected) {
  301. break;
  302. }
  303. //fprintf(stderr, "STx pass %d.\n", i);
  304. }
  305. if (troubledetected) {
  306. fprintf(stderr, "\n\nFP register corruption detected.\n");
  307. SetFailureFlag(TestInfo, FAILURECASE_STX_CORRUPTION);
  308. }
  309. }
  310. VOID
  311. DoFpPreinitTest(
  312. IN OUT PTEST_INFO TestInfo,
  313. IN ULONG PreInitTestFlags
  314. )
  315. {
  316. unsigned short cw, sw;
  317. ULONG failureCode;
  318. failureCode = (PreInitTestFlags & PREINIT_FLAG_CLEANTHREAD) ?
  319. FAILURECASE_CLEAN_PREINIT : FAILURECASE_DIRTY_PREINIT;
  320. //
  321. // No FP should be used at this point.
  322. //
  323. KModeTouchNpx();
  324. _asm {
  325. fnstcw [cw]
  326. fnstsw [sw]
  327. }
  328. if (cw != 0x27F) {
  329. fprintf(
  330. stderr,
  331. "\n\nPre-init corruption detected, incorrect precision in control word (cw = %x)\n",
  332. cw
  333. );
  334. SetFailureFlag(TestInfo, failureCode);
  335. return;
  336. }
  337. if ((PreInitTestFlags&PREINIT_FLAG_CLEANTHREAD) && (sw != 0)) {
  338. fprintf(
  339. stderr,
  340. "\n\nPre-init corruption detected, status word should be zero on a clean thread (sw = %x)\n",
  341. sw
  342. );
  343. SetFailureFlag(TestInfo, failureCode);
  344. return;
  345. }
  346. }
  347. VOID
  348. FPxTestCallback(
  349. IN PVOID Context
  350. )
  351. {
  352. ULONG exceptionTestFlags;
  353. unsigned int j;
  354. exceptionTestFlags = *((PULONG) Context);
  355. if (exceptionTestFlags & EXCEPTIONTEST_FLAG_SLEEP) {
  356. //
  357. // Release time slice
  358. //
  359. Sleep(0);
  360. }
  361. if (exceptionTestFlags & EXCEPTIONTEST_FLAG_CALL_KERNEL_FP) {
  362. //
  363. // Use FP in K-Mode
  364. //
  365. KModeTouchNpx();
  366. }
  367. if (exceptionTestFlags & EXCEPTIONTEST_FLAG_SPIN) {
  368. j=0x1000;
  369. while(j) j--;
  370. }
  371. }