devkprof.c 3.6 KB

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