timerTest.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #include <unistd.h>
  2. #include <time.h>
  3. #include <signal.h>
  4. #include <stdio.h>
  5. #include <sys/queue.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <err.h>
  9. #include <sys/file.h>
  10. /*
  11. * signal and timer example
  12. *
  13. * timerTest.c
  14. */
  15. /*
  16. * map timer code to a string
  17. *
  18. */
  19. #define MAX_LEN_NAME 128
  20. SLIST_HEAD(slisthead, entry) head = SLIST_HEAD_INITIALIZER(head);
  21. struct slisthead *headp; /* Singly-linked List head. */
  22. struct entry {
  23. char *name;
  24. int code;
  25. SLIST_ENTRY(entry) entries; /* Singly-linked List. */
  26. } *np;
  27. /*
  28. * signal handler
  29. *
  30. */
  31. static int spankme;
  32. void
  33. sigHandler(int signo, siginfo_t * si, void * /* ucontext_t */ uap)
  34. {
  35. switch (signo) {
  36. case SIGALRM:
  37. /* timer timeout */
  38. SLIST_FOREACH(np, &head, entries) {
  39. if (np && np->code == si->si_value.sival_int) {
  40. flockfile(stdout);
  41. printf("%s", np->name);
  42. fflush(stdout);
  43. funlockfile(stdout);
  44. break;
  45. }
  46. }
  47. if (np == NULL)
  48. printf("Timeout #%d, unknown.\n", si->si_value.sival_int);
  49. break;
  50. case SIGINFO:
  51. printf("no need to panic.\n");
  52. break;
  53. case SIGINT:
  54. /* exit flag */
  55. ++spankme;
  56. break;
  57. default:
  58. printf("sig:%d received.", signo);
  59. break;
  60. }
  61. }
  62. int
  63. main(int argc, char *argv[])
  64. {
  65. SLIST_INIT(&head);
  66. /* timer pointers */
  67. size_t nb_timers = 5;
  68. if (argc > 1) {
  69. nb_timers = atoi(argv[1]);
  70. }
  71. if (nb_timers < 1) {
  72. fprintf(stderr, "Invalid timer number.\n");
  73. abort();
  74. }
  75. timer_t timerid[nb_timers];
  76. char *names[nb_timers];
  77. /* build text to display for each */
  78. for (size_t i = 0; i < nb_timers; ++i) {
  79. names[i] = malloc(MAX_LEN_NAME);
  80. if (i == 0) {
  81. strncpy(names[i], ".", MAX_LEN_NAME);
  82. continue;
  83. }
  84. if (MAX_LEN_NAME <= snprintf(names[i], MAX_LEN_NAME, "+%zu+", i * 2 + 1)) {
  85. warnx("string %zu shorten", i);
  86. }
  87. }
  88. /* signal */
  89. struct sigaction sa;
  90. sa.sa_handler = NULL;
  91. sa.sa_sigaction = &sigHandler;
  92. sa.sa_flags = SA_SIGINFO;
  93. sigemptyset(&sa.sa_mask);
  94. if (sigaction(SIGINFO, &sa, NULL)) {
  95. warn("SIGNFO not caught.");
  96. }
  97. if (sigaction(SIGALRM, &sa, NULL)) {
  98. err(2, "sigaction:ALARM");
  99. }
  100. if (sigaction(SIGINT, &sa, NULL)) {
  101. err(2, "sigaction:INTERRUPT");
  102. }
  103. /* timer */
  104. for (size_t i = 0; i < nb_timers; ++i) {
  105. if (timer_create(CLOCK_REALTIME, NULL, &timerid[i])) {
  106. warn("timer_create failed for %zu", i);
  107. continue;
  108. }
  109. /* 3 -> TIMER_MAX stored into timerid->oshandle */
  110. np = malloc(sizeof(struct entry)); /* Insert at the head. */
  111. np->code = timer_oshandle_np(timerid[i]);
  112. np->name = names[i];
  113. SLIST_INSERT_HEAD(&head, np, entries);
  114. /* Set values and start timer */
  115. struct itimerspec its;
  116. its.it_interval.tv_sec = 1 + i * 2;
  117. its.it_interval.tv_nsec = 0;
  118. its.it_value.tv_sec = its.it_interval.tv_sec;
  119. its.it_value.tv_nsec = 0;
  120. if (timer_settime(timerid[i], 0, &its, NULL)) {
  121. warn("timer_settime failed for %zu", i);
  122. }
  123. printf("Timer %s now created at interval %ld.\n", np->name, its.it_interval.tv_sec);
  124. }
  125. printf("waiting...\n");
  126. for (; !spankme;) {
  127. pause();
  128. }
  129. printf("\nbye.\n");
  130. for (size_t i = 0; i < nb_timers; ++i) {
  131. timer_delete(timerid[i]);
  132. }
  133. while (!SLIST_EMPTY(&head)) {
  134. np = SLIST_FIRST(&head);
  135. SLIST_REMOVE_HEAD(&head, entries);
  136. free(np->name);
  137. free(np);
  138. }
  139. }