threadtest.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /* threadtest.c
  2. * by: john stultz ([email protected])
  3. * (C) Copyright IBM 2004, 2005, 2006, 2012
  4. * Licensed under the GPLv2
  5. *
  6. * To build:
  7. * $ gcc threadtest.c -o threadtest -lrt
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. */
  19. #include <stdio.h>
  20. #include <unistd.h>
  21. #include <stdlib.h>
  22. #include <sys/time.h>
  23. #include <pthread.h>
  24. #include "../kselftest.h"
  25. /* serializes shared list access */
  26. pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
  27. /* serializes console output */
  28. pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
  29. #define MAX_THREADS 128
  30. #define LISTSIZE 128
  31. int done = 0;
  32. struct timespec global_list[LISTSIZE];
  33. int listcount = 0;
  34. void checklist(struct timespec *list, int size)
  35. {
  36. int i, j;
  37. struct timespec *a, *b;
  38. /* scan the list */
  39. for (i = 0; i < size-1; i++) {
  40. a = &list[i];
  41. b = &list[i+1];
  42. /* look for any time inconsistencies */
  43. if ((b->tv_sec <= a->tv_sec) &&
  44. (b->tv_nsec < a->tv_nsec)) {
  45. /* flag other threads */
  46. done = 1;
  47. /*serialize printing to avoid junky output*/
  48. pthread_mutex_lock(&print_lock);
  49. /* dump the list */
  50. printf("\n");
  51. for (j = 0; j < size; j++) {
  52. if (j == i)
  53. printf("---------------\n");
  54. printf("%lu:%lu\n", list[j].tv_sec, list[j].tv_nsec);
  55. if (j == i+1)
  56. printf("---------------\n");
  57. }
  58. printf("[FAILED]\n");
  59. pthread_mutex_unlock(&print_lock);
  60. }
  61. }
  62. }
  63. /* The shared thread shares a global list
  64. * that each thread fills while holding the lock.
  65. * This stresses clock synchronization across cpus.
  66. */
  67. void *shared_thread(void *arg)
  68. {
  69. while (!done) {
  70. /* protect the list */
  71. pthread_mutex_lock(&list_lock);
  72. /* see if we're ready to check the list */
  73. if (listcount >= LISTSIZE) {
  74. checklist(global_list, LISTSIZE);
  75. listcount = 0;
  76. }
  77. clock_gettime(CLOCK_MONOTONIC, &global_list[listcount++]);
  78. pthread_mutex_unlock(&list_lock);
  79. }
  80. return NULL;
  81. }
  82. /* Each independent thread fills in its own
  83. * list. This stresses clock_gettime() lock contention.
  84. */
  85. void *independent_thread(void *arg)
  86. {
  87. struct timespec my_list[LISTSIZE];
  88. int count;
  89. while (!done) {
  90. /* fill the list */
  91. for (count = 0; count < LISTSIZE; count++)
  92. clock_gettime(CLOCK_MONOTONIC, &my_list[count]);
  93. checklist(my_list, LISTSIZE);
  94. }
  95. return NULL;
  96. }
  97. #define DEFAULT_THREAD_COUNT 8
  98. #define DEFAULT_RUNTIME 30
  99. int main(int argc, char **argv)
  100. {
  101. int thread_count, i;
  102. time_t start, now, runtime;
  103. char buf[255];
  104. pthread_t pth[MAX_THREADS];
  105. int opt;
  106. void *tret;
  107. int ret = 0;
  108. void *(*thread)(void *) = shared_thread;
  109. thread_count = DEFAULT_THREAD_COUNT;
  110. runtime = DEFAULT_RUNTIME;
  111. /* Process arguments */
  112. while ((opt = getopt(argc, argv, "t:n:i")) != -1) {
  113. switch (opt) {
  114. case 't':
  115. runtime = atoi(optarg);
  116. break;
  117. case 'n':
  118. thread_count = atoi(optarg);
  119. break;
  120. case 'i':
  121. thread = independent_thread;
  122. printf("using independent threads\n");
  123. break;
  124. default:
  125. printf("Usage: %s [-t <secs>] [-n <numthreads>] [-i]\n", argv[0]);
  126. printf(" -t: time to run\n");
  127. printf(" -n: number of threads\n");
  128. printf(" -i: use independent threads\n");
  129. return -1;
  130. }
  131. }
  132. if (thread_count > MAX_THREADS)
  133. thread_count = MAX_THREADS;
  134. setbuf(stdout, NULL);
  135. start = time(0);
  136. strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&start));
  137. printf("%s\n", buf);
  138. printf("Testing consistency with %i threads for %ld seconds: ", thread_count, runtime);
  139. fflush(stdout);
  140. /* spawn */
  141. for (i = 0; i < thread_count; i++)
  142. pthread_create(&pth[i], 0, thread, 0);
  143. while (time(&now) < start + runtime) {
  144. sleep(1);
  145. if (done) {
  146. ret = 1;
  147. strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&now));
  148. printf("%s\n", buf);
  149. goto out;
  150. }
  151. }
  152. printf("[OK]\n");
  153. done = 1;
  154. out:
  155. /* wait */
  156. for (i = 0; i < thread_count; i++)
  157. pthread_join(pth[i], &tret);
  158. /* die */
  159. if (ret)
  160. ksft_exit_fail();
  161. return ksft_exit_pass();
  162. }