Windows NT 4.0 source code leak
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.

729 lines
19 KiB

4 years ago
  1. #ifdef WIN32
  2. #include <windows.h>
  3. #define delay(a) Sleep((a))
  4. #else
  5. #define INCL_BASE
  6. #define INCL_DOSSEMAPHORES
  7. #include <os2.h>
  8. #define delay(a) DosSleep((a))
  9. #define GetTickCount clock
  10. #endif
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include "mptest.h"
  14. THREADDATA ThreadData [MAXTHREADS];
  15. #ifdef WIN32
  16. HANDLE ThreadEvents [MAXTHREADS];
  17. HANDLE BeginTest;
  18. HANDLE InitializeTest;
  19. HANDLE TestComplete;
  20. #else
  21. SEMRECORD ThreadEvents1 [MAXTHREADS];
  22. SEMRECORD ThreadEvents2 [MAXTHREADS];
  23. TID ThreadHandles[MAXTHREADS];
  24. HMUX MuxWait1;
  25. HMUX MuxWait2;
  26. HEV BeginTest;
  27. HEV InitializeTest;
  28. HEV TestComplete;
  29. #pragma linkage(WorkerThread,system)
  30. #endif
  31. unsigned long MaxThreads;
  32. unsigned long CurThreads;
  33. unsigned long TestParam;
  34. unsigned long RunNo;
  35. unsigned long MaxTest;
  36. unsigned long TestsSpecified;
  37. unsigned long MultIter = 1;
  38. VOID (* InitThreadForTest)(PTHREADDATA, unsigned char);
  39. unsigned long (* RunTestThread)(PTHREADDATA);
  40. void RunTest (ULONG TestNo);
  41. void
  42. WorkerThread (
  43. PTHREADDATA p
  44. );
  45. unsigned char TestError;
  46. unsigned char Verbose;
  47. struct {
  48. unsigned long Flag;
  49. char *Title;
  50. void (* InitFnc)(PTHREADDATA, unsigned char);
  51. unsigned long (* TestFnc)(PTHREADDATA);
  52. unsigned long Param;
  53. } TestTable[] = {
  54. 1, "Read Cell U", UniqueValue, R3ReadCell, 0,
  55. 0, "R/W Cell U", UniqueValue, R3ReadWriteCell, 0,
  56. 0, "WriteCell U", UniqueValue, R3WriteCell, 0,
  57. 1, "Interlock U", UniqueValue, R3Interlock, 0,
  58. 0, "Interlock S", CommonValue, R3Interlock, 0,
  59. 0, "CacheLine S", DoNothing, R3MemShare, 0,
  60. 0, "M Comp 64K ", DoNothing, R3MemCompare, 0,
  61. 0, "M Copy 64k ", DoNothing, R3MemCopy, 0,
  62. 1, "SReads 64 ", UniqueFile, TestSeqReads, 64,
  63. 0, "SReads 512 ", UniqueFile, TestSeqReads, 512,
  64. 0, "SReads 4K ", UniqueFile, TestSeqReads, 4096,
  65. 0, "SReads 32K ", UniqueFile, TestSeqReads, 32768,
  66. 1, "SWrite 512 ", UniqueFile, TestSeqWrites, 512,
  67. 0, "SWrite 4k ", UniqueFile, TestSeqWrites, 4096,
  68. 0, "SWrite 32k ", UniqueFile, TestSeqWrites, 32768,
  69. /*
  70. 0, "Tx I/Os ", CommonFile, TxIOs, 0,
  71. 1, "Processes ", DoNothing, TxIOs, 0,
  72. 0, "Threads ", DoNothing, TxIOs, 0,
  73. 0, "LPC ", DoNothing, TxIOs, 0,
  74. */
  75. 0,NULL, NULL, NULL, 0
  76. };
  77. #define F_SKIPLINE 0x01
  78. #define F_RUNIT 0x02
  79. void
  80. WorkerThread (
  81. PTHREADDATA p
  82. )
  83. {
  84. ULONG l;
  85. VOID (* LastInitialization)(PTHREADDATA,unsigned char);
  86. #ifdef WIN32
  87. HANDLE OurEvent;
  88. #else
  89. PSEMRECORD OurEvent;
  90. #endif
  91. #ifdef WIN32
  92. OurEvent = ThreadEvents[p->ThreadNumber];
  93. //
  94. // Are we testing a specific processor?
  95. //
  96. if (p->ThreadAffinity) {
  97. SetThreadAffinityMask (GetCurrentThread (), p->ThreadAffinity);
  98. }
  99. #else
  100. OurEvent = &ThreadEvents1[p->ThreadNumber];
  101. #endif
  102. LastInitialization = NULL;
  103. p->Buffer1 = malloc (32768 + 512);
  104. p->Buffer1 = (PUCHAR) ((ULONG) p->Buffer1 & ~0x7f) + 0x80;
  105. p->Buffer2 = malloc (32768 + 512);
  106. p->Buffer2 = (PUCHAR) ((ULONG) p->Buffer2 & ~0x7f) + 0x80;
  107. memset (p->Buffer1, 0xAA, 32768);
  108. memset (p->Buffer2, 0x22, 32768);
  109. for (; ;) {
  110. /* signal we are waiting and wait for initialize signal */
  111. #ifdef WIN32
  112. SetEvent (OurEvent);
  113. WaitForSingleObject (InitializeTest, WAIT_FOREVER);
  114. #else
  115. DosPostEventSem(OurEvent->hsemCur);
  116. DosWaitEventSem(InitializeTest, SEM_INDEFINITE_WAIT);
  117. #endif
  118. if (InitThreadForTest != LastInitialization) {
  119. /* initialize this thread for the test */
  120. InitThreadForTest (p, TRUE);
  121. LastInitialization = InitThreadForTest;
  122. }
  123. #ifdef WIN32
  124. /* signal we are waiting */
  125. SetEvent (OurEvent);
  126. #else
  127. DosPostEventSem(OurEvent->hsemCur);
  128. #endif
  129. if (p->ThreadNumber < CurThreads) {
  130. InitThreadForTest (p, FALSE);
  131. /* wait for signal to begin test */
  132. #ifdef WIN32
  133. WaitForSingleObject (BeginTest, WAIT_FOREVER);
  134. #else
  135. DosWaitEventSem(BeginTest, SEM_INDEFINITE_WAIT);
  136. #endif
  137. /* start benchmark */
  138. p->StartTime = GetTickCount();
  139. /* run the requested test */
  140. l = RunTestThread (p);
  141. /* end benchmark */
  142. p->FinishTime = GetTickCount();
  143. /* pause for settle time after test */
  144. if (l) {
  145. if (l == -1) {
  146. TestError = TRUE;
  147. } else {
  148. delay (l);
  149. }
  150. }
  151. #ifdef WIN32
  152. /* signal we are complete */
  153. SetEvent (OurEvent);
  154. #else
  155. DosPostEventSem(OurEvent->hsemCur);
  156. #endif
  157. }
  158. #ifdef WIN32
  159. WaitForSingleObject (TestComplete, WAIT_FOREVER);
  160. #else
  161. DosWaitEventSem(TestComplete, SEM_INDEFINITE_WAIT);
  162. #endif
  163. }
  164. }
  165. VOID Usage()
  166. {
  167. printf ("mptest [-a P1 P2 ... Pn | -p n] [-t T1 T2 ... Tn] [-m n]\n");
  168. printf (" -a = affinity Thread1 to P1, Thread2 to P2, etc..\n");
  169. printf (" -p = use 'n' threads with no affinity setting. (default is 2)\n");
  170. printf (" -t = run test T1, T2, ... (default is all tests)\n");
  171. printf (" -m = multiple test interactions by n (must be whole number)\n");
  172. exit (1);
  173. }
  174. VOID
  175. #ifdef WIN32
  176. _CRTAPI1
  177. #endif
  178. main(argc, argv)
  179. int argc;
  180. char **argv;
  181. {
  182. ULONG i, l, f, state;
  183. PUCHAR pt;
  184. printf ("\n");
  185. for (MaxTest = 0; TestTable[MaxTest].Title; MaxTest++) ;
  186. MaxThreads = 2;
  187. state = 3;
  188. while (--argc) {
  189. argv++;
  190. if (argv[0][0] == '?') {
  191. Usage();
  192. }
  193. pt = *argv;
  194. if (*pt == '-') {
  195. state = 0;
  196. if (pt[1] >= 'a') {
  197. pt[1] -= ('a' - 'A');
  198. }
  199. switch (pt[1]) {
  200. case 'A':
  201. MaxThreads = 0;
  202. state = 1;
  203. break;
  204. case 'P': state = 2; break;
  205. case 'T': state = 3; break;
  206. case 'M': state = 4; break;
  207. default:
  208. printf ("mptest: flag %c not understood\n", pt[1]);
  209. Usage();
  210. }
  211. pt += 2;
  212. }
  213. if (!*pt) {
  214. continue;
  215. }
  216. l = atoi(pt);
  217. switch (state) {
  218. case 1:
  219. #ifdef WIN32
  220. f = 1 << (l - 1);
  221. if (!SetThreadAffinityMask (GetCurrentThread (), f)) {
  222. printf ("mptest: Invalid affinity value %d\n", l);
  223. exit (1);
  224. }
  225. ThreadData[MaxThreads].ThreadAffinity = l;
  226. MaxThreads += 1;
  227. printf ("Test thread %d runs only on processor %d\n", MaxThreads, l);
  228. #else
  229. printf ("affinity setting not supported\n");
  230. #endif
  231. break;
  232. case 2:
  233. MaxThreads = l;
  234. break;
  235. case 3:
  236. if (l > MaxTest) {
  237. printf ("mptest: unkown test # %d\n", l);
  238. } else {
  239. TestsSpecified = 1;
  240. TestTable[l].Flag |= F_RUNIT;
  241. }
  242. break;
  243. case 4:
  244. MultIter = l;
  245. break;
  246. }
  247. }
  248. if (MultIter != 1) {
  249. printf ("Iterations multiplied by: %d\n", MultIter);
  250. }
  251. #ifdef WIN32
  252. /* create event for thread to wait for */
  253. BeginTest = CreateEvent(NULL,TRUE,FALSE,NULL);
  254. InitializeTest = CreateEvent(NULL,TRUE,FALSE,NULL);
  255. TestComplete = CreateEvent(NULL,TRUE,FALSE,NULL);
  256. #else
  257. DosCreateEventSem(NULL,&BeginTest,DC_SEM_SHARED,FALSE);
  258. DosCreateEventSem(NULL,&InitializeTest,DC_SEM_SHARED,FALSE);
  259. DosCreateEventSem(NULL,&TestComplete,DC_SEM_SHARED,FALSE);
  260. #endif
  261. /* start each thread */
  262. for(i=0; i < MaxThreads; i++) {
  263. ThreadData[i].ThreadNumber = i;
  264. #ifdef WIN32
  265. ThreadEvents[i] = CreateEvent(NULL,FALSE,FALSE,NULL);
  266. ThreadData[i].ThreadHandle = CreateThread (NULL, 0,
  267. (LPTHREAD_START_ROUTINE) WorkerThread,
  268. (LPVOID) &ThreadData[i],
  269. 0,
  270. &ThreadData[i].ThreadId );
  271. #else
  272. DosCreateEventSem(NULL, &ThreadEvents1[i].hsemCur, FALSE, NULL);
  273. DosCreateThread(&ThreadHandles[i],WorkerThread,&ThreadData[i],0,8192);
  274. #endif
  275. }
  276. f = 0;
  277. for (i = 0; TestTable[i].Title; i++) {
  278. f |= TestTable[i].Flag;
  279. if (TestsSpecified && !(TestTable[i].Flag & F_RUNIT)) {
  280. continue;
  281. }
  282. if (f & F_SKIPLINE) {
  283. f = 0;
  284. printf ("\n");
  285. }
  286. RunTest (i);
  287. }
  288. }
  289. void
  290. RunTest (ULONG TestNo)
  291. {
  292. ULONG sum;
  293. ULONG SingleThreadTime;
  294. LONG l;
  295. double scaled;
  296. char s[20];
  297. ULONG ulPostCount;
  298. ULONG ulUser;
  299. ULONG i;
  300. TestParam = TestTable[TestNo].Param;
  301. InitThreadForTest = TestTable[TestNo].InitFnc;
  302. RunTestThread = TestTable[TestNo].TestFnc;
  303. printf ("%2d %s", TestNo, TestTable[TestNo].Title);
  304. #ifndef WIN32
  305. DosCreateMuxWaitSem(NULL, &MuxWait1, MaxThreads, &ThreadEvents1[0], DCMW_WAIT_ALL);
  306. #endif
  307. for (CurThreads=1; CurThreads <= MaxThreads; CurThreads++) {
  308. RunNo++;
  309. #ifdef WIN32
  310. /* wait for all threads signal they are waiting */
  311. WaitForMultipleObjects(MaxThreads, ThreadEvents, TRUE, WAIT_FOREVER);
  312. ResetEvent(TestComplete);
  313. SetEvent (InitializeTest); /* let the threads initialize for test */
  314. /* wait for all threads signal they have initialized for the test */
  315. WaitForMultipleObjects(MaxThreads, ThreadEvents, TRUE, WAIT_FOREVER);
  316. ResetEvent(InitializeTest);
  317. delay (100); /* settle */
  318. SetEvent (BeginTest); /* wake thread to start test now */
  319. /* wait for the threads to complete */
  320. WaitForMultipleObjects(CurThreads, ThreadEvents, TRUE, WAIT_FOREVER);
  321. ResetEvent(BeginTest);
  322. #else
  323. DosCreateMuxWaitSem(NULL, &MuxWait2, CurThreads, &ThreadEvents1[0], DCMW_WAIT_ALL);
  324. DosResetEventSem(TestComplete, &ulPostCount);
  325. /* wait for all threads signal they are waiting */
  326. DosWaitMuxWaitSem(MuxWait1, SEM_INDEFINITE_WAIT, &ulUser);
  327. for (i=0;i<MaxThreads;i++) {
  328. DosResetEventSem(ThreadEvents1[i].hsemCur, &ulPostCount);
  329. }
  330. DosPostEventSem(InitializeTest); /* let the threads initialize */
  331. /* wait for all threads signal they are initialized */
  332. DosWaitMuxWaitSem(MuxWait1, SEM_INDEFINITE_WAIT, &ulUser);
  333. DosResetEventSem(InitializeTest, &ulPostCount);
  334. for (i=0;i<MaxThreads;i++) {
  335. DosResetEventSem(ThreadEvents1[i].hsemCur, &ulPostCount);
  336. }
  337. delay(100); /* settle */
  338. DosPostEventSem(BeginTest); /* wake threads to start test now */
  339. /* wait for the threads to complete */
  340. DosWaitMuxWaitSem(MuxWait2, SEM_INDEFINITE_WAIT, &ulUser);
  341. DosResetEventSem(BeginTest, &ulPostCount);
  342. for (i=0;i<CurThreads;i++) {
  343. DosResetEventSem(ThreadEvents1[i].hsemCur, &ulPostCount);
  344. }
  345. #endif
  346. if (TestError) {
  347. TestError = FALSE;
  348. printf ("*ERR*");
  349. CurThreads = MaxThreads+1; /* abort rest of sequence */
  350. } else {
  351. /*
  352. ** Calculate average runtime
  353. */
  354. sum = 0;
  355. for (i = 0; i < CurThreads; i++) {
  356. sum += ThreadData[i].FinishTime - ThreadData[i].StartTime;
  357. }
  358. sum = sum / CurThreads;
  359. if (Verbose) {
  360. /*
  361. ** Print each thread's runtime
  362. */
  363. printf ("\n %d ", CurThreads);
  364. for (i = 0; i < CurThreads; i++) {
  365. l = ThreadData[i].FinishTime - ThreadData[i].StartTime;
  366. printf ("[%ld]\t", l);
  367. }
  368. } else {
  369. printf ("%6ld ", sum);
  370. if (CurThreads == 1) {
  371. SingleThreadTime = sum;
  372. } else {
  373. if (SingleThreadTime == 0) {
  374. printf (" ");
  375. } else {
  376. l = SingleThreadTime * CurThreads; /* projected time */
  377. l = l - sum; /* time savings */
  378. scaled = (double) l / sum * 100.0;
  379. sprintf (s, "%#+.1f", scaled);
  380. i = strlen(s);
  381. i = 9 - (i < 5 ? 5 : i);
  382. printf ("%5s%-*s", s, i, "%");
  383. }
  384. }
  385. }
  386. }
  387. #ifdef WIN32
  388. SetEvent (TestComplete);
  389. #else
  390. DosPostEventSem(TestComplete);
  391. DosCloseMuxWaitSem(MuxWait2);
  392. #endif
  393. }
  394. printf ("\n");
  395. }
  396. VOID DoNothing (PTHREADDATA p, unsigned char f)
  397. {
  398. }
  399. VOID CommonFile (PTHREADDATA p, unsigned char f)
  400. {
  401. }
  402. VOID UniqueFile (PTHREADDATA p, unsigned char f)
  403. {
  404. #ifdef WIN32
  405. HANDLE h;
  406. OFSTRUCT OpnInf;
  407. #else
  408. HFILE h;
  409. APIRET rv;
  410. ULONG ulAction;
  411. #endif
  412. char s[30];
  413. unsigned long i;
  414. ULONG ByteCount;
  415. if (!p->UniqueFile) {
  416. /*
  417. ** Create unique file for this thread
  418. */
  419. sprintf (s, "Test%d.tmp", p->ThreadNumber);
  420. #ifdef WIN32
  421. h = OpenFile (s, &OpnInf, OF_CREATE | OF_READWRITE | OF_SHARE_DENY_NONE);
  422. if (h == (HANDLE) -1) {
  423. printf ("Create of %s failed\n", s);
  424. TestError = TRUE;
  425. return;
  426. }
  427. #if 0
  428. h = CreateFile(s,
  429. GENERIC_READ | GENERIC_WRITE,
  430. FILE_SHARE_READ | FILE_SHARE_WRITE,
  431. NULL,
  432. OPEN_ALWAYS,
  433. 0,
  434. NULL);
  435. if (h == INVALID_HANDLE_VALUE) {
  436. fprintf (stderr,"Create of %s failed %d\n", s,GetLastError());
  437. TestError = TRUE;
  438. return;
  439. }
  440. #endif
  441. #else
  442. rv = DosOpen(s,
  443. &h,
  444. &ulAction,
  445. 0,
  446. 0,
  447. 0x11,
  448. OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
  449. 0);
  450. if (rv) {
  451. fprintf (stderr,"Create of %s failed %d\n", s,rv);
  452. TestError = TRUE;
  453. return;
  454. }
  455. #endif
  456. p->UniqueFile = h;
  457. /*
  458. ** Fill in blank contents 512*256 bytes (128K)
  459. */
  460. for (i=0; i < 256; i++) {
  461. #ifdef WIN32
  462. WriteFile(h, p->Buffer1, 512, &ByteCount,NULL);
  463. #else
  464. DosWrite(h, p->Buffer1, 512, &ByteCount);
  465. #endif
  466. }
  467. delay (5000); /* allow lazy writter to write file */
  468. }
  469. p->CurIoHandle = p->UniqueFile;
  470. if (!f) {
  471. /* not global initialization
  472. ** read file to get it into the filesystem's cache
  473. */
  474. for (i=0; i < 256; i++) {
  475. #ifdef WIN32
  476. ReadFile(h, p->Buffer1, 512, &ByteCount, NULL);
  477. #else
  478. DosRead(h, p->Buffer1, 512, &ByteCount);
  479. #endif
  480. }
  481. }
  482. }
  483. ULONG TestSeqReads (PTHREADDATA p)
  484. {
  485. ULONG i, j;
  486. ULONG status, iter, flen;
  487. ULONG ByteCount;
  488. #ifdef WIN32
  489. HANDLE h;
  490. #else
  491. HFILE h;
  492. APIRET rv;
  493. ULONG ulNew;
  494. #endif
  495. h = p->UniqueFile;
  496. flen = 128*1024 / TestParam;
  497. iter = (flen < 512 ? 500 : 100) * MultIter;
  498. for (i=0; i < iter; i++) {
  499. #ifdef WIN32
  500. status = SetFilePointer(h,0,0,FILE_BEGIN);
  501. if (status == -1) {
  502. printf("TestSeqReads: seek to 0 failed %d\n",GetLastError());
  503. return (ULONG) -1;
  504. }
  505. for (j=0; j < flen; j++) {
  506. status = ReadFile(h, p->Buffer1, TestParam, &ByteCount, NULL);
  507. if (!status) {
  508. printf("TestSeqReads: ReadFile %d failed %d\n",TestParam,GetLastError());
  509. return (ULONG) -1;
  510. }
  511. }
  512. #else
  513. rv = DosSetFilePtr(h,0,0,&ulNew);
  514. if (rv) {
  515. printf("TestSeqReads: seek to 0 failed %d\n",rv);
  516. return -1;
  517. }
  518. for (j=0; j < flen; j++) {
  519. rv = DosRead(h, p->Buffer1, TestParam, &ByteCount);
  520. if (rv) {
  521. printf("TestSeqReads: ReadFile %d failed %d\n",TestParam,rv);
  522. return (ULONG) -1;
  523. }
  524. }
  525. #endif
  526. }
  527. return 0;
  528. }
  529. ULONG TestSeqWrites (PTHREADDATA p)
  530. {
  531. int i, j;
  532. ULONG status, flen, iter;
  533. ULONG ByteCount;
  534. #ifdef WIN32
  535. HANDLE h;
  536. #else
  537. HFILE h;
  538. APIRET rv;
  539. ULONG ulNew;
  540. #endif
  541. h = p->UniqueFile;
  542. flen = 128*1024 / TestParam;
  543. iter = (flen < 512 ? 500 : 100) * MultIter;
  544. for (i=0; i < iter; i++) {
  545. #ifdef WIN32
  546. status = SetFilePointer(h,0,0,FILE_BEGIN);
  547. if (status == -1) {
  548. printf("TestSeqWrites: seek to 0 failed %d\n",GetLastError());
  549. return (ULONG) -1;
  550. }
  551. for (j=0; j < flen; j++) {
  552. status = WriteFile(h, p->Buffer2, TestParam, &ByteCount, NULL);
  553. if (!status) {
  554. printf("TestSeqWrites: WriteFile %d failed %d\n",TestParam,GetLastError());
  555. return (ULONG) -1;
  556. }
  557. }
  558. #else
  559. rv = DosSetFilePtr(h,0,0,&ulNew);
  560. if (rv) {
  561. printf("TestSeqWrites: seek to 0 failed %d\n",rv);
  562. return (ULONG) -1;
  563. }
  564. for (j=0; j < flen; j++) {
  565. rv = DosWrite(h, p->Buffer2, TestParam, &ByteCount);
  566. if (rv) {
  567. printf("TestSeqWrites: WriteFile %d failed %d\n",TestParam,rv);
  568. return (ULONG) -1;
  569. }
  570. }
  571. #endif
  572. #ifdef WIN32
  573. status = SetFilePointer(h,0,0,FILE_BEGIN);
  574. if (status == -1) {
  575. printf("TestSeqWrites: seek to 0 failed %d\n",GetLastError());
  576. return (ULONG) -1;
  577. }
  578. for (j=0; j < flen; j++) {
  579. status = WriteFile(h, p->Buffer1, TestParam, &ByteCount, NULL);
  580. if (!status) {
  581. printf("TestSeqWrites: WriteFile %d failed %d\n",TestParam,GetLastError());
  582. return (ULONG) -1;
  583. }
  584. }
  585. #else
  586. rv = DosSetFilePtr(h,0,0,&ulNew);
  587. if (rv) {
  588. printf("TestSeqWrites: seek to 0 failed %d\n",rv);
  589. return (ULONG) -1;
  590. }
  591. for (j=0; j < flen; j++) {
  592. rv = DosWrite(h, p->Buffer1, TestParam, &ByteCount);
  593. if (rv) {
  594. printf("TestSeqWrites: WriteFile %d failed %d\n",TestParam,rv);
  595. return (ULONG) -1;
  596. }
  597. }
  598. #endif
  599. }
  600. return 5000;
  601. }