ktrace.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of version 2 of the GNU General Public License as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it would be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. *
  12. * Further, this software is distributed without any warranty that it is
  13. * free of the rightful claim of any third person regarding infringement
  14. * or the like. Any license provided herein, whether implied or
  15. * otherwise, applies only to this software file. Patent licenses, if
  16. * any, provided herein do not apply to combinations of this program with
  17. * other software, or any other product whatsoever.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write the Free Software Foundation, Inc., 59
  21. * Temple Place - Suite 330, Boston MA 02111-1307, USA.
  22. *
  23. * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
  24. * Mountain View, CA 94043, or:
  25. *
  26. * http://www.sgi.com
  27. *
  28. * For further information regarding this notice, see:
  29. *
  30. * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  31. */
  32. #include <xfs.h>
  33. static kmem_zone_t *ktrace_hdr_zone;
  34. static kmem_zone_t *ktrace_ent_zone;
  35. static int ktrace_zentries;
  36. void
  37. ktrace_init(int zentries)
  38. {
  39. ktrace_zentries = zentries;
  40. ktrace_hdr_zone = kmem_zone_init(sizeof(ktrace_t),
  41. "ktrace_hdr");
  42. ASSERT(ktrace_hdr_zone);
  43. ktrace_ent_zone = kmem_zone_init(ktrace_zentries
  44. * sizeof(ktrace_entry_t),
  45. "ktrace_ent");
  46. ASSERT(ktrace_ent_zone);
  47. }
  48. void
  49. ktrace_uninit(void)
  50. {
  51. kmem_cache_destroy(ktrace_hdr_zone);
  52. kmem_cache_destroy(ktrace_ent_zone);
  53. }
  54. /*
  55. * ktrace_alloc()
  56. *
  57. * Allocate a ktrace header and enough buffering for the given
  58. * number of entries.
  59. */
  60. ktrace_t *
  61. ktrace_alloc(int nentries, int sleep)
  62. {
  63. ktrace_t *ktp;
  64. ktrace_entry_t *ktep;
  65. ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep);
  66. if (ktp == (ktrace_t*)NULL) {
  67. /*
  68. * KM_SLEEP callers don't expect failure.
  69. */
  70. if (sleep & KM_SLEEP)
  71. panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
  72. return NULL;
  73. }
  74. /*
  75. * Special treatment for buffers with the ktrace_zentries entries
  76. */
  77. if (nentries == ktrace_zentries) {
  78. ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone,
  79. sleep);
  80. } else {
  81. ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
  82. sleep);
  83. }
  84. if (ktep == NULL) {
  85. /*
  86. * KM_SLEEP callers don't expect failure.
  87. */
  88. if (sleep & KM_SLEEP)
  89. panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
  90. kmem_free(ktp, sizeof(*ktp));
  91. return NULL;
  92. }
  93. spinlock_init(&(ktp->kt_lock), "kt_lock");
  94. ktp->kt_entries = ktep;
  95. ktp->kt_nentries = nentries;
  96. ktp->kt_index = 0;
  97. ktp->kt_rollover = 0;
  98. return ktp;
  99. }
  100. /*
  101. * ktrace_free()
  102. *
  103. * Free up the ktrace header and buffer. It is up to the caller
  104. * to ensure that no-one is referencing it.
  105. */
  106. void
  107. ktrace_free(ktrace_t *ktp)
  108. {
  109. int entries_size;
  110. if (ktp == (ktrace_t *)NULL)
  111. return;
  112. spinlock_destroy(&ktp->kt_lock);
  113. /*
  114. * Special treatment for the Vnode trace buffer.
  115. */
  116. if (ktp->kt_nentries == ktrace_zentries) {
  117. kmem_zone_free(ktrace_ent_zone, ktp->kt_entries);
  118. } else {
  119. entries_size = (int)(ktp->kt_nentries * sizeof(ktrace_entry_t));
  120. kmem_free(ktp->kt_entries, entries_size);
  121. }
  122. kmem_zone_free(ktrace_hdr_zone, ktp);
  123. }
  124. /*
  125. * Enter the given values into the "next" entry in the trace buffer.
  126. * kt_index is always the index of the next entry to be filled.
  127. */
  128. void
  129. ktrace_enter(
  130. ktrace_t *ktp,
  131. void *val0,
  132. void *val1,
  133. void *val2,
  134. void *val3,
  135. void *val4,
  136. void *val5,
  137. void *val6,
  138. void *val7,
  139. void *val8,
  140. void *val9,
  141. void *val10,
  142. void *val11,
  143. void *val12,
  144. void *val13,
  145. void *val14,
  146. void *val15)
  147. {
  148. static DEFINE_SPINLOCK(wrap_lock);
  149. unsigned long flags;
  150. int index;
  151. ktrace_entry_t *ktep;
  152. ASSERT(ktp != NULL);
  153. /*
  154. * Grab an entry by pushing the index up to the next one.
  155. */
  156. spin_lock_irqsave(&wrap_lock, flags);
  157. index = ktp->kt_index;
  158. if (++ktp->kt_index == ktp->kt_nentries)
  159. ktp->kt_index = 0;
  160. spin_unlock_irqrestore(&wrap_lock, flags);
  161. if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
  162. ktp->kt_rollover = 1;
  163. ASSERT((index >= 0) && (index < ktp->kt_nentries));
  164. ktep = &(ktp->kt_entries[index]);
  165. ktep->val[0] = val0;
  166. ktep->val[1] = val1;
  167. ktep->val[2] = val2;
  168. ktep->val[3] = val3;
  169. ktep->val[4] = val4;
  170. ktep->val[5] = val5;
  171. ktep->val[6] = val6;
  172. ktep->val[7] = val7;
  173. ktep->val[8] = val8;
  174. ktep->val[9] = val9;
  175. ktep->val[10] = val10;
  176. ktep->val[11] = val11;
  177. ktep->val[12] = val12;
  178. ktep->val[13] = val13;
  179. ktep->val[14] = val14;
  180. ktep->val[15] = val15;
  181. }
  182. /*
  183. * Return the number of entries in the trace buffer.
  184. */
  185. int
  186. ktrace_nentries(
  187. ktrace_t *ktp)
  188. {
  189. if (ktp == NULL) {
  190. return 0;
  191. }
  192. return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
  193. }
  194. /*
  195. * ktrace_first()
  196. *
  197. * This is used to find the start of the trace buffer.
  198. * In conjunction with ktrace_next() it can be used to
  199. * iterate through the entire trace buffer. This code does
  200. * not do any locking because it is assumed that it is called
  201. * from the debugger.
  202. *
  203. * The caller must pass in a pointer to a ktrace_snap
  204. * structure in which we will keep some state used to
  205. * iterate through the buffer. This state must not touched
  206. * by any code outside of this module.
  207. */
  208. ktrace_entry_t *
  209. ktrace_first(ktrace_t *ktp, ktrace_snap_t *ktsp)
  210. {
  211. ktrace_entry_t *ktep;
  212. int index;
  213. int nentries;
  214. if (ktp->kt_rollover)
  215. index = ktp->kt_index;
  216. else
  217. index = 0;
  218. ktsp->ks_start = index;
  219. ktep = &(ktp->kt_entries[index]);
  220. nentries = ktrace_nentries(ktp);
  221. index++;
  222. if (index < nentries) {
  223. ktsp->ks_index = index;
  224. } else {
  225. ktsp->ks_index = 0;
  226. if (index > nentries)
  227. ktep = NULL;
  228. }
  229. return ktep;
  230. }
  231. /*
  232. * ktrace_next()
  233. *
  234. * This is used to iterate through the entries of the given
  235. * trace buffer. The caller must pass in the ktrace_snap_t
  236. * structure initialized by ktrace_first(). The return value
  237. * will be either a pointer to the next ktrace_entry or NULL
  238. * if all of the entries have been traversed.
  239. */
  240. ktrace_entry_t *
  241. ktrace_next(
  242. ktrace_t *ktp,
  243. ktrace_snap_t *ktsp)
  244. {
  245. int index;
  246. ktrace_entry_t *ktep;
  247. index = ktsp->ks_index;
  248. if (index == ktsp->ks_start) {
  249. ktep = NULL;
  250. } else {
  251. ktep = &ktp->kt_entries[index];
  252. }
  253. index++;
  254. if (index == ktrace_nentries(ktp)) {
  255. ktsp->ks_index = 0;
  256. } else {
  257. ktsp->ks_index = index;
  258. }
  259. return ktep;
  260. }
  261. /*
  262. * ktrace_skip()
  263. *
  264. * Skip the next "count" entries and return the entry after that.
  265. * Return NULL if this causes us to iterate past the beginning again.
  266. */
  267. ktrace_entry_t *
  268. ktrace_skip(
  269. ktrace_t *ktp,
  270. int count,
  271. ktrace_snap_t *ktsp)
  272. {
  273. int index;
  274. int new_index;
  275. ktrace_entry_t *ktep;
  276. int nentries = ktrace_nentries(ktp);
  277. index = ktsp->ks_index;
  278. new_index = index + count;
  279. while (new_index >= nentries) {
  280. new_index -= nentries;
  281. }
  282. if (index == ktsp->ks_start) {
  283. /*
  284. * We've iterated around to the start, so we're done.
  285. */
  286. ktep = NULL;
  287. } else if ((new_index < index) && (index < ktsp->ks_index)) {
  288. /*
  289. * We've skipped past the start again, so we're done.
  290. */
  291. ktep = NULL;
  292. ktsp->ks_index = ktsp->ks_start;
  293. } else {
  294. ktep = &(ktp->kt_entries[new_index]);
  295. new_index++;
  296. if (new_index == nentries) {
  297. ktsp->ks_index = 0;
  298. } else {
  299. ktsp->ks_index = new_index;
  300. }
  301. }
  302. return ktep;
  303. }