utmrtest.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. utmrtest.c
  9. Abstract:
  10. This module implements the tests used to verify that user mode timers are
  11. functioning properly.
  12. Author:
  13. Evan Green 11-Aug-2012
  14. Environment:
  15. User Mode
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/lib/minocaos.h>
  21. #include <assert.h>
  22. #include <errno.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sys/time.h>
  27. #include <time.h>
  28. #include <unistd.h>
  29. #include <pthread.h>
  30. //
  31. // --------------------------------------------------------------------- Macros
  32. //
  33. #define DEBUG_PRINT(...) \
  34. if (TimerTestVerbose != FALSE) { \
  35. printf(__VA_ARGS__); \
  36. }
  37. #define PRINT_ERROR(...) printf(__VA_ARGS__)
  38. //
  39. // ---------------------------------------------------------------- Definitions
  40. //
  41. //
  42. // Define the number of timers to fire up.
  43. //
  44. #define TEST_TIMER_COUNT 50
  45. //
  46. // Define the number of time ticks all the timers should get up to.
  47. //
  48. #define TEST_TIMER_GOAL 50
  49. //
  50. // Define the test timer period.
  51. //
  52. #define TEST_TIMER_PERIOD_SECONDS 0
  53. #define TEST_TIMER_PERIOD_NANOSECONDS 250000000
  54. //
  55. // Define the waiting period of the test.
  56. //
  57. #define TEST_TIMER_TIMEOUT ((LONGLONG)500)
  58. //
  59. // Define how often progress gets printed in verbose mode.
  60. //
  61. #define TEST_TIMER_UPDATE_INTERVAL 5
  62. //
  63. // Define the number of timers and threads to fire up.
  64. //
  65. #define TEST_THREAD_TIMER_COUNT 50
  66. //
  67. // Define the number of time ticks all the thread timers should get up to.
  68. //
  69. #define TEST_THREAD_TIMER_GOAL 50
  70. //
  71. // ------------------------------------------------------ Data Type Definitions
  72. //
  73. //
  74. // ----------------------------------------------- Internal Function Prototypes
  75. //
  76. ULONG
  77. RunAllTimerTests (
  78. VOID
  79. );
  80. ULONG
  81. RunTimerTest (
  82. VOID
  83. );
  84. ULONG
  85. RunITimerTest (
  86. VOID
  87. );
  88. ULONG
  89. RunThreadTimerTest (
  90. VOID
  91. );
  92. VOID
  93. ITimerTestSignalHandler (
  94. INT SignalNumber
  95. );
  96. VOID
  97. TimerTestAlarmSignalHandler (
  98. INT SignalNumber,
  99. siginfo_t *Information,
  100. void *SomethingElse
  101. );
  102. void *
  103. TimerThreadTestStartRoutine (
  104. void *Parameter
  105. );
  106. VOID
  107. TimerThreadTestAlarmSignalHandler (
  108. INT SignalNumber,
  109. siginfo_t *Information,
  110. void *SomethingElse
  111. );
  112. //
  113. // -------------------------------------------------------------------- Globals
  114. //
  115. //
  116. // Set this to TRUE to enable more verbose debug output.
  117. //
  118. BOOL TimerTestVerbose = TRUE;
  119. //
  120. // Store the test timers.
  121. //
  122. timer_t TestTimers[TEST_TIMER_COUNT];
  123. volatile int TestTimerCount[TEST_TIMER_COUNT];
  124. volatile int TestTimerSignals[NSIG];
  125. int TestITimerTypes[3] = {
  126. ITIMER_REAL,
  127. ITIMER_VIRTUAL,
  128. ITIMER_PROF
  129. };
  130. int TestITimerTypeSignals[3] = {
  131. SIGALRM,
  132. SIGVTALRM,
  133. SIGPROF
  134. };
  135. //
  136. // Store the timer thread test timers and threads.
  137. //
  138. pthread_t TestThreads[TEST_THREAD_TIMER_COUNT];
  139. timer_t TestThreadTimers[TEST_THREAD_TIMER_COUNT];
  140. volatile int TestThreadTimerCount[TEST_THREAD_TIMER_COUNT];
  141. //
  142. // ------------------------------------------------------------------ Functions
  143. //
  144. int
  145. main (
  146. int ArgumentCount,
  147. char **Arguments
  148. )
  149. /*++
  150. Routine Description:
  151. This routine implements the signal test program.
  152. Arguments:
  153. ArgumentCount - Supplies the number of elements in the arguments array.
  154. Arguments - Supplies an array of strings. The array count is bounded by the
  155. previous parameter, and the strings are null-terminated.
  156. Return Value:
  157. 0 on success.
  158. Non-zero on failure.
  159. --*/
  160. {
  161. ULONG Failures;
  162. Failures = RunAllTimerTests();
  163. if (Failures == 0) {
  164. return 0;
  165. }
  166. return 1;
  167. }
  168. //
  169. // --------------------------------------------------------- Internal Functions
  170. //
  171. ULONG
  172. RunAllTimerTests (
  173. VOID
  174. )
  175. /*++
  176. Routine Description:
  177. This routine executes all timer tests.
  178. Arguments:
  179. None.
  180. Return Value:
  181. Returns the number of failures in the test suite.
  182. --*/
  183. {
  184. ULONG Failures;
  185. Failures = 0;
  186. Failures += RunTimerTest();
  187. if (Failures != 0) {
  188. PRINT_ERROR("*** %d failures in timer test. ***\n", Failures);
  189. }
  190. Failures += RunITimerTest();
  191. if (Failures != 0) {
  192. PRINT_ERROR("*** %d failures in itimer test. ***\n", Failures);
  193. }
  194. Failures += RunThreadTimerTest();
  195. if (Failures != 0) {
  196. PRINT_ERROR("*** %d failures in thread timer test. ***\n", Failures);
  197. }
  198. if (Failures == 0) {
  199. DEBUG_PRINT("All timer tests pass.\n");
  200. }
  201. return Failures;
  202. }
  203. ULONG
  204. RunTimerTest (
  205. VOID
  206. )
  207. /*++
  208. Routine Description:
  209. This routine tests user mode timers.
  210. Arguments:
  211. None.
  212. Return Value:
  213. Returns the number of failures in the test.
  214. --*/
  215. {
  216. struct sigaction Action;
  217. ULONGLONG CurrentTime;
  218. ULONGLONG EndTime;
  219. ULONG Failures;
  220. ULONGLONG Frequency;
  221. ULONGLONG LastUpdate;
  222. int MaxCount;
  223. ULONG MaxTimer;
  224. int MinCount;
  225. ULONG MinTimer;
  226. struct sigaction OriginalAction;
  227. struct itimerspec Rate;
  228. int Result;
  229. BOOL Stop;
  230. ULONG TimerIndex;
  231. Failures = 0;
  232. Stop = TRUE;
  233. //
  234. // Set up the signal handler.
  235. //
  236. Action.sa_sigaction = TimerTestAlarmSignalHandler;
  237. sigemptyset(&(Action.sa_mask));
  238. Action.sa_flags = SA_SIGINFO;
  239. Result = sigaction(SIGALRM, &Action, &OriginalAction);
  240. if (Result != 0) {
  241. PRINT_ERROR("TimerTest: sigaction failed: %s\n", strerror(errno));
  242. return 1;
  243. }
  244. //
  245. // Create a bunch of timers.
  246. //
  247. for (TimerIndex = 0; TimerIndex < TEST_TIMER_COUNT; TimerIndex += 1) {
  248. TestTimers[TimerIndex] = -1;
  249. Result = timer_create(CLOCK_REALTIME, NULL, &(TestTimers[TimerIndex]));
  250. if (Result != 0) {
  251. PRINT_ERROR("TimerTest: Failed to create timer: %s.\n",
  252. strerror(errno));
  253. Failures += 1;
  254. }
  255. }
  256. //
  257. // Arm them.
  258. //
  259. Rate.it_value.tv_sec = TEST_TIMER_PERIOD_SECONDS;
  260. Rate.it_value.tv_nsec = TEST_TIMER_PERIOD_NANOSECONDS;
  261. Rate.it_interval.tv_sec = TEST_TIMER_PERIOD_SECONDS;
  262. Rate.it_interval.tv_nsec = TEST_TIMER_PERIOD_NANOSECONDS;
  263. for (TimerIndex = 0; TimerIndex < TEST_TIMER_COUNT; TimerIndex += 1) {
  264. Result = timer_settime(TestTimers[TimerIndex], 0, &Rate, NULL);
  265. if (Result != 0) {
  266. PRINT_ERROR("TimerTest: Failed to create timer: %s.\n",
  267. strerror(errno));
  268. Failures += 1;
  269. }
  270. }
  271. //
  272. // Compute the timeout time.
  273. //
  274. Frequency = OsGetTimeCounterFrequency();
  275. EndTime = OsGetRecentTimeCounter() + (TEST_TIMER_TIMEOUT * Frequency);
  276. LastUpdate = OsGetRecentTimeCounter() / Frequency;
  277. while (OsGetRecentTimeCounter() < EndTime) {
  278. Stop = TRUE;
  279. MinTimer = -1;
  280. MinCount = MAX_LONG;
  281. MaxTimer = -1;
  282. MaxCount = 0;
  283. for (TimerIndex = 0; TimerIndex < TEST_TIMER_COUNT; TimerIndex += 1) {
  284. if (TestTimerCount[TimerIndex] < TEST_TIMER_GOAL) {
  285. Stop = FALSE;
  286. }
  287. if ((MinTimer == -1) || (TestTimerCount[TimerIndex] < MinCount)) {
  288. MinTimer = TimerIndex;
  289. MinCount = TestTimerCount[TimerIndex];
  290. }
  291. if ((MaxTimer == -1) || (TestTimerCount[TimerIndex] > MaxCount)) {
  292. MaxTimer = TimerIndex;
  293. MaxCount = TestTimerCount[TimerIndex];
  294. }
  295. }
  296. if (Stop != FALSE) {
  297. DEBUG_PRINT("All timers reached threshold.\n");
  298. break;
  299. }
  300. CurrentTime = OsGetRecentTimeCounter() / Frequency;
  301. if (CurrentTime - LastUpdate >= TEST_TIMER_UPDATE_INTERVAL) {
  302. DEBUG_PRINT("%I64d: Min count %d, timer %d. "
  303. "Max count %d, timer %d.\n",
  304. CurrentTime,
  305. MinCount,
  306. MinTimer,
  307. MaxCount,
  308. MaxTimer);
  309. fflush(NULL);
  310. LastUpdate = CurrentTime;
  311. }
  312. }
  313. if (Stop == FALSE) {
  314. PRINT_ERROR("TimerTest: Some timers did not count!\n");
  315. }
  316. //
  317. // Delete all the timers.
  318. //
  319. for (TimerIndex = 0; TimerIndex < TEST_TIMER_COUNT; TimerIndex += 1) {
  320. Result = timer_delete(TestTimers[TimerIndex]);
  321. if (Result != 0) {
  322. PRINT_ERROR("TimerTest: Failed to delete timer: %s.\n",
  323. strerror(errno));
  324. Failures += 1;
  325. }
  326. }
  327. //
  328. // Restore the signal handler.
  329. //
  330. Result = sigaction(SIGALRM, &OriginalAction, NULL);
  331. if (Result != 0) {
  332. PRINT_ERROR("TimerTest: Failed to restore SIGALRM: %s.\n",
  333. strerror(errno));
  334. Failures += 1;
  335. }
  336. return Failures;
  337. }
  338. ULONG
  339. RunITimerTest (
  340. VOID
  341. )
  342. /*++
  343. Routine Description:
  344. This routine tests user mode interval timers.
  345. Arguments:
  346. None.
  347. Return Value:
  348. Returns the number of failures in the test.
  349. --*/
  350. {
  351. struct sigaction Action;
  352. int Actual;
  353. struct timespec EndTime;
  354. int Expected;
  355. ULONG Failures;
  356. struct sigaction OldAlarm;
  357. struct sigaction OldProfile;
  358. struct sigaction OldVirtualAlarm;
  359. int Signal;
  360. struct timespec Time;
  361. int Tolerance;
  362. int Type;
  363. struct itimerval Value;
  364. Failures = 0;
  365. memset((void *)TestTimerSignals, 0, sizeof(TestTimerSignals));
  366. memset(&Action, 0, sizeof(Action));
  367. Action.sa_handler = ITimerTestSignalHandler;
  368. if ((sigaction(SIGALRM, &Action, &OldAlarm) != 0) ||
  369. (sigaction(SIGVTALRM, &Action, &OldVirtualAlarm) != 0) ||
  370. (sigaction(SIGPROF, &Action, &OldProfile) != 0)) {
  371. PRINT_ERROR("TimerTest: Failed to set signal handlers: %s.\n",
  372. strerror(errno));
  373. return 1;
  374. }
  375. //
  376. // Ensure that wacky values don't work.
  377. //
  378. memset(&Value, 0, sizeof(Value));
  379. if ((setitimer(33, &Value, NULL) != -1) || (errno != EINVAL)) {
  380. PRINT_ERROR("TimerTest: Wacky itimer type succeeded.\n");
  381. Failures += 1;
  382. }
  383. Value.it_value.tv_usec = 1000001;
  384. if ((setitimer(ITIMER_REAL, &Value, NULL) != -1) || (errno != EINVAL)) {
  385. PRINT_ERROR("TimerTest: Wacky itimer value succeeded.\n");
  386. Failures += 1;
  387. }
  388. Value.it_value.tv_sec = 2;
  389. Value.it_value.tv_usec = 500000;
  390. Value.it_interval.tv_usec = 1000001;
  391. if ((setitimer(ITIMER_REAL, &Value, NULL) != -1) || (errno != EINVAL)) {
  392. PRINT_ERROR("TimerTest: Wacky itimer period succeeded.\n");
  393. Failures += 1;
  394. }
  395. //
  396. // Getting the timers before setting them should return zero.
  397. //
  398. for (Type = 0; Type < 3; Type += 1) {
  399. if (getitimer(TestITimerTypes[Type], &Value) != 0) {
  400. PRINT_ERROR("TimerTest: getitimer failed.\n");
  401. Failures += 1;
  402. }
  403. if ((Value.it_value.tv_sec | Value.it_value.tv_usec) != 0) {
  404. PRINT_ERROR("TimerTest: getitimer had a value!\n");
  405. Failures += 1;
  406. }
  407. }
  408. //
  409. // Create timers with a period.
  410. //
  411. for (Type = 0; Type < 3; Type += 1) {
  412. Value.it_value.tv_sec = 2;
  413. Value.it_value.tv_usec = 500000;
  414. Value.it_interval.tv_sec = 1;
  415. Value.it_interval.tv_usec = 250000;
  416. //
  417. // Get aligned to a one second boundary.
  418. //
  419. if (clock_gettime(CLOCK_REALTIME, &Time) != 0) {
  420. PRINT_ERROR("TimerTest: clock_gettime(CLOCK_REALTIME) failed.\n");
  421. Failures += 1;
  422. }
  423. do {
  424. clock_gettime(CLOCK_REALTIME, &EndTime);
  425. } while (Time.tv_sec == EndTime.tv_sec);
  426. //
  427. // Set the timer.
  428. //
  429. if (setitimer(TestITimerTypes[Type], &Value, NULL) != 0) {
  430. PRINT_ERROR("TimerTest: setitimer failed.\n");
  431. Failures += 1;
  432. }
  433. if (getitimer(TestITimerTypes[Type], &Value) != 0) {
  434. PRINT_ERROR("TimerTest: getitimer failed.\n");
  435. Failures += 1;
  436. }
  437. if ((Value.it_value.tv_sec != 2) ||
  438. (Value.it_value.tv_usec >= 500000) ||
  439. (Value.it_interval.tv_sec != 1) ||
  440. (abs(Value.it_interval.tv_usec - 250000) > 1000)) {
  441. PRINT_ERROR("TimerTest: getitimer value was off: "
  442. "%lld.%d %lld.%d.\n",
  443. (LONGLONG)Value.it_value.tv_sec,
  444. Value.it_value.tv_usec,
  445. (LONGLONG)Value.it_interval.tv_sec,
  446. Value.it_interval.tv_usec);
  447. Failures += 1;
  448. }
  449. //
  450. // 2.5 + (4 * 1.25) = 7.5. So wait 8 seconds. Sleep for the first 3,
  451. // which should not affect the real timer but should delay the virtual
  452. // ones.
  453. //
  454. sleep(3);
  455. clock_gettime(CLOCK_REALTIME, &Time);
  456. if (TestITimerTypes[Type] == ITIMER_REAL) {
  457. if (Time.tv_sec != EndTime.tv_sec + 2) {
  458. PRINT_ERROR("TimerTest: RealTime itimer did not interrupt "
  459. "sleep.\n");
  460. Failures += 1;
  461. }
  462. } else {
  463. if (Time.tv_sec != EndTime.tv_sec + 3) {
  464. PRINT_ERROR("TimerTest: Virtual itimer interrupted sleep.\n");
  465. Failures += 1;
  466. }
  467. }
  468. //
  469. // Busy spin for the remaining 5 or 5.5 seconds.
  470. //
  471. EndTime.tv_sec += 8;
  472. do {
  473. clock_gettime(CLOCK_REALTIME, &Time);
  474. } while (Time.tv_sec < EndTime.tv_sec);
  475. //
  476. // Now stop the timer and see how many signals came in.
  477. //
  478. memset(&Value, 0, sizeof(Value));
  479. if (setitimer(TestITimerTypes[Type], &Value, NULL) != 0) {
  480. PRINT_ERROR("TimerTest: setitimer failed.\n");
  481. Failures += 1;
  482. }
  483. Signal = TestITimerTypeSignals[Type];
  484. Actual = TestTimerSignals[Signal];
  485. TestTimerSignals[Signal] = 0;
  486. if (TestITimerTypes[Type] == ITIMER_REAL) {
  487. Expected = 5;
  488. Tolerance = 0;
  489. } else if (TestITimerTypes[Type] == ITIMER_PROF) {
  490. Expected = 3;
  491. Tolerance = 1;
  492. } else {
  493. Expected = 3;
  494. Tolerance = 2;
  495. }
  496. if (!((Actual >= Expected - Tolerance) &&
  497. (Actual <= Expected + Tolerance))) {
  498. PRINT_ERROR("TimerTest: Expected %d interrupts for timer type "
  499. "%d (tolerance %d), got %d.\n",
  500. Expected,
  501. TestITimerTypes[Type],
  502. Tolerance,
  503. Actual);
  504. Failures += 1;
  505. }
  506. }
  507. //
  508. // Ensure that there are no extra signals.
  509. //
  510. for (Signal = 0; Signal < NSIG; Signal += 1) {
  511. if (TestTimerSignals[Signal] != 0) {
  512. PRINT_ERROR("TimerTest: %d extra %d signals.\n",
  513. TestTimerSignals[Signal],
  514. Signal);
  515. Failures += 1;
  516. }
  517. }
  518. sigaction(SIGALRM, &OldAlarm, NULL);
  519. sigaction(SIGVTALRM, &OldVirtualAlarm, NULL);
  520. sigaction(SIGPROF, &OldProfile, NULL);
  521. return Failures;
  522. }
  523. ULONG
  524. RunThreadTimerTest (
  525. VOID
  526. )
  527. /*++
  528. Routine Description:
  529. This routine tests user mode timers using SIGEV_THREAD_ID .
  530. Arguments:
  531. None.
  532. Return Value:
  533. Returns the number of failures in the test.
  534. --*/
  535. {
  536. struct sigaction Action;
  537. pthread_barrier_t Barrier;
  538. ULONGLONG CurrentTime;
  539. ULONGLONG EndTime;
  540. struct sigevent Event;
  541. ULONG Failures;
  542. ULONGLONG Frequency;
  543. ULONG Index;
  544. ULONGLONG LastUpdate;
  545. int MaxCount;
  546. ULONG MaxTimer;
  547. int MinCount;
  548. ULONG MinTimer;
  549. struct sigaction OriginalAction;
  550. struct itimerspec Rate;
  551. int Result;
  552. BOOL Stop;
  553. pthread_t Thread;
  554. Failures = 0;
  555. Stop = TRUE;
  556. //
  557. // Set up the signal handler.
  558. //
  559. Action.sa_sigaction = TimerThreadTestAlarmSignalHandler;
  560. sigemptyset(&(Action.sa_mask));
  561. Action.sa_flags = SA_SIGINFO;
  562. Result = sigaction(SIGALRM, &Action, &OriginalAction);
  563. if (Result != 0) {
  564. PRINT_ERROR("ThreadTimerTest: sigaction failed: %s\n", strerror(errno));
  565. return 1;
  566. }
  567. //
  568. // Use a barrier to make the signal threads wait to exit.
  569. //
  570. pthread_barrier_init(&Barrier, NULL, TEST_THREAD_TIMER_COUNT + 1);
  571. //
  572. // Initialize the portions of the signal event common to each timer.
  573. //
  574. memset(&Event, 0, sizeof(struct sigevent));
  575. Event.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
  576. Event.sigev_signo = SIGALRM;
  577. //
  578. // Create a bunch of timers and a thread to receive the signal for each.
  579. //
  580. for (Index = 0; Index < TEST_THREAD_TIMER_COUNT; Index += 1) {
  581. TestThreads[Index] = -1;
  582. TestThreadTimers[Index] = -1;
  583. Result = pthread_create(&Thread,
  584. NULL,
  585. TimerThreadTestStartRoutine,
  586. &Barrier);
  587. if (Result != 0) {
  588. PRINT_ERROR("ThreadTimerTest: pthread_create failed: %s.\n",
  589. strerror(errno));
  590. return Failures;
  591. }
  592. Event.sigev_value.sival_int = Index;
  593. Event.sigev_notify_thread_id = pthread_gettid_np(Thread);
  594. TestThreads[Index] = Thread;
  595. Result = timer_create(CLOCK_REALTIME,
  596. &Event,
  597. &(TestThreadTimers[Index]));
  598. if (Result != 0) {
  599. PRINT_ERROR("ThreadTimerTest: Failed to create timer: %s.\n",
  600. strerror(errno));
  601. Failures += 1;
  602. }
  603. }
  604. //
  605. // Arm the timers.
  606. //
  607. Rate.it_value.tv_sec = TEST_TIMER_PERIOD_SECONDS;
  608. Rate.it_value.tv_nsec = TEST_TIMER_PERIOD_NANOSECONDS;
  609. Rate.it_interval.tv_sec = TEST_TIMER_PERIOD_SECONDS;
  610. Rate.it_interval.tv_nsec = TEST_TIMER_PERIOD_NANOSECONDS;
  611. for (Index = 0; Index < TEST_THREAD_TIMER_COUNT; Index += 1) {
  612. Result = timer_settime(TestThreadTimers[Index], 0, &Rate, NULL);
  613. if (Result != 0) {
  614. PRINT_ERROR("ThreadTimerTest: Failed to create timer: %s.\n",
  615. strerror(errno));
  616. Failures += 1;
  617. }
  618. }
  619. //
  620. // Compute the timeout time.
  621. //
  622. Frequency = OsGetTimeCounterFrequency();
  623. EndTime = OsGetRecentTimeCounter() + (TEST_TIMER_TIMEOUT * Frequency);
  624. LastUpdate = OsGetRecentTimeCounter() / Frequency;
  625. while (OsGetRecentTimeCounter() < EndTime) {
  626. Stop = TRUE;
  627. MinTimer = -1;
  628. MinCount = MAX_LONG;
  629. MaxTimer = -1;
  630. MaxCount = 0;
  631. for (Index = 0; Index < TEST_THREAD_TIMER_COUNT; Index += 1) {
  632. if (TestThreadTimerCount[Index] < TEST_THREAD_TIMER_GOAL) {
  633. Stop = FALSE;
  634. }
  635. if ((MinTimer == -1) || (TestThreadTimerCount[Index] < MinCount)) {
  636. MinTimer = Index;
  637. MinCount = TestThreadTimerCount[Index];
  638. }
  639. if ((MaxTimer == -1) || (TestThreadTimerCount[Index] > MaxCount)) {
  640. MaxTimer = Index;
  641. MaxCount = TestThreadTimerCount[Index];
  642. }
  643. }
  644. if (Stop != FALSE) {
  645. DEBUG_PRINT("All timer threads reached threshold.\n");
  646. break;
  647. }
  648. CurrentTime = OsGetRecentTimeCounter() / Frequency;
  649. if (CurrentTime - LastUpdate >= TEST_TIMER_UPDATE_INTERVAL) {
  650. DEBUG_PRINT("%I64d: Min count %d, timer %d. "
  651. "Max count %d, timer %d.\n",
  652. CurrentTime,
  653. MinCount,
  654. MinTimer,
  655. MaxCount,
  656. MaxTimer);
  657. fflush(NULL);
  658. LastUpdate = CurrentTime;
  659. }
  660. }
  661. if (Stop == FALSE) {
  662. PRINT_ERROR("ThreadTimerTest: Some timers did not count!\n");
  663. }
  664. //
  665. // Delete all the timers so they stop firing.
  666. //
  667. for (Index = 0; Index < TEST_THREAD_TIMER_COUNT; Index += 1) {
  668. Result = timer_delete(TestThreadTimers[Index]);
  669. if (Result != 0) {
  670. PRINT_ERROR("ThreadTimerTest: Failed to delete timer: %s.\n",
  671. strerror(errno));
  672. Failures += 1;
  673. }
  674. }
  675. //
  676. // With the timers destroyed, the threads are free to exit. Wait on the
  677. // barrier to make sure all threads get released. Then wait for each
  678. // thread's exit status.
  679. //
  680. pthread_barrier_wait(&Barrier);
  681. pthread_barrier_destroy(&Barrier);
  682. for (Index = 0; Index < TEST_THREAD_TIMER_COUNT; Index += 1) {
  683. Result = pthread_join(TestThreads[Index], NULL);
  684. if (Result != 0) {
  685. PRINT_ERROR("ThreadTimerTest: Failed to join thread: %s.\n",
  686. strerror(errno));
  687. Failures += 1;
  688. }
  689. }
  690. //
  691. // Restore the signal handler.
  692. //
  693. Result = sigaction(SIGALRM, &OriginalAction, NULL);
  694. if (Result != 0) {
  695. PRINT_ERROR("ThreadTimerTest: Failed to restore SIGALRM: %s.\n",
  696. strerror(errno));
  697. Failures += 1;
  698. }
  699. return Failures;
  700. }
  701. VOID
  702. ITimerTestSignalHandler (
  703. INT SignalNumber
  704. )
  705. /*++
  706. Routine Description:
  707. This routine implements the signal handler for the interval timer test.
  708. Arguments:
  709. SignalNumber - Supplies the incoming signal, always SIGALRM in this case.
  710. Return Value:
  711. None.
  712. --*/
  713. {
  714. TestTimerSignals[SignalNumber] += 1;
  715. return;
  716. }
  717. VOID
  718. TimerTestAlarmSignalHandler (
  719. INT SignalNumber,
  720. siginfo_t *Information,
  721. void *SomethingElse
  722. )
  723. /*++
  724. Routine Description:
  725. This routine implements the alarm signal handler.
  726. Arguments:
  727. SignalNumber - Supplies the incoming signal, always SIGALRM in this case.
  728. Information - Supplies a pointer to the signal information structure.
  729. SomethingElse - Supplies an unused context pointer.
  730. Return Value:
  731. None.
  732. --*/
  733. {
  734. ULONG TimerIndex;
  735. assert(SignalNumber == SIGALRM);
  736. for (TimerIndex = 0; TimerIndex < TEST_TIMER_COUNT; TimerIndex += 1) {
  737. if (TestTimers[TimerIndex] == Information->si_value.sival_int) {
  738. TestTimerCount[TimerIndex] += 1;
  739. break;
  740. }
  741. }
  742. assert(TimerIndex != TEST_TIMER_COUNT);
  743. return;
  744. }
  745. void *
  746. TimerThreadTestStartRoutine (
  747. void *Parameter
  748. )
  749. /*++
  750. Routine Description:
  751. This routine implements the start routine for a timer thread test.
  752. Arguments:
  753. Parameter - Supplies a pointer to a POSIX thread barrier to wait on.
  754. Return Value:
  755. Returns NULL.
  756. --*/
  757. {
  758. pthread_barrier_t *Barrier;
  759. //
  760. // Wait on the barrier.
  761. //
  762. Barrier = (pthread_barrier_t *)Parameter;
  763. pthread_barrier_wait(Barrier);
  764. return NULL;
  765. }
  766. VOID
  767. TimerThreadTestAlarmSignalHandler (
  768. INT SignalNumber,
  769. siginfo_t *Information,
  770. void *SomethingElse
  771. )
  772. /*++
  773. Routine Description:
  774. This routine implements the alarm signal handler for the timer thread test.
  775. Arguments:
  776. SignalNumber - Supplies the incoming signal, always SIGALRM in this case.
  777. Information - Supplies a pointer to the signal information structure.
  778. SomethingElse - Supplies an unused context pointer.
  779. Return Value:
  780. None.
  781. --*/
  782. {
  783. assert(SignalNumber == SIGALRM);
  784. TestThreadTimerCount[Information->si_value.sival_int] += 1;
  785. return;
  786. }