2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 static kmem_zone_t *ktrace_hdr_zone;
21 static kmem_zone_t *ktrace_ent_zone;
22 static int ktrace_zentries;
23 static struct mtx wrap_lock;
26 ktrace_init(int zentries)
28 ktrace_zentries = zentries;
30 ktrace_hdr_zone = kmem_zone_init(sizeof(ktrace_t),
32 ASSERT(ktrace_hdr_zone);
34 ktrace_ent_zone = kmem_zone_init(ktrace_zentries
35 * sizeof(ktrace_entry_t),
37 ASSERT(ktrace_ent_zone);
39 mtx_init(&wrap_lock, "xfsktr", NULL, MTX_DEF);
45 kmem_zone_destroy(ktrace_hdr_zone);
46 kmem_zone_destroy(ktrace_ent_zone);
48 mtx_destroy(&wrap_lock);
54 * Allocate a ktrace header and enough buffering for the given
58 ktrace_alloc(int nentries, int sleep)
63 ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep);
65 if (ktp == (ktrace_t*)NULL) {
67 * KM_SLEEP callers don't expect failure.
70 panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
76 * Special treatment for buffers with the ktrace_zentries entries
78 if (nentries == ktrace_zentries) {
79 ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone,
82 ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
88 * KM_SLEEP callers don't expect failure.
91 panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
93 kmem_free(ktp, sizeof(*ktp));
98 spinlock_init(&(ktp->kt_lock), "kt_lock");
100 ktp->kt_entries = ktep;
101 ktp->kt_nentries = nentries;
103 ktp->kt_rollover = 0;
111 * Free up the ktrace header and buffer. It is up to the caller
112 * to ensure that no-one is referencing it.
115 ktrace_free(ktrace_t *ktp)
119 if (ktp == (ktrace_t *)NULL)
122 spinlock_destroy(&ktp->kt_lock);
125 * Special treatment for the Vnode trace buffer.
127 if (ktp->kt_nentries == ktrace_zentries) {
128 kmem_zone_free(ktrace_ent_zone, ktp->kt_entries);
130 entries_size = (int)(ktp->kt_nentries * sizeof(ktrace_entry_t));
132 kmem_free(ktp->kt_entries, entries_size);
135 kmem_zone_free(ktrace_hdr_zone, ktp);
140 * Enter the given values into the "next" entry in the trace buffer.
141 * kt_index is always the index of the next entry to be filled.
164 ktrace_entry_t *ktep;
169 * Grab an entry by pushing the index up to the next one.
171 mtx_lock(&wrap_lock);
172 index = ktp->kt_index;
173 if (++ktp->kt_index == ktp->kt_nentries)
175 mtx_unlock(&wrap_lock);
177 if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
178 ktp->kt_rollover = 1;
180 ASSERT((index >= 0) && (index < ktp->kt_nentries));
182 ktep = &(ktp->kt_entries[index]);
194 ktep->val[10] = val10;
195 ktep->val[11] = val11;
196 ktep->val[12] = val12;
197 ktep->val[13] = val13;
198 ktep->val[14] = val14;
199 ktep->val[15] = val15;
203 * Return the number of entries in the trace buffer.
213 return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
219 * This is used to find the start of the trace buffer.
220 * In conjunction with ktrace_next() it can be used to
221 * iterate through the entire trace buffer. This code does
222 * not do any locking because it is assumed that it is called
225 * The caller must pass in a pointer to a ktrace_snap
226 * structure in which we will keep some state used to
227 * iterate through the buffer. This state must not touched
228 * by any code outside of this module.
231 ktrace_first(ktrace_t *ktp, ktrace_snap_t *ktsp)
233 ktrace_entry_t *ktep;
237 if (ktp->kt_rollover)
238 index = ktp->kt_index;
242 ktsp->ks_start = index;
243 ktep = &(ktp->kt_entries[index]);
245 nentries = ktrace_nentries(ktp);
247 if (index < nentries) {
248 ktsp->ks_index = index;
251 if (index > nentries)
260 * This is used to iterate through the entries of the given
261 * trace buffer. The caller must pass in the ktrace_snap_t
262 * structure initialized by ktrace_first(). The return value
263 * will be either a pointer to the next ktrace_entry or NULL
264 * if all of the entries have been traversed.
272 ktrace_entry_t *ktep;
274 index = ktsp->ks_index;
275 if (index == ktsp->ks_start) {
278 ktep = &ktp->kt_entries[index];
282 if (index == ktrace_nentries(ktp)) {
285 ktsp->ks_index = index;
294 * Skip the next "count" entries and return the entry after that.
295 * Return NULL if this causes us to iterate past the beginning again.
305 ktrace_entry_t *ktep;
306 int nentries = ktrace_nentries(ktp);
308 index = ktsp->ks_index;
309 new_index = index + count;
310 while (new_index >= nentries) {
311 new_index -= nentries;
313 if (index == ktsp->ks_start) {
315 * We've iterated around to the start, so we're done.
318 } else if ((new_index < index) && (index < ktsp->ks_index)) {
320 * We've skipped past the start again, so we're done.
323 ktsp->ks_index = ktsp->ks_start;
325 ktep = &(ktp->kt_entries[new_index]);
327 if (new_index == nentries) {
330 ktsp->ks_index = new_index;