devkprof.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #define LRES 3 /* log of PC resolution */
  8. #define SZ 4 /* sizeof of count cell; well known as 4 */
  9. struct
  10. {
  11. int minpc;
  12. int maxpc;
  13. int nbuf;
  14. int time;
  15. ulong *buf;
  16. }kprof;
  17. enum{
  18. Kprofdirqid,
  19. Kprofdataqid,
  20. Kprofctlqid,
  21. };
  22. Dirtab kproftab[]={
  23. ".", {Kprofdirqid, 0, QTDIR}, 0, DMDIR|0550,
  24. "kpdata", {Kprofdataqid}, 0, 0600,
  25. "kpctl", {Kprofctlqid}, 0, 0600,
  26. };
  27. static void
  28. _kproftimer(ulong pc)
  29. {
  30. extern void spldone(void);
  31. if(kprof.time == 0)
  32. return;
  33. /*
  34. * if the pc is coming out of spllo or splx,
  35. * use the pc saved when we went splhi.
  36. */
  37. if(pc>=(ulong)spllo && pc<=(ulong)spldone)
  38. pc = m->splpc;
  39. kprof.buf[0] += TK2MS(1);
  40. if(kprof.minpc<=pc && pc<kprof.maxpc){
  41. pc -= kprof.minpc;
  42. pc >>= LRES;
  43. kprof.buf[pc] += TK2MS(1);
  44. }else
  45. kprof.buf[1] += TK2MS(1);
  46. }
  47. static void
  48. kprofinit(void)
  49. {
  50. if(SZ != sizeof kprof.buf[0])
  51. panic("kprof size");
  52. kproftimer = _kproftimer;
  53. }
  54. static Chan*
  55. kprofattach(char *spec)
  56. {
  57. ulong n;
  58. /* allocate when first used */
  59. kprof.minpc = KTZERO;
  60. kprof.maxpc = (ulong)etext;
  61. kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
  62. n = kprof.nbuf*SZ;
  63. if(kprof.buf == 0) {
  64. kprof.buf = xalloc(n);
  65. if(kprof.buf == 0)
  66. error(Enomem);
  67. }
  68. kproftab[1].length = n;
  69. return devattach('K', spec);
  70. }
  71. static Walkqid*
  72. kprofwalk(Chan *c, Chan *nc, char **name, int nname)
  73. {
  74. return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen);
  75. }
  76. static int
  77. kprofstat(Chan *c, uchar *db, int n)
  78. {
  79. return devstat(c, db, n, kproftab, nelem(kproftab), devgen);
  80. }
  81. static Chan*
  82. kprofopen(Chan *c, int omode)
  83. {
  84. if(c->qid.type == QTDIR){
  85. if(omode != OREAD)
  86. error(Eperm);
  87. }
  88. c->mode = openmode(omode);
  89. c->flag |= COPEN;
  90. c->offset = 0;
  91. return c;
  92. }
  93. static void
  94. kprofclose(Chan*)
  95. {
  96. }
  97. static long
  98. kprofread(Chan *c, void *va, long n, vlong off)
  99. {
  100. ulong end;
  101. ulong w, *bp;
  102. uchar *a, *ea;
  103. ulong offset = off;
  104. switch((int)c->qid.path){
  105. case Kprofdirqid:
  106. return devdirread(c, va, n, kproftab, nelem(kproftab), devgen);
  107. case Kprofdataqid:
  108. end = kprof.nbuf*SZ;
  109. if(offset & (SZ-1))
  110. error(Ebadarg);
  111. if(offset >= end){
  112. n = 0;
  113. break;
  114. }
  115. if(offset+n > end)
  116. n = end-offset;
  117. n &= ~(SZ-1);
  118. a = va;
  119. ea = a + n;
  120. bp = kprof.buf + offset/SZ;
  121. while(a < ea){
  122. w = *bp++;
  123. *a++ = w>>24;
  124. *a++ = w>>16;
  125. *a++ = w>>8;
  126. *a++ = w>>0;
  127. }
  128. break;
  129. default:
  130. n = 0;
  131. break;
  132. }
  133. return n;
  134. }
  135. static long
  136. kprofwrite(Chan *c, void *a, long n, vlong)
  137. {
  138. switch((int)(c->qid.path)){
  139. case Kprofctlqid:
  140. if(strncmp(a, "startclr", 8) == 0){
  141. memset((char *)kprof.buf, 0, kprof.nbuf*SZ);
  142. kprof.time = 1;
  143. }else if(strncmp(a, "start", 5) == 0)
  144. kprof.time = 1;
  145. else if(strncmp(a, "stop", 4) == 0)
  146. kprof.time = 0;
  147. break;
  148. default:
  149. error(Ebadusefd);
  150. }
  151. return n;
  152. }
  153. Dev kprofdevtab = {
  154. 'K',
  155. "kprof",
  156. devreset,
  157. kprofinit,
  158. devshutdown,
  159. kprofattach,
  160. kprofwalk,
  161. kprofstat,
  162. kprofopen,
  163. devcreate,
  164. kprofclose,
  165. kprofread,
  166. devbread,
  167. kprofwrite,
  168. devbwrite,
  169. devremove,
  170. devwstat,
  171. };