/*
 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <xfs.h>

static kmem_zone_t *ktrace_hdr_zone;
static kmem_zone_t *ktrace_ent_zone;
static int          ktrace_zentries;

void
ktrace_init(int zentries)
{
	ktrace_zentries = zentries;

	ktrace_hdr_zone = kmem_zone_init(sizeof(ktrace_t),
					"ktrace_hdr");
	ASSERT(ktrace_hdr_zone);

	ktrace_ent_zone = kmem_zone_init(ktrace_zentries
					* sizeof(ktrace_entry_t),
					"ktrace_ent");
	ASSERT(ktrace_ent_zone);
}

void
ktrace_uninit(void)
{
	kmem_zone_destroy(ktrace_hdr_zone);
	kmem_zone_destroy(ktrace_ent_zone);
}

/*
 * ktrace_alloc()
 *
 * Allocate a ktrace header and enough buffering for the given
 * number of entries.
 */
ktrace_t *
ktrace_alloc(int nentries, unsigned int __nocast sleep)
{
	ktrace_t        *ktp;
	ktrace_entry_t  *ktep;

	ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep);

	if (ktp == (ktrace_t*)NULL) {
		/*
		 * KM_SLEEP callers don't expect failure.
		 */
		if (sleep & KM_SLEEP)
			panic("ktrace_alloc: NULL memory on KM_SLEEP request!");

		return NULL;
	}

	/*
	 * Special treatment for buffers with the ktrace_zentries entries
	 */
	if (nentries == ktrace_zentries) {
		ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone,
							    sleep);
	} else {
		ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
							    sleep | KM_LARGE);
	}

	if (ktep == NULL) {
		/*
		 * KM_SLEEP callers don't expect failure.
		 */
		if (sleep & KM_SLEEP)
			panic("ktrace_alloc: NULL memory on KM_SLEEP request!");

		kmem_free(ktp, sizeof(*ktp));

		return NULL;
	}

	spinlock_init(&(ktp->kt_lock), "kt_lock");

	ktp->kt_entries  = ktep;
	ktp->kt_nentries = nentries;
	ktp->kt_index    = 0;
	ktp->kt_rollover = 0;
	return ktp;
}


/*
 * ktrace_free()
 *
 * Free up the ktrace header and buffer.  It is up to the caller
 * to ensure that no-one is referencing it.
 */
void
ktrace_free(ktrace_t *ktp)
{
	int     entries_size;

	if (ktp == (ktrace_t *)NULL)
		return;

	spinlock_destroy(&ktp->kt_lock);

	/*
	 * Special treatment for the Vnode trace buffer.
	 */
	if (ktp->kt_nentries == ktrace_zentries) {
		kmem_zone_free(ktrace_ent_zone, ktp->kt_entries);
	} else {
		entries_size = (int)(ktp->kt_nentries * sizeof(ktrace_entry_t));

		kmem_free(ktp->kt_entries, entries_size);
	}

	kmem_zone_free(ktrace_hdr_zone, ktp);
}


/*
 * Enter the given values into the "next" entry in the trace buffer.
 * kt_index is always the index of the next entry to be filled.
 */
void
ktrace_enter(
	ktrace_t        *ktp,
	void            *val0,
	void            *val1,
	void            *val2,
	void            *val3,
	void            *val4,
	void            *val5,
	void            *val6,
	void            *val7,
	void            *val8,
	void            *val9,
	void            *val10,
	void            *val11,
	void            *val12,
	void            *val13,
	void            *val14,
	void            *val15)
{
	static DEFINE_SPINLOCK(wrap_lock);
	unsigned long	flags;
	int             index;
	ktrace_entry_t  *ktep;

	ASSERT(ktp != NULL);

	/*
	 * Grab an entry by pushing the index up to the next one.
	 */
	spin_lock_irqsave(&wrap_lock, flags);
	index = ktp->kt_index;
	if (++ktp->kt_index == ktp->kt_nentries)
		ktp->kt_index = 0;
	spin_unlock_irqrestore(&wrap_lock, flags);

	if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
		ktp->kt_rollover = 1;

	ASSERT((index >= 0) && (index < ktp->kt_nentries));

	ktep = &(ktp->kt_entries[index]);

	ktep->val[0]  = val0;
	ktep->val[1]  = val1;
	ktep->val[2]  = val2;
	ktep->val[3]  = val3;
	ktep->val[4]  = val4;
	ktep->val[5]  = val5;
	ktep->val[6]  = val6;
	ktep->val[7]  = val7;
	ktep->val[8]  = val8;
	ktep->val[9]  = val9;
	ktep->val[10] = val10;
	ktep->val[11] = val11;
	ktep->val[12] = val12;
	ktep->val[13] = val13;
	ktep->val[14] = val14;
	ktep->val[15] = val15;
}

/*
 * Return the number of entries in the trace buffer.
 */
int
ktrace_nentries(
	ktrace_t        *ktp)
{
	if (ktp == NULL) {
		return 0;
	}

	return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
}

/*
 * ktrace_first()
 *
 * This is used to find the start of the trace buffer.
 * In conjunction with ktrace_next() it can be used to
 * iterate through the entire trace buffer.  This code does
 * not do any locking because it is assumed that it is called
 * from the debugger.
 *
 * The caller must pass in a pointer to a ktrace_snap
 * structure in which we will keep some state used to
 * iterate through the buffer.  This state must not touched
 * by any code outside of this module.
 */
ktrace_entry_t *
ktrace_first(ktrace_t   *ktp, ktrace_snap_t     *ktsp)
{
	ktrace_entry_t  *ktep;
	int             index;
	int             nentries;

	if (ktp->kt_rollover)
		index = ktp->kt_index;
	else
		index = 0;

	ktsp->ks_start = index;
	ktep = &(ktp->kt_entries[index]);

	nentries = ktrace_nentries(ktp);
	index++;
	if (index < nentries) {
		ktsp->ks_index = index;
	} else {
		ktsp->ks_index = 0;
		if (index > nentries)
			ktep = NULL;
	}
	return ktep;
}

/*
 * ktrace_next()
 *
 * This is used to iterate through the entries of the given
 * trace buffer.  The caller must pass in the ktrace_snap_t
 * structure initialized by ktrace_first().  The return value
 * will be either a pointer to the next ktrace_entry or NULL
 * if all of the entries have been traversed.
 */
ktrace_entry_t *
ktrace_next(
	ktrace_t        *ktp,
	ktrace_snap_t   *ktsp)
{
	int             index;
	ktrace_entry_t  *ktep;

	index = ktsp->ks_index;
	if (index == ktsp->ks_start) {
		ktep = NULL;
	} else {
		ktep = &ktp->kt_entries[index];
	}

	index++;
	if (index == ktrace_nentries(ktp)) {
		ktsp->ks_index = 0;
	} else {
		ktsp->ks_index = index;
	}

	return ktep;
}

/*
 * ktrace_skip()
 *
 * Skip the next "count" entries and return the entry after that.
 * Return NULL if this causes us to iterate past the beginning again.
 */
ktrace_entry_t *
ktrace_skip(
	ktrace_t        *ktp,
	int             count,
	ktrace_snap_t   *ktsp)
{
	int             index;
	int             new_index;
	ktrace_entry_t  *ktep;
	int             nentries = ktrace_nentries(ktp);

	index = ktsp->ks_index;
	new_index = index + count;
	while (new_index >= nentries) {
		new_index -= nentries;
	}
	if (index == ktsp->ks_start) {
		/*
		 * We've iterated around to the start, so we're done.
		 */
		ktep = NULL;
	} else if ((new_index < index) && (index < ktsp->ks_index)) {
		/*
		 * We've skipped past the start again, so we're done.
		 */
		ktep = NULL;
		ktsp->ks_index = ktsp->ks_start;
	} else {
		ktep = &(ktp->kt_entries[new_index]);
		new_index++;
		if (new_index == nentries) {
			ktsp->ks_index = 0;
		} else {
			ktsp->ks_index = new_index;
		}
	}
	return ktep;
}
