lat_sig.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * lat_sig.c - signal handler test
  3. *
  4. * XXX - this benchmark requires the POSIX sigaction interface. The reason
  5. * for that is that the signal handler stays installed with that interface.
  6. * The more portable signal() interface may or may not stay installed and
  7. * reinstalling it each time is expensive.
  8. *
  9. * XXX - should really do a two process version.
  10. *
  11. * Copyright (c) 1994 Larry McVoy. Distributed under the FSF GPL with
  12. * additional restriction that results may published only if
  13. * (1) the benchmark is unmodified, and
  14. * (2) the version in the sccsid below is included in the report.
  15. */
  16. char *id = "$Id$\n";
  17. #include <math.h>
  18. #include "bench.h"
  19. #include "confidence.h"
  20. int caught, to_catch, n, pos;
  21. double *times;
  22. double adj;
  23. double adj_mean, adj_var;
  24. void handler() { }
  25. #define ITER_UNITS 50
  26. void prot() {
  27. if (++caught == to_catch) {
  28. double u;
  29. double mean;
  30. double var;
  31. u = stop(0,0);
  32. u /= (double) to_catch;
  33. times[pos++] = u;
  34. mean = calc_mean(times, pos);
  35. fprintf(stderr, "mean=%.4f adj_mean=%.4f\n", mean, adj_mean);
  36. var = calc_variance(mean, times, pos);
  37. fprintf(stderr, "var=%.4f adj_var=%.4f\n", var, adj_var);
  38. mean -= adj_mean;
  39. var += adj_var;
  40. fprintf(stderr, "Protection fault: "
  41. "[mean=%.4lf +/-%.4lf] microseconds\n",
  42. mean, ci_width(sqrt(var), pos));
  43. exit(0);
  44. }
  45. if (caught == ITER_UNITS) {
  46. double u;
  47. double mean;
  48. double var;
  49. u = stop(0,0);
  50. u /= (double) ITER_UNITS;
  51. times[pos++] = u;
  52. caught = 0;
  53. to_catch -= ITER_UNITS;
  54. start(0);
  55. }
  56. }
  57. double
  58. overhead(double *mean, double *var)
  59. {
  60. int me = getpid();
  61. double o;
  62. /*
  63. * OS cost of sending a signal without actually sending one
  64. */
  65. BENCH(kill(me, 0), 0);
  66. o = usecs_spent();
  67. o /= get_n();
  68. if (mean)
  69. *mean = getmeantime();
  70. if (var)
  71. *var = getvariancetime();
  72. return (o);
  73. }
  74. double
  75. overhead_mean(void)
  76. {
  77. }
  78. void
  79. install(void)
  80. {
  81. struct sigaction sa, old;
  82. sa.sa_handler = handler;
  83. sigemptyset(&sa.sa_mask);
  84. sa.sa_flags = 0;
  85. sigaction(SIGUSR1, &sa, &old);
  86. }
  87. void
  88. do_install(void)
  89. {
  90. double u, mean, var;
  91. /*
  92. * Installation cost
  93. */
  94. BENCH(install(), 0);
  95. u = usecs_spent();
  96. u /= get_n();
  97. mean = getmeantime();
  98. var = getvariancetime();
  99. fprintf(stderr, "Signal handler installation: median=%.3f "
  100. "[mean=%.4lf +/-%.4lf] microseconds\n",
  101. u, mean, ci_width(sqrt(var), TRIES));
  102. }
  103. void
  104. do_catch(int report)
  105. {
  106. int me = getpid();
  107. struct sigaction sa, old;
  108. double u, mean, var;
  109. double sig_mean, sig_var;
  110. /*
  111. * Cost of catching the signal less the cost of sending it
  112. */
  113. sa.sa_handler = handler;
  114. sigemptyset(&sa.sa_mask);
  115. sa.sa_flags = 0;
  116. sigaction(SIGUSR1, &sa, &old);
  117. BENCH(kill(me, SIGUSR1), 0);
  118. u = usecs_spent();
  119. mean = getmeantime();
  120. var = getvariancetime();
  121. u /= get_n();
  122. u -= overhead(&sig_mean, &sig_var);
  123. adj = u;
  124. n = SHORT/u;
  125. to_catch = n;
  126. mean -= sig_mean;
  127. var += sig_var;
  128. adj_mean = mean;
  129. adj_var = var;
  130. if (report) {
  131. fprintf(stderr,
  132. "Signal handler overhead: median=%.3f "
  133. "[mean=%.4lf +/-%.4lf] microseconds\n",
  134. u, mean, ci_width(sqrt(var), TRIES));
  135. }
  136. }
  137. void
  138. do_prot(int ac, char **av)
  139. {
  140. int fd;
  141. struct sigaction sa;
  142. char *where;
  143. if (ac != 3) {
  144. fprintf(stderr, "usage: %s prot file\n", av[0]);
  145. exit(1);
  146. }
  147. fd = open(av[2], 0);
  148. where = mmap(0, 4096, PROT_READ, MAP_SHARED, fd, 0);
  149. if ((int)where == -1) {
  150. perror("mmap");
  151. exit(1);
  152. }
  153. /*
  154. * Catch protection faults.
  155. * Assume that they will cost the same as a normal catch.
  156. */
  157. do_catch(0);
  158. sa.sa_handler = prot;
  159. sigemptyset(&sa.sa_mask);
  160. sa.sa_flags = 0;
  161. sigaction(SIGSEGV, &sa, 0);
  162. sigaction(SIGBUS, &sa, 0);
  163. times = malloc(sizeof(double) * ceil(n / ITER_UNITS));
  164. start(0);
  165. *where = 1;
  166. }
  167. int
  168. main(int ac, char **av)
  169. {
  170. if (ac < 2) goto usage;
  171. if (!strcmp("install", av[1])) {
  172. do_install();
  173. } else if (!strcmp("catch", av[1])) {
  174. do_catch(1);
  175. } else if (!strcmp("prot", av[1])) {
  176. do_prot(ac, av);
  177. } else {
  178. usage: printf("Usage: %s install|catch|prot file\n", av[0]);
  179. }
  180. return(0);
  181. }