devkprof.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. #include "ureg.h"
  16. #include "../port/portfns.h"
  17. #define LRES 3 /* log of PC resolution */
  18. #define SZ 4 /* sizeof of count cell; well known as 4 */
  19. struct
  20. {
  21. uintptr minpc;
  22. uintptr maxpc;
  23. int nbuf;
  24. int time;
  25. uint32_t *buf;
  26. Lock l;
  27. }kprof;
  28. enum{
  29. Kprofdirqid,
  30. Kprofdataqid,
  31. Kprofctlqid,
  32. Kprofoprofileqid,
  33. };
  34. Dirtab kproftab[]={
  35. {".", {Kprofdirqid, 0, QTDIR},0, DMDIR|0550},
  36. {"kpdata", {Kprofdataqid}, 0, 0600},
  37. {"kpctl", {Kprofctlqid}, 0, 0600},
  38. {"kpoprofile", {Kprofoprofileqid}, 0, 0600},
  39. };
  40. void oprof_alarm_handler(Ureg *u)
  41. {
  42. //int coreid = machp()->machno;
  43. if (u->ip > KTZERO)
  44. oprofile_add_backtrace(u->ip, u->bp);
  45. else
  46. oprofile_add_userpc(u->ip);
  47. }
  48. static Chan*
  49. kprofattach(char *spec)
  50. {
  51. uint32_t n;
  52. /* allocate when first used */
  53. kprof.minpc = KTZERO;
  54. kprof.maxpc = PTR2UINT(etext);
  55. kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
  56. n = kprof.nbuf*SZ;
  57. if(kprof.buf == 0) {
  58. kprof.buf = malloc(n);
  59. if(kprof.buf == 0)
  60. error(Enomem);
  61. }
  62. kproftab[1].length = n;
  63. alloc_cpu_buffers();
  64. print("Kprof attached. Buf is %p, %d bytes, minpc %p maxpc %p\n",
  65. kprof.buf, n, (void *)kprof.minpc, (void *)kprof.maxpc);
  66. return devattach('K', spec);
  67. }
  68. static void
  69. _kproftimer(uintptr_t pc)
  70. {
  71. if(kprof.time == 0)
  72. return;
  73. /*
  74. * if the pc corresponds to the idle loop, don't consider it.
  75. if(m->inidle)
  76. return;
  77. */
  78. /*
  79. * if the pc is coming out of spllo or splx,
  80. * use the pc saved when we went splhi.
  81. */
  82. if(pc>=PTR2UINT(spllo) && pc<=PTR2UINT(spldone))
  83. pc = machp()->splpc;
  84. ilock(&kprof.l);
  85. kprof.buf[0] += TK2MS(1);
  86. if(kprof.minpc<=pc && pc<kprof.maxpc){
  87. pc -= kprof.minpc;
  88. pc >>= LRES;
  89. kprof.buf[pc] += TK2MS(1);
  90. }else
  91. kprof.buf[1] += TK2MS(1);
  92. iunlock(&kprof.l);
  93. }
  94. static void
  95. kprofinit(void)
  96. {
  97. if(SZ != sizeof kprof.buf[0])
  98. panic("kprof size");
  99. kproftimer = _kproftimer;
  100. }
  101. static Walkqid*
  102. kprofwalk(Chan *c, Chan *nc, char **name, int nname)
  103. {
  104. return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen);
  105. }
  106. static int32_t
  107. kprofstat(Chan *c, uint8_t *db, int32_t n)
  108. {
  109. return devstat(c, db, n, kproftab, nelem(kproftab), devgen);
  110. }
  111. static Chan*
  112. kprofopen(Chan *c, int omode)
  113. {
  114. if(c->qid.type & QTDIR){
  115. if(omode != OREAD)
  116. error(Eperm);
  117. }
  118. c->mode = openmode(omode);
  119. c->flag |= COPEN;
  120. c->offset = 0;
  121. return c;
  122. }
  123. static void
  124. kprofclose(Chan* c)
  125. {
  126. }
  127. static int32_t
  128. kprofread(Chan *c, void *va, int32_t n, int64_t off)
  129. {
  130. uint32_t end;
  131. uint32_t w, *bp;
  132. uint8_t *a, *ea;
  133. uint32_t offset = off;
  134. switch((int)c->qid.path){
  135. case Kprofdirqid:
  136. return devdirread(c, va, n, kproftab, nelem(kproftab), devgen);
  137. case Kprofdataqid:
  138. end = kprof.nbuf*SZ;
  139. if(offset & (SZ-1))
  140. error(Ebadarg);
  141. if(offset >= end){
  142. n = 0;
  143. break;
  144. }
  145. if(offset+n > end)
  146. n = end-offset;
  147. n &= ~(SZ-1);
  148. a = va;
  149. ea = a + n;
  150. bp = kprof.buf + offset/SZ;
  151. while(a < ea){
  152. w = *bp++;
  153. *a++ = w>>24;
  154. *a++ = w>>16;
  155. *a++ = w>>8;
  156. *a++ = w>>0;
  157. }
  158. break;
  159. case Kprofoprofileqid:
  160. n = oprofread(va,n);
  161. break;
  162. default:
  163. n = 0;
  164. break;
  165. }
  166. return n;
  167. }
  168. static int32_t
  169. kprofwrite(Chan *c, void *a, int32_t n, int64_t m)
  170. {
  171. switch((int)(c->qid.path)){
  172. case Kprofctlqid:
  173. if(strncmp(a, "startclr", 8) == 0){
  174. memset((char *)kprof.buf, 0, kprof.nbuf*SZ);
  175. kprof.time = 1;
  176. }else if(strncmp(a, "start", 5) == 0)
  177. kprof.time = 1;
  178. else if(strncmp(a, "stop", 4) == 0) {
  179. print("kprof stopped. %d ms\n", kprof.buf[0]);
  180. kprof.time = 0;
  181. } else if (!strncmp(a, "opstart", 7)) {
  182. oprofile_control_trace(1);
  183. } else if (!strncmp(a, "opstop", 6)) {
  184. oprofile_control_trace(0);
  185. } else {
  186. error("startclr|start|stop|opstart|opstop");
  187. }
  188. break;
  189. default:
  190. error(Ebadusefd);
  191. }
  192. return n;
  193. }
  194. Dev kprofdevtab = {
  195. .dc = 'K',
  196. .name = "kprof",
  197. .reset = devreset,
  198. .init = kprofinit,
  199. .shutdown = devshutdown,
  200. .attach = kprofattach,
  201. .walk = kprofwalk,
  202. .stat = kprofstat,
  203. .open = kprofopen,
  204. .create = devcreate,
  205. .close = kprofclose,
  206. .read = kprofread,
  207. .bread = devbread,
  208. .write = kprofwrite,
  209. .bwrite = devbwrite,
  210. .remove = devremove,
  211. .wstat = devwstat,
  212. };