master
c 923 lines 25.8 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 timer.c
8
9 Abstract:
10
11 This file is a timer test.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <signal.h>
18 #include <time.h>
19 #include <sys/resource.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <sys/time.h>
23 #include <limits.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26
27 #define LXT_NAME "timer"
28
29 #define LXT_SHORT_TIMER 1
30 #define LXT_SHORT_TIMER_WAIT_PID 5
31 #define LXT_SHORT_TIMER_US 250000
32 #define LXT_LONG_TIMER 10
33
34 #define LXT_INVALID_TIMER_ID ((timer_t) - 1)
35
36 int AlarmSyscall(PLXT_ARGS Args);
37
38 int ITimerInvalidParam(PLXT_ARGS Args);
39
40 int ITimerPerThreadGroup(PLXT_ARGS Args);
41
42 int ITimerSignal(PLXT_ARGS Args);
43
44 int ITimerPeriodicSignal(PLXT_ARGS Args);
45
46 int NanosleepInvalidParam(PLXT_ARGS Args);
47
48 int TimerCreateSyscall(PLXT_ARGS Args);
49
50 int TimerCreateInvalidParam(PLXT_ARGS Args);
51
52 int ClockGetTimeAlignment(PLXT_ARGS Args);
53
54 //
55 // Global constants
56 //
57
58 static const LXT_VARIATION g_LxtVariations[] = {
59 {"nanosleep invalid param", NanosleepInvalidParam},
60 {"ITimerPerThreadGroup", ITimerPerThreadGroup},
61 {"ITimerSignal", ITimerSignal},
62 {"AlarmSyscall", AlarmSyscall},
63 {"ITimerPeriodicSignal", ITimerPeriodicSignal},
64 {"ITimer invalid param", ITimerInvalidParam},
65 {"timer_create", TimerCreateSyscall},
66 {"timer_create invalid param", TimerCreateInvalidParam},
67 {"clock_gettime alignment", ClockGetTimeAlignment}};
68
69 static const struct itimerval g_ZeroTimer;
70
71 //
72 // Global variables
73 //
74
75 static struct timespec g_SignalTime;
76 static int g_SignalCount;
77
78 int TimerTestEntry(int Argc, char* Argv[])
79
80 /*++
81 --*/
82
83 {
84
85 LXT_ARGS Args;
86 int Result;
87
88 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
89 LXT_SYNCHRONIZATION_POINT_INIT();
90 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
91
92 ErrorExit:
93 LXT_SYNCHRONIZATION_POINT_DESTROY();
94 LxtUninitialize();
95 return !LXT_SUCCESS(Result);
96 }
97
98 int ITimerInvalidParam(PLXT_ARGS Args)
99
100 {
101
102 struct itimerval NewTimer;
103 int Result;
104
105 memset(&NewTimer, 0, sizeof(NewTimer));
106 NewTimer.it_value.tv_sec = -1;
107 LxtCheckErrnoFailure(setitimer(ITIMER_REAL, &NewTimer, NULL), EINVAL);
108 memset(&NewTimer, 0, sizeof(NewTimer));
109 NewTimer.it_value.tv_usec = 999999 + 1;
110 LxtCheckErrnoFailure(setitimer(ITIMER_REAL, &NewTimer, NULL), EINVAL);
111 memset(&NewTimer, 0, sizeof(NewTimer));
112 NewTimer.it_interval.tv_sec = -1;
113 LxtCheckErrnoFailure(setitimer(ITIMER_REAL, &NewTimer, NULL), EINVAL);
114 memset(&NewTimer, 0, sizeof(NewTimer));
115 NewTimer.it_interval.tv_usec = 999999 + 1;
116 LxtCheckErrnoFailure(setitimer(ITIMER_REAL, &NewTimer, NULL), EINVAL);
117
118 ErrorExit:
119 return Result;
120 }
121
122 void* ITimerPerThreadGroupWorker(void* ptr)
123
124 {
125
126 struct itimerval NewTimer;
127 struct itimerval OldTimer;
128 int Result;
129
130 //
131 // Check that the timer is per threadgroup and the result is the remaining
132 // time.
133 //
134
135 memset(&NewTimer, 0, sizeof(NewTimer));
136 memset(&OldTimer, 1, sizeof(OldTimer));
137 sleep(1);
138 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, &OldTimer));
139 if (OldTimer.it_value.tv_sec >= LXT_LONG_TIMER)
140 {
141 Result = 1;
142 LxtLogError("Unexpected OldTimer %d", OldTimer.it_value.tv_sec);
143 goto ErrorExit;
144 }
145
146 ErrorExit:
147 return 0;
148 }
149
150 int ITimerPerThreadGroup(PLXT_ARGS Args)
151
152 /*++
153 --*/
154
155 {
156
157 int ChildPid;
158 int Result;
159 struct itimerval NewTimer;
160 struct itimerval OldTimer;
161 pthread_t Thread = {0};
162
163 //
164 // Check that the timer is per threadgroup and not preserved across fork.
165 //
166
167 memset(&NewTimer, 0, sizeof(NewTimer));
168 NewTimer.it_value.tv_sec = LXT_LONG_TIMER;
169 memset(&OldTimer, 1, sizeof(OldTimer));
170 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, &OldTimer));
171 LxtCheckResult(LxtCompareMemory((void*)&g_ZeroTimer, (void*)&OldTimer, sizeof(g_ZeroTimer), "Zero", "Initial"));
172 LxtCheckResult(ChildPid = fork());
173 if (ChildPid == 0)
174 {
175 memset(&OldTimer, 1, sizeof(OldTimer));
176 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, &OldTimer));
177 LxtCheckResult(LxtCompareMemory((void*)&g_ZeroTimer, (void*)&OldTimer, sizeof(g_ZeroTimer), "Zero", "Initial child"));
178 _exit(LXT_RESULT_SUCCESS);
179 }
180
181 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
182 LxtCheckErrno(pthread_create(&Thread, NULL, ITimerPerThreadGroupWorker, NULL));
183 pthread_join(Thread, NULL);
184
185 Result = LXT_RESULT_SUCCESS;
186
187 ErrorExit:
188 return Result;
189 }
190
191 void ITimerSignalHandler(int Signal)
192
193 /*++
194 --*/
195
196 {
197 if (Signal == SIGALRM)
198 {
199 LxtClockGetTime(CLOCK_REALTIME, &g_SignalTime);
200 }
201
202 return;
203 }
204
205 int ITimerSignal(PLXT_ARGS Args)
206
207 /*++
208 --*/
209
210 {
211
212 struct sigaction Action;
213 int ChildPid;
214 int ExpectedWaitStatus;
215 int Result;
216 struct timespec StartTime;
217 struct itimerval NewTimer;
218
219 //
220 // Check the different dispositions of the SIGALRM signal and cancelling the
221 // timer.
222 //
223
224 //
225 // Default disposition should terminate
226 //
227
228 LxtCheckResult(ChildPid = fork());
229 if (ChildPid == 0)
230 {
231 memset(&NewTimer, 0, sizeof(NewTimer));
232 NewTimer.it_value.tv_sec = LXT_SHORT_TIMER;
233 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, NULL));
234 sleep(LXT_SHORT_TIMER * 2);
235 _exit(LXT_RESULT_SUCCESS);
236 }
237
238 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, SIGALRM, 0, LXT_SHORT_TIMER_WAIT_PID));
239
240 //
241 // Default disposition should not terminate if canceled.
242 //
243
244 LxtCheckResult(ChildPid = fork());
245 if (ChildPid == 0)
246 {
247 memset(&NewTimer, 0, sizeof(NewTimer));
248 NewTimer.it_value.tv_sec = LXT_SHORT_TIMER;
249 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, NULL));
250 memset(&NewTimer, 0, sizeof(NewTimer));
251 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, NULL));
252 sleep(LXT_SHORT_TIMER * 2);
253 _exit(LXT_RESULT_SUCCESS);
254 }
255
256 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, LXT_SHORT_TIMER_WAIT_PID));
257
258 //
259 // Ignored should not terminate.
260 //
261
262 LxtCheckResult(ChildPid = fork());
263 if (ChildPid == 0)
264 {
265 memset(&Action, 0, sizeof(Action));
266 Action.sa_handler = SIG_IGN;
267 LxtCheckErrnoZeroSuccess(sigaction(SIGALRM, &Action, NULL));
268 memset(&NewTimer, 0, sizeof(NewTimer));
269 NewTimer.it_value.tv_sec = LXT_SHORT_TIMER;
270 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, NULL));
271 sleep(LXT_SHORT_TIMER * 2);
272 _exit(LXT_RESULT_SUCCESS);
273 }
274
275 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, LXT_SHORT_TIMER_WAIT_PID));
276
277 //
278 // Check that the signal handler is invoked within a reasonable time
279 // interval.
280 //
281
282 LxtCheckResult(ChildPid = fork());
283 if (ChildPid == 0)
284 {
285 memset(&Action, 0, sizeof(Action));
286 Action.sa_handler = ITimerSignalHandler;
287 LxtCheckErrnoZeroSuccess(sigaction(SIGALRM, &Action, NULL));
288 memset(&g_SignalTime, 0, sizeof(g_SignalTime));
289 memset(&NewTimer, 0, sizeof(NewTimer));
290 NewTimer.it_value.tv_sec = LXT_SHORT_TIMER;
291 LxtClockGetTime(CLOCK_REALTIME, &StartTime);
292 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, NULL));
293 sleep(LXT_SHORT_TIMER * 2);
294 if (g_SignalTime.tv_sec - StartTime.tv_sec != 1)
295 {
296 LxtLogError("Unexpected seconds elapsed %d", g_SignalTime.tv_sec - StartTime.tv_sec);
297
298 _exit(1);
299 }
300
301 _exit(LXT_RESULT_SUCCESS);
302 }
303
304 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, LXT_SHORT_TIMER_WAIT_PID));
305
306 Result = LXT_RESULT_SUCCESS;
307
308 ErrorExit:
309 return Result;
310 }
311
312 int AlarmSyscall(PLXT_ARGS Args)
313
314 /*++
315 --*/
316
317 {
318
319 struct sigaction Action;
320 int ChildPid;
321 int ExpectedWaitStatus;
322 int Result;
323 struct timespec StartTime;
324
325 //
326 // Check the different dispositions of the SIGALRM signal and cancelling the
327 // timer.
328 //
329
330 //
331 // Default disposition should terminate
332 //
333
334 LxtCheckResult(ChildPid = fork());
335 if (ChildPid == 0)
336 {
337 LxtCheckResult(alarm(LXT_SHORT_TIMER));
338 sleep(LXT_SHORT_TIMER * 2);
339 _exit(LXT_RESULT_SUCCESS);
340 }
341
342 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, SIGALRM, 0, LXT_SHORT_TIMER_WAIT_PID));
343
344 //
345 // Default disposition should not terminate if canceled.
346 //
347
348 LxtCheckResult(ChildPid = fork());
349 if (ChildPid == 0)
350 {
351 LxtCheckResult(alarm(LXT_SHORT_TIMER));
352 LxtCheckResult(Result = alarm(0));
353 if (Result > LXT_SHORT_TIMER)
354 {
355 LxtLogError("Unexpected value for previously armed timer %u", Result);
356 _exit(1);
357 }
358
359 sleep(LXT_SHORT_TIMER * 2);
360 _exit(LXT_RESULT_SUCCESS);
361 }
362
363 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, LXT_SHORT_TIMER_WAIT_PID));
364
365 //
366 // Ignored should not terminate.
367 //
368
369 LxtCheckResult(ChildPid = fork());
370 if (ChildPid == 0)
371 {
372 memset(&Action, 0, sizeof(Action));
373 Action.sa_handler = SIG_IGN;
374 LxtCheckErrnoZeroSuccess(sigaction(SIGALRM, &Action, NULL));
375 LxtCheckResult(alarm(LXT_SHORT_TIMER));
376 sleep(LXT_SHORT_TIMER * 2);
377 _exit(LXT_RESULT_SUCCESS);
378 }
379
380 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, LXT_SHORT_TIMER_WAIT_PID));
381
382 //
383 // Check that the signal handler is invoked within a reasonable time
384 // interval.
385 //
386
387 LxtCheckResult(ChildPid = fork());
388 if (ChildPid == 0)
389 {
390 memset(&Action, 0, sizeof(Action));
391 Action.sa_handler = ITimerSignalHandler;
392 LxtCheckErrnoZeroSuccess(sigaction(SIGALRM, &Action, NULL));
393 memset(&g_SignalTime, 0, sizeof(g_SignalTime));
394 LxtClockGetTime(CLOCK_REALTIME, &StartTime);
395 LxtCheckResult(alarm(LXT_SHORT_TIMER));
396 sleep(LXT_SHORT_TIMER * 2);
397 if (g_SignalTime.tv_sec - StartTime.tv_sec != 1)
398 {
399 LxtLogError("Unexpected seconds elapsed %d", g_SignalTime.tv_sec - StartTime.tv_sec);
400
401 _exit(1);
402 }
403
404 _exit(LXT_RESULT_SUCCESS);
405 }
406
407 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, LXT_SHORT_TIMER_WAIT_PID));
408
409 Result = LXT_RESULT_SUCCESS;
410
411 ErrorExit:
412 return Result;
413 }
414
415 void ITimerPeriodicSignalHandler(int Signal)
416
417 /*++
418 --*/
419
420 {
421 if (Signal == SIGALRM)
422 {
423 ++g_SignalCount;
424 }
425
426 return;
427 }
428
429 int ITimerPeriodicSignal(PLXT_ARGS Args)
430
431 /*++
432 --*/
433
434 {
435
436 struct sigaction Action;
437 int ChildPid;
438 int ExpectedWaitStatus;
439 int Result;
440 struct itimerval NewTimer;
441
442 //
443 // Check that the signal handler is invoked within a reasonable time
444 // interval.
445 //
446
447 LxtCheckResult(ChildPid = fork());
448 if (ChildPid == 0)
449 {
450 memset(&Action, 0, sizeof(Action));
451 Action.sa_handler = ITimerPeriodicSignalHandler;
452 LxtCheckErrnoZeroSuccess(sigaction(SIGALRM, &Action, NULL));
453 memset(&g_SignalCount, 0, sizeof(g_SignalCount));
454 memset(&NewTimer, 0, sizeof(NewTimer));
455 NewTimer.it_value.tv_sec = LXT_SHORT_TIMER;
456 NewTimer.it_interval.tv_usec = LXT_SHORT_TIMER_US;
457 LxtCheckResult(setitimer(ITIMER_REAL, &NewTimer, NULL));
458 while (sleep(LXT_SHORT_TIMER * 2) != LXT_SHORT_TIMER * 2)
459 {
460 LxtLogInfo("Periodic timer detected: %d", g_SignalCount);
461 if (g_SignalCount >= 3)
462 {
463 break;
464 }
465 }
466
467 LxtLogInfo("Periodic timer count: %d", g_SignalCount);
468 _exit(LXT_RESULT_SUCCESS);
469 }
470
471 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, LXT_SHORT_TIMER_WAIT_PID));
472
473 Result = LXT_RESULT_SUCCESS;
474
475 ErrorExit:
476 return Result;
477 }
478
479 int NanosleepInvalidParam(PLXT_ARGS Args)
480
481 {
482
483 struct timespec SleepDuration;
484 int Result;
485
486 SleepDuration.tv_sec = 0;
487 SleepDuration.tv_nsec = 999999999;
488 LxtCheckErrno(nanosleep(&SleepDuration, NULL));
489
490 //
491 // N.B. The clock_nanosleep system call returns error codes on failure
492 // instead of setting errno.
493 //
494
495 LxtCheckEqual(0, clock_nanosleep(CLOCK_MONOTONIC, 0, &SleepDuration, NULL), "%d");
496
497 SleepDuration.tv_nsec += 1;
498 LxtCheckErrnoFailure(nanosleep(&SleepDuration, NULL), EINVAL);
499
500 //
501 // N.B. The clock_nanosleep system call returns error codes on failure
502 // instead of setting errno.
503 //
504
505 LxtCheckEqual(EINVAL, clock_nanosleep(CLOCK_MONOTONIC, 0, &SleepDuration, NULL), "%d");
506
507 ErrorExit:
508 return Result;
509 }
510
511 void TimerCreateHandler(int Signal, siginfo_t* SignalInfo, void* SignalContext)
512 {
513
514 int Overrun;
515 int Result;
516 timer_t TimerId;
517
518 LxtLogInfo("Caught signal %d", Signal);
519
520 TimerId = *((timer_t*)SignalInfo->si_value.sival_ptr);
521 LxtLogInfo("SignalInfo->si_value.sival_ptr = %p", SignalInfo->si_value.sival_ptr);
522 LxtLogInfo("*SignalInfo->si_value.sival_ptr = %d", (long)TimerId);
523 LxtLogInfo("SignalInfo->si_overrun count = %d", SignalInfo->si_overrun);
524 LxtCheckResult(Overrun = LxtTimer_GetOverrun(TimerId));
525 LxtLogInfo("timer_getoverrun count = %d", Overrun);
526 LxtCheckEqual(Overrun, SignalInfo->si_overrun, "%d");
527 LxtLogInfo("SignalInfo->si_timerid = %d", SignalInfo->_sifields._timer);
528
529 ErrorExit:
530 signal(Signal, SIG_IGN);
531 return;
532 }
533
534 void* TimerCreateSyscallThread(void* Parameter)
535
536 /*++
537
538 Routine Description:
539
540 This routine is the timer create thread callback.
541
542 Arguments:
543
544 Parameter - Supplies the parameter.
545
546 Return Value:
547
548 0 on success, -1 on failure.
549
550 --*/
551
552 {
553
554 timer_t TimerId;
555 int Result;
556 struct itimerspec TimerSpec;
557
558 //
559 // Query the timer and validate that it is not set.
560 //
561
562 TimerId = (timer_t)Parameter;
563 LxtCheckResult(LxtTimer_GetTime(TimerId, &TimerSpec));
564 LxtCheckEqual(TimerSpec.it_value.tv_sec, 0, "%lx");
565 LxtCheckEqual(TimerSpec.it_value.tv_nsec, 0, "%lx");
566 LxtCheckEqual(TimerSpec.it_interval.tv_sec, 0, "%lx");
567 LxtCheckEqual(TimerSpec.it_interval.tv_nsec, 0, "%lx");
568
569 ErrorExit:
570 return (void*)(long)Result;
571 }
572
573 int TimerCreateSyscall(PLXT_ARGS Args)
574
575 {
576
577 struct itimerspec OldTimerSpec;
578 int Overrun;
579 int Result;
580 struct sigaction SigAction;
581 int Signal;
582 int SignalToTest;
583 struct sigevent SigEvent;
584 siginfo_t SignalInfo;
585 sigset_t SigMask;
586 pthread_t Thread;
587 void* ThreadReturn;
588 timer_t TimerId;
589 struct itimerspec TimerSpec;
590
591 SignalToTest = SIGRTMIN;
592 TimerId = (timer_t)-1;
593
594 //
595 // Create signal handler and temporarily block signal delivery.
596 //
597
598 SigAction.sa_flags = SA_SIGINFO;
599 SigAction.sa_sigaction = TimerCreateHandler;
600 sigemptyset(&SigAction.sa_mask);
601 LxtCheckResult(sigaction(SignalToTest, &SigAction, NULL));
602
603 sigemptyset(&SigMask);
604 sigaddset(&SigMask, SignalToTest);
605 LxtCheckResult(sigprocmask(SIG_SETMASK, &SigMask, NULL));
606
607 //
608 // Create the timer.
609 //
610
611 SigEvent.sigev_value.sival_ptr = &TimerId;
612 SigEvent.sigev_signo = SignalToTest;
613 SigEvent.sigev_notify = SIGEV_SIGNAL;
614 LxtCheckResult(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, &TimerId));
615 LxtLogInfo("create_timer TimerId = %d", TimerId);
616
617 //
618 // Set the timer - verify that the initial timer state is all zeros.
619 //
620
621 memset(&TimerSpec, 0, sizeof(TimerSpec));
622 TimerSpec.it_value.tv_sec = 1;
623 LxtCheckResult(LxtTimer_SetTime(TimerId, 0, &TimerSpec, &OldTimerSpec));
624 LxtCheckEqual(OldTimerSpec.it_value.tv_sec, 0, "%lx");
625 LxtCheckEqual(OldTimerSpec.it_value.tv_nsec, 0, "%lx");
626 LxtCheckEqual(OldTimerSpec.it_interval.tv_sec, 0, "%lx");
627 LxtCheckEqual(OldTimerSpec.it_interval.tv_nsec, 0, "%lx");
628
629 //
630 // Query the time of the timer that was just created.
631 //
632
633 LxtCheckResult(LxtTimer_GetTime(TimerId, &OldTimerSpec));
634 LxtLogInfo("OldTimerSpec.it_value.tv_sec = 0x%lx", OldTimerSpec.it_value.tv_sec);
635 LxtLogInfo("OldTimerSpec.it_value.tv_nsec = 0x%lx", OldTimerSpec.it_value.tv_nsec);
636 LxtLogInfo("OldTimerSpec.it_interval.tv_sec = 0x%lx", OldTimerSpec.it_interval.tv_sec);
637 LxtLogInfo("OldTimerSpec.it_interval.tv_nsec = 0x%lx", OldTimerSpec.it_interval.tv_nsec);
638 if ((OldTimerSpec.it_value.tv_sec > 1) || ((OldTimerSpec.it_value.tv_sec < 1) && (OldTimerSpec.it_value.tv_nsec == 0)))
639 {
640
641 Result = LXT_RESULT_FAILURE;
642 LxtLogError("timer_gettime returned tv_sec %lx tv_nsec %lx", OldTimerSpec.it_value.tv_sec, OldTimerSpec.it_value.tv_nsec);
643
644 goto ErrorExit;
645 }
646
647 LxtCheckEqual(OldTimerSpec.it_interval.tv_sec, 0, "%lx");
648 LxtCheckEqual(OldTimerSpec.it_interval.tv_nsec, 0, "%lx");
649
650 //
651 // Unblock signal delivery.
652 //
653
654 LxtCheckResult(sigprocmask(SIG_UNBLOCK, &SigMask, NULL));
655
656 //
657 // Wait for the signal to be delivered.
658 //
659
660 LxtCheckErrno(Signal = sigtimedwait(&SigMask, &SignalInfo, NULL));
661 LxtCheckEqual(Signal, SignalToTest, "%d");
662 LxtCheckEqual(SignalInfo.si_signo, SignalToTest, "%d");
663 LxtCheckEqual(SignalInfo.si_code, SI_TIMER, "%d");
664 LxtLogInfo("SignalInfo->si_value.sival_ptr = %p", SignalInfo.si_value.sival_ptr);
665 LxtLogInfo("SignalInfo->si_value.sival_int = %d", SignalInfo.si_value.sival_int);
666 LxtLogInfo("SignalInfo->si_overrun = %d", SignalInfo.si_overrun);
667 LxtCheckResult(Overrun = LxtTimer_GetOverrun(TimerId));
668 LxtLogInfo("timer_getoverrun count = %d", Overrun);
669 LxtCheckEqual(Overrun, SignalInfo.si_overrun, "%d");
670 LxtLogInfo("SignalInfo->si_timerid = %d", SignalInfo._sifields._timer);
671 LxtCheckErrnoZeroSuccess(sigpending(&SigMask));
672
673 //
674 // Create a pthread and ensure that it can see the timer.
675 //
676
677 LxtCheckResultError(pthread_create(&Thread, NULL, TimerCreateSyscallThread, (void*)TimerId));
678
679 pthread_join(Thread, &ThreadReturn);
680 LxtCheckEqual((long)ThreadReturn, 0L, "%ld");
681
682 //
683 // Delete the timer, delete twice to verify the second deletion fails.
684 //
685
686 LxtCheckResult(LxtTimer_Delete(TimerId));
687 LxtCheckErrnoFailure(LxtTimer_Delete(TimerId), EINVAL);
688 TimerId = LXT_INVALID_TIMER_ID;
689
690 Result = LXT_RESULT_SUCCESS;
691
692 ErrorExit:
693 if (TimerId != LXT_INVALID_TIMER_ID)
694 {
695 LxtTimer_Delete(TimerId);
696 }
697
698 return Result;
699 }
700
701 int TimerCreateInvalidParam(PLXT_ARGS Args)
702
703 {
704
705 pid_t ChildPid;
706 int Index;
707 struct itimerspec OldTimerSpec;
708 struct rlimit ResourceLimit = {0};
709 int Result;
710 struct sigevent SigEvent;
711 sigset_t SigMask;
712 int Status;
713 timer_t TimerId;
714 timer_t* TimerIdArray;
715 struct itimerspec TimerSpec;
716
717 ChildPid = -1;
718 TimerId = LXT_INVALID_TIMER_ID;
719 TimerIdArray = NULL;
720
721 //
722 // timer_create invalid user buffers.
723 //
724
725 SigEvent.sigev_value.sival_ptr = &TimerId;
726 SigEvent.sigev_notify = SIGEV_SIGNAL;
727 SigEvent.sigev_signo = SIGRTMIN;
728 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, -1, &TimerId), EFAULT);
729 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, NULL), EFAULT);
730 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, -1), EFAULT);
731
732 //
733 // timer_create invalid clock id's.
734 //
735
736 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_MONOTONIC_RAW, &SigEvent, &TimerId), ENOTSUP);
737 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME_COARSE, &SigEvent, &TimerId), ENOTSUP);
738 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_MONOTONIC_COARSE, &SigEvent, &TimerId), ENOTSUP);
739 LxtCheckErrnoFailure(LxtTimer_Create(-1, &SigEvent, &TimerId), EINVAL);
740
741 //
742 // timer_create invalid sigevent structures.
743 //
744
745 //
746 // Invalid notify methods.
747 //
748
749 SigEvent.sigev_notify = 5;
750 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, &TimerId), EINVAL);
751 SigEvent.sigev_notify = -1;
752 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, &TimerId), EINVAL);
753
754 //
755 // Invalid signal numbers.
756 //
757
758 SigEvent.sigev_notify = SIGEV_SIGNAL;
759 SigEvent.sigev_signo = 0;
760 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, &TimerId), EINVAL);
761 SigEvent.sigev_signo = 65;
762 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, &TimerId), EINVAL);
763 SigEvent.sigev_signo = -1;
764 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, &SigEvent, &TimerId), EINVAL);
765
766 //
767 // N.B. timer_create with a NULL SigEvent argument succeeds.
768 //
769
770 TimerId = LXT_INVALID_TIMER_ID;
771 LxtCheckResult(LxtTimer_Create(CLOCK_REALTIME, NULL, &TimerId));
772 LxtLogInfo("create_timer TimerId = %d", TimerId);
773
774 //
775 // timer_settime invalid user buffers.
776 //
777
778 LxtCheckErrnoFailure(LxtTimer_SetTime(TimerId, 0, NULL, &OldTimerSpec), EINVAL);
779 LxtCheckErrnoFailure(LxtTimer_SetTime(TimerId, 0, -1, &OldTimerSpec), EFAULT);
780
781 //
782 // N.B. timer_settime with NULL old value succeeds.
783 //
784
785 TimerSpec.it_value.tv_sec = 1;
786 TimerSpec.it_value.tv_nsec = 0;
787 TimerSpec.it_interval.tv_sec = 1;
788 TimerSpec.it_interval.tv_nsec = 1;
789 LxtCheckResult(LxtTimer_SetTime(TimerId, 0, &TimerSpec, NULL));
790
791 //
792 // N.B. Even though the timer_settime call fails with an invalid buffer for
793 // old value, the timer is still modified.
794 //
795
796 TimerSpec.it_interval.tv_sec = 4;
797 TimerSpec.it_interval.tv_nsec = 4;
798 LxtCheckErrnoFailure(LxtTimer_SetTime(TimerId, 0, &TimerSpec, -1), EFAULT);
799 OldTimerSpec = TimerSpec;
800 TimerSpec.it_interval.tv_sec = 5;
801 TimerSpec.it_interval.tv_nsec = 5;
802 LxtCheckResult(LxtTimer_SetTime(TimerId, 0, &TimerSpec, &OldTimerSpec));
803 LxtCheckEqual(OldTimerSpec.it_interval.tv_sec, 4, "%lx");
804 LxtCheckEqual(OldTimerSpec.it_interval.tv_nsec, 4, "%lx");
805
806 //
807 // Invalid timerspec values.
808 //
809
810 memset(&TimerSpec, 0, sizeof(TimerSpec));
811 TimerSpec.it_value.tv_sec = -1;
812 LxtCheckErrnoFailure(LxtTimer_SetTime(TimerId, 0, &TimerSpec, NULL), EINVAL);
813 memset(&TimerSpec, 0, sizeof(TimerSpec));
814 TimerSpec.it_value.tv_nsec = 999999999 + 1;
815 LxtCheckErrnoFailure(LxtTimer_SetTime(TimerId, 0, &TimerSpec, NULL), EINVAL);
816 memset(&TimerSpec, 0, sizeof(TimerSpec));
817 TimerSpec.it_interval.tv_sec = -1;
818 LxtCheckErrnoFailure(LxtTimer_SetTime(TimerId, 0, &TimerSpec, NULL), EINVAL);
819 memset(&TimerSpec, 0, sizeof(TimerSpec));
820 TimerSpec.it_interval.tv_nsec = 999999999 + 1;
821 LxtCheckErrnoFailure(LxtTimer_SetTime(TimerId, 0, &TimerSpec, NULL), EINVAL);
822
823 //
824 // timer_getoverrun and timer_gettime invalid param.
825 //
826
827 LxtCheckErrnoFailure(LxtTimer_GetOverrun(-1), EINVAL);
828 LxtCheckErrnoFailure(LxtTimer_GetTime(-1, &TimerSpec), EINVAL);
829 LxtCheckErrnoFailure(LxtTimer_GetTime(TimerId, NULL), EFAULT);
830 LxtCheckErrnoFailure(LxtTimer_GetTime(TimerId, -1), EFAULT);
831 LxtCheckResult(LxtTimer_Delete(TimerId));
832 TimerId = LXT_INVALID_TIMER_ID;
833
834 //
835 // Query how many timers can be created, ensure that we are able to create
836 // exactly that many timers.
837 //
838
839 LxtCheckResult(getrlimit(RLIMIT_SIGPENDING, &ResourceLimit));
840 LxtLogInfo("getrlimit(RLIMIT_SIGPENDING) Current %lu, Max %lu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
841
842 TimerIdArray = malloc(ResourceLimit.rlim_cur * sizeof(timer_t));
843 if (TimerIdArray == NULL)
844 {
845 goto ErrorExit;
846 }
847
848 memset(TimerIdArray, 0xff, (ResourceLimit.rlim_cur * sizeof(timer_t)));
849 for (Index = 0; Index < ResourceLimit.rlim_cur; Index += 1)
850 {
851 LxtCheckResult(LxtTimer_Create(CLOCK_REALTIME, NULL, &TimerIdArray[Index]));
852 }
853
854 //
855 // Create one more timer, this should fail. Delete one and create another.
856 //
857
858 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, NULL, &TimerId), EAGAIN);
859 LxtCheckResult(LxtTimer_Delete(TimerIdArray[0]));
860 TimerIdArray[0] = LXT_INVALID_TIMER_ID;
861 LxtCheckResult(LxtTimer_Create(CLOCK_REALTIME, NULL, &TimerId));
862 LxtCheckResult(LxtTimer_Delete(TimerId));
863 TimerId = LXT_INVALID_TIMER_ID;
864
865 //
866 // Set the timer limit to zero and attempt to create a new timer.
867 //
868
869 LXT_SYNCHRONIZATION_POINT_START();
870 LxtCheckErrno(ChildPid = fork());
871 if (ChildPid == 0)
872 {
873 ResourceLimit.rlim_cur = 0;
874 LxtCheckResult(setrlimit(RLIMIT_SIGPENDING, &ResourceLimit));
875 LxtCheckErrnoFailure(LxtTimer_Create(CLOCK_REALTIME, NULL, &TimerId), EAGAIN);
876 LXT_SYNCHRONIZATION_POINT();
877 goto ErrorExit;
878 }
879
880 LXT_SYNCHRONIZATION_POINT();
881 Result = LXT_RESULT_SUCCESS;
882
883 ErrorExit:
884 if (TimerId != LXT_INVALID_TIMER_ID)
885 {
886 LxtTimer_Delete(TimerId);
887 }
888
889 if (TimerIdArray != NULL)
890 {
891 for (Index = 0; Index < ResourceLimit.rlim_max; Index += 1)
892 {
893 if (TimerIdArray[Index] != LXT_INVALID_TIMER_ID)
894 {
895 LxtTimer_Delete(TimerIdArray[Index]);
896 }
897 }
898
899 free(TimerIdArray);
900 }
901
902 LXT_SYNCHRONIZATION_POINT_END();
903 return Result;
904 }
905
906 typedef struct _LXSS_BYTE_ALIGNED_TIMESPEC
907 {
908 char Padding;
909 char Buffer[10];
910 } LXSS_BYTE_ALIGNED_TIMESPEC;
911
912 int ClockGetTimeAlignment(PLXT_ARGS Args)
913
914 {
915 int Result;
916 LXSS_BYTE_ALIGNED_TIMESPEC Timespec;
917
918 LxtLogInfo("calling clock_gettime with user buffer %p", &Timespec.Buffer);
919 LxtCheckErrnoZeroSuccess(clock_gettime(CLOCK_MONOTONIC, (struct timespec*)&Timespec.Buffer));
920
921 ErrorExit:
922 return Result;
923 }