/*
 * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 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.
 *
 * Further, this software is distributed without any warranty that it is
 * free of the rightful claim of any third person regarding infringement
 * or the like.  Any license provided herein, whether implied or
 * otherwise, applies only to this software file.  Patent licenses, if
 * any, provided herein do not apply to combinations of this program with
 * other software, or any other product whatsoever.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 *
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 * Mountain View, CA  94043, or:
 *
 * http://www.sgi.com
 *
 * For further information regarding this notice, see:
 *
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 */

#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_cache_destroy(ktrace_hdr_zone);
	kmem_cache_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, int 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);
	}

	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 lock_t   wrap_lock = SPIN_LOCK_UNLOCKED;
	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;
}
