lat_sig.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. char *buffer;
  32. double ci;
  33. int n;
  34. double level;
  35. u = stop(0,0);
  36. u /= (double) to_catch;
  37. times[pos++] = u;
  38. mean = calc_mean(times, pos);
  39. var = calc_variance(mean, times, pos);
  40. mean -= adj_mean;
  41. var += adj_var;
  42. ci = ci_width(sqrt(var), pos);
  43. buffer = malloc(80);
  44. n = 0;
  45. strcpy(buffer + n, "mean=");
  46. n += 5;
  47. for (level = 1; level < mean; level *= 10);
  48. while (level > 0.0001) {
  49. if (level == 1) buffer[n++] = '.';
  50. level /= 10;
  51. buffer[n++] = '0' + (int) (mean / level);
  52. mean -= ((int) (mean / level)) * level;
  53. }
  54. strcpy(buffer + n, " +/-");
  55. n += 4;
  56. for (level = 1; level < ci; level *= 10);
  57. while (level > 0.0001) {
  58. if (level == 1) buffer[n++] = '.';
  59. level /= 10;
  60. buffer[n++] = '0' + (int) (ci / level);
  61. mean -= ((int) (ci / level)) * level;
  62. }
  63. n += 4;
  64. buffer[n++] = '\n';
  65. write(2, buffer, n);
  66. exit(0);
  67. }
  68. if (caught == ITER_UNITS) {
  69. double u;
  70. double mean;
  71. double var;
  72. u = stop(0,0);
  73. u /= (double) ITER_UNITS;
  74. times[pos++] = u;
  75. caught = 0;
  76. to_catch -= ITER_UNITS;
  77. start(0);
  78. }
  79. }
  80. double
  81. overhead(double *mean, double *var)
  82. {
  83. int me = getpid();
  84. double o;
  85. /*
  86. * OS cost of sending a signal without actually sending one
  87. */
  88. BENCH(kill(me, 0), 0);
  89. o = usecs_spent();
  90. o /= get_n();
  91. if (mean)
  92. *mean = getmeantime();
  93. if (var)
  94. *var = getvariancetime();
  95. return (o);
  96. }
  97. double
  98. overhead_mean(void)
  99. {
  100. }
  101. void
  102. install(void)
  103. {
  104. struct sigaction sa, old;
  105. sa.sa_handler = handler;
  106. sigemptyset(&sa.sa_mask);
  107. sa.sa_flags = 0;
  108. sigaction(SIGUSR1, &sa, &old);
  109. }
  110. void
  111. do_install(void)
  112. {
  113. double u, mean, var;
  114. /*
  115. * Installation cost
  116. */
  117. BENCH(install(), 0);
  118. u = usecs_spent();
  119. u /= get_n();
  120. mean = getmeantime();
  121. var = getvariancetime();
  122. fprintf(stderr, "Signal handler installation: median=%.3f "
  123. "[mean=%.4lf +/-%.4lf] microseconds\n",
  124. u, mean, ci_width(sqrt(var), TRIES));
  125. }
  126. void
  127. do_catch(int report)
  128. {
  129. int me = getpid();
  130. struct sigaction sa, old;
  131. double u, mean, var;
  132. double sig_mean, sig_var;
  133. /*
  134. * Cost of catching the signal less the cost of sending it
  135. */
  136. sa.sa_handler = handler;
  137. sigemptyset(&sa.sa_mask);
  138. sa.sa_flags = 0;
  139. sigaction(SIGUSR1, &sa, &old);
  140. BENCH(kill(me, SIGUSR1), 0);
  141. u = usecs_spent();
  142. mean = getmeantime();
  143. var = getvariancetime();
  144. u /= get_n();
  145. u -= overhead(&sig_mean, &sig_var);
  146. adj = u;
  147. n = SHORT/u;
  148. to_catch = n;
  149. mean -= sig_mean;
  150. var += sig_var;
  151. adj_mean = mean;
  152. adj_var = var;
  153. if (report) {
  154. fprintf(stderr,
  155. "Signal handler overhead: median=%.3f "
  156. "[mean=%.4lf +/-%.4lf] microseconds\n",
  157. u, mean, ci_width(sqrt(var), TRIES));
  158. }
  159. }
  160. void
  161. do_prot(int ac, char **av)
  162. {
  163. int fd;
  164. struct sigaction sa;
  165. char *where;
  166. if (ac != 3) {
  167. fprintf(stderr, "usage: %s prot file\n", av[0]);
  168. exit(1);
  169. }
  170. fd = open(av[2], 0);
  171. where = mmap(0, 4096, PROT_READ, MAP_SHARED, fd, 0);
  172. if ((int)where == -1) {
  173. perror("mmap");
  174. exit(1);
  175. }
  176. /*
  177. * Catch protection faults.
  178. * Assume that they will cost the same as a normal catch.
  179. */
  180. do_catch(0);
  181. sa.sa_handler = prot;
  182. sigemptyset(&sa.sa_mask);
  183. sa.sa_flags = 0;
  184. sigaction(SIGSEGV, &sa, 0);
  185. sigaction(SIGBUS, &sa, 0);
  186. times = malloc(sizeof(double) * ceil(n / ITER_UNITS));
  187. start(0);
  188. *where = 1;
  189. }
  190. int
  191. main(int ac, char **av)
  192. {
  193. if (ac < 2) goto usage;
  194. if (!strcmp("install", av[1])) {
  195. do_install();
  196. } else if (!strcmp("catch", av[1])) {
  197. do_catch(1);
  198. } else if (!strcmp("prot", av[1])) {
  199. do_prot(ac, av);
  200. } else {
  201. usage: printf("Usage: %s install|catch|prot file\n", av[0]);
  202. }
  203. return(0);
  204. }