/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */



#include "libuutil_common.h"

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/avl.h>

static uu_avl_pool_t	uu_null_apool = { &uu_null_apool, &uu_null_apool };
static pthread_mutex_t	uu_apool_list_lock = PTHREAD_MUTEX_INITIALIZER;

/*
 * The index mark change on every insert and delete, to catch stale
 * references.
 *
 * We leave the low bit alone, since the avl code uses it.
 */
#define	INDEX_MAX		(sizeof (uintptr_t) - 2)
#define	INDEX_NEXT(m)		(((m) == INDEX_MAX)? 2 : ((m) + 2) & INDEX_MAX)

#define	INDEX_DECODE(i)		((i) & ~INDEX_MAX)
#define	INDEX_ENCODE(p, n)	(((n) & ~INDEX_MAX) | (p)->ua_index)
#define	INDEX_VALID(p, i)	(((i) & INDEX_MAX) == (p)->ua_index)
#define	INDEX_CHECK(i)		(((i) & INDEX_MAX) != 0)

/*
 * When an element is inactive (not in a tree), we keep a marked pointer to
 * its containing pool in its first word, and a NULL pointer in its second.
 *
 * On insert, we use these to verify that it comes from the correct pool.
 */
#define	NODE_ARRAY(p, n)	((uintptr_t *)((uintptr_t)(n) + \
				    (pp)->uap_nodeoffset))

#define	POOL_TO_MARKER(pp) (((uintptr_t)(pp) | 1))

#define	DEAD_MARKER		0xc4

uu_avl_pool_t *
uu_avl_pool_create(const char *name, size_t objsize, size_t nodeoffset,
    uu_compare_fn_t *compare_func, uint32_t flags)
{
	uu_avl_pool_t *pp, *next, *prev;

	if (name == NULL ||
	    uu_check_name(name, UU_NAME_DOMAIN) == -1 ||
	    nodeoffset + sizeof (uu_avl_node_t) > objsize ||
	    compare_func == NULL) {
		uu_set_error(UU_ERROR_INVALID_ARGUMENT);
		return (NULL);
	}

	if (flags & ~UU_AVL_POOL_DEBUG) {
		uu_set_error(UU_ERROR_UNKNOWN_FLAG);
		return (NULL);
	}

	pp = uu_zalloc(sizeof (uu_avl_pool_t));
	if (pp == NULL) {
		uu_set_error(UU_ERROR_NO_MEMORY);
		return (NULL);
	}

	(void) strlcpy(pp->uap_name, name, sizeof (pp->uap_name));
	pp->uap_nodeoffset = nodeoffset;
	pp->uap_objsize = objsize;
	pp->uap_cmp = compare_func;
	if (flags & UU_AVL_POOL_DEBUG)
		pp->uap_debug = 1;
	pp->uap_last_index = 0;

	(void) pthread_mutex_init(&pp->uap_lock, NULL);

	pp->uap_null_avl.ua_next_enc = UU_PTR_ENCODE(&pp->uap_null_avl);
	pp->uap_null_avl.ua_prev_enc = UU_PTR_ENCODE(&pp->uap_null_avl);

	(void) pthread_mutex_lock(&uu_apool_list_lock);
	pp->uap_next = next = &uu_null_apool;
	pp->uap_prev = prev = next->uap_prev;
	next->uap_prev = pp;
	prev->uap_next = pp;
	(void) pthread_mutex_unlock(&uu_apool_list_lock);

	return (pp);
}

void
uu_avl_pool_destroy(uu_avl_pool_t *pp)
{
	if (pp->uap_debug) {
		if (pp->uap_null_avl.ua_next_enc !=
		    UU_PTR_ENCODE(&pp->uap_null_avl) ||
		    pp->uap_null_avl.ua_prev_enc !=
		    UU_PTR_ENCODE(&pp->uap_null_avl)) {
			uu_panic("uu_avl_pool_destroy: Pool \"%.*s\" (%p) has "
			    "outstanding avls, or is corrupt.\n",
			    (int)sizeof (pp->uap_name), pp->uap_name,
			    (void *)pp);
		}
	}
	(void) pthread_mutex_lock(&uu_apool_list_lock);
	pp->uap_next->uap_prev = pp->uap_prev;
	pp->uap_prev->uap_next = pp->uap_next;
	(void) pthread_mutex_unlock(&uu_apool_list_lock);
	pp->uap_prev = NULL;
	pp->uap_next = NULL;
	uu_free(pp);
}

void
uu_avl_node_init(void *base, uu_avl_node_t *np, uu_avl_pool_t *pp)
{
	uintptr_t *na = (uintptr_t *)np;

	if (pp->uap_debug) {
		uintptr_t offset = (uintptr_t)np - (uintptr_t)base;
		if (offset + sizeof (*np) > pp->uap_objsize) {
			uu_panic("uu_avl_node_init(%p, %p, %p (\"%s\")): "
			    "offset %ld doesn't fit in object (size %ld)\n",
			    base, (void *)np, (void *)pp, pp->uap_name,
			    (long)offset, (long)pp->uap_objsize);
		}
		if (offset != pp->uap_nodeoffset) {
			uu_panic("uu_avl_node_init(%p, %p, %p (\"%s\")): "
			    "offset %ld doesn't match pool's offset (%ld)\n",
			    base, (void *)np, (void *)pp, pp->uap_name,
			    (long)offset, (long)pp->uap_objsize);
		}
	}

	na[0] = POOL_TO_MARKER(pp);
	na[1] = 0;
}

void
uu_avl_node_fini(void *base, uu_avl_node_t *np, uu_avl_pool_t *pp)
{
	uintptr_t *na = (uintptr_t *)np;

	if (pp->uap_debug) {
		if (na[0] == DEAD_MARKER && na[1] == DEAD_MARKER) {
			uu_panic("uu_avl_node_fini(%p, %p, %p (\"%s\")): "
			    "node already finied\n",
			    base, (void *)np, (void *)pp, pp->uap_name);
		}
		if (na[0] != POOL_TO_MARKER(pp) || na[1] != 0) {
			uu_panic("uu_avl_node_fini(%p, %p, %p (\"%s\")): "
			    "node corrupt, in tree, or in different pool\n",
			    base, (void *)np, (void *)pp, pp->uap_name);
		}
	}

	na[0] = DEAD_MARKER;
	na[1] = DEAD_MARKER;
	na[2] = DEAD_MARKER;
}

struct uu_avl_node_compare_info {
	uu_compare_fn_t	*ac_compare;
	void		*ac_private;
	void		*ac_right;
	void		*ac_found;
};

static int
uu_avl_node_compare(const void *l, const void *r)
{
	struct uu_avl_node_compare_info *info =
	    (struct uu_avl_node_compare_info *)l;

	int res = info->ac_compare(r, info->ac_right, info->ac_private);

	if (res == 0) {
		if (info->ac_found == NULL)
			info->ac_found = (void *)r;
		return (-1);
	}
	if (res < 0)
		return (1);
	return (-1);
}

uu_avl_t *
uu_avl_create(uu_avl_pool_t *pp, void *parent, uint32_t flags)
{
	uu_avl_t *ap, *next, *prev;

	if (flags & ~UU_AVL_DEBUG) {
		uu_set_error(UU_ERROR_UNKNOWN_FLAG);
		return (NULL);
	}

	ap = uu_zalloc(sizeof (*ap));
	if (ap == NULL) {
		uu_set_error(UU_ERROR_NO_MEMORY);
		return (NULL);
	}

	ap->ua_pool = pp;
	ap->ua_parent_enc = UU_PTR_ENCODE(parent);
	ap->ua_debug = pp->uap_debug || (flags & UU_AVL_DEBUG);
	ap->ua_index = (pp->uap_last_index = INDEX_NEXT(pp->uap_last_index));

	avl_create(&ap->ua_tree, &uu_avl_node_compare, pp->uap_objsize,
	    pp->uap_nodeoffset);

	ap->ua_null_walk.uaw_next = &ap->ua_null_walk;
	ap->ua_null_walk.uaw_prev = &ap->ua_null_walk;

	(void) pthread_mutex_lock(&pp->uap_lock);
	next = &pp->uap_null_avl;
	prev = UU_PTR_DECODE(next->ua_prev_enc);
	ap->ua_next_enc = UU_PTR_ENCODE(next);
	ap->ua_prev_enc = UU_PTR_ENCODE(prev);
	next->ua_prev_enc = UU_PTR_ENCODE(ap);
	prev->ua_next_enc = UU_PTR_ENCODE(ap);
	(void) pthread_mutex_unlock(&pp->uap_lock);

	return (ap);
}

void
uu_avl_destroy(uu_avl_t *ap)
{
	uu_avl_pool_t *pp = ap->ua_pool;

	if (ap->ua_debug) {
		if (avl_numnodes(&ap->ua_tree) != 0) {
			uu_panic("uu_avl_destroy(%p): tree not empty\n",
			    (void *)ap);
		}
		if (ap->ua_null_walk.uaw_next != &ap->ua_null_walk ||
		    ap->ua_null_walk.uaw_prev != &ap->ua_null_walk) {
			uu_panic("uu_avl_destroy(%p):  outstanding walkers\n",
			    (void *)ap);
		}
	}
	(void) pthread_mutex_lock(&pp->uap_lock);
	UU_AVL_PTR(ap->ua_next_enc)->ua_prev_enc = ap->ua_prev_enc;
	UU_AVL_PTR(ap->ua_prev_enc)->ua_next_enc = ap->ua_next_enc;
	(void) pthread_mutex_unlock(&pp->uap_lock);
	ap->ua_prev_enc = UU_PTR_ENCODE(NULL);
	ap->ua_next_enc = UU_PTR_ENCODE(NULL);

	ap->ua_pool = NULL;
	avl_destroy(&ap->ua_tree);

	uu_free(ap);
}

size_t
uu_avl_numnodes(uu_avl_t *ap)
{
	return (avl_numnodes(&ap->ua_tree));
}

void *
uu_avl_first(uu_avl_t *ap)
{
	return (avl_first(&ap->ua_tree));
}

void *
uu_avl_last(uu_avl_t *ap)
{
	return (avl_last(&ap->ua_tree));
}

void *
uu_avl_next(uu_avl_t *ap, void *node)
{
	return (AVL_NEXT(&ap->ua_tree, node));
}

void *
uu_avl_prev(uu_avl_t *ap, void *node)
{
	return (AVL_PREV(&ap->ua_tree, node));
}

static void
_avl_walk_init(uu_avl_walk_t *wp, uu_avl_t *ap, uint32_t flags)
{
	uu_avl_walk_t *next, *prev;

	int robust = (flags & UU_WALK_ROBUST);
	int direction = (flags & UU_WALK_REVERSE)? -1 : 1;

	(void) memset(wp, 0, sizeof (*wp));
	wp->uaw_avl = ap;
	wp->uaw_robust = robust;
	wp->uaw_dir = direction;

	if (direction > 0)
		wp->uaw_next_result = avl_first(&ap->ua_tree);
	else
		wp->uaw_next_result = avl_last(&ap->ua_tree);

	if (ap->ua_debug || robust) {
		wp->uaw_next = next = &ap->ua_null_walk;
		wp->uaw_prev = prev = next->uaw_prev;
		next->uaw_prev = wp;
		prev->uaw_next = wp;
	}
}

static void *
_avl_walk_advance(uu_avl_walk_t *wp, uu_avl_t *ap)
{
	void *np = wp->uaw_next_result;

	avl_tree_t *t = &ap->ua_tree;

	if (np == NULL)
		return (NULL);

	wp->uaw_next_result = (wp->uaw_dir > 0)? AVL_NEXT(t, np) :
	    AVL_PREV(t, np);

	return (np);
}

static void
_avl_walk_fini(uu_avl_walk_t *wp)
{
	if (wp->uaw_next != NULL) {
		wp->uaw_next->uaw_prev = wp->uaw_prev;
		wp->uaw_prev->uaw_next = wp->uaw_next;
		wp->uaw_next = NULL;
		wp->uaw_prev = NULL;
	}
	wp->uaw_avl = NULL;
	wp->uaw_next_result = NULL;
}

uu_avl_walk_t *
uu_avl_walk_start(uu_avl_t *ap, uint32_t flags)
{
	uu_avl_walk_t *wp;

	if (flags & ~(UU_WALK_ROBUST | UU_WALK_REVERSE)) {
		uu_set_error(UU_ERROR_UNKNOWN_FLAG);
		return (NULL);
	}

	wp = uu_zalloc(sizeof (*wp));
	if (wp == NULL) {
		uu_set_error(UU_ERROR_NO_MEMORY);
		return (NULL);
	}

	_avl_walk_init(wp, ap, flags);
	return (wp);
}

void *
uu_avl_walk_next(uu_avl_walk_t *wp)
{
	return (_avl_walk_advance(wp, wp->uaw_avl));
}

void
uu_avl_walk_end(uu_avl_walk_t *wp)
{
	_avl_walk_fini(wp);
	uu_free(wp);
}

int
uu_avl_walk(uu_avl_t *ap, uu_walk_fn_t *func, void *private, uint32_t flags)
{
	void *e;
	uu_avl_walk_t my_walk;

	int status = UU_WALK_NEXT;

	if (flags & ~(UU_WALK_ROBUST | UU_WALK_REVERSE)) {
		uu_set_error(UU_ERROR_UNKNOWN_FLAG);
		return (-1);
	}

	_avl_walk_init(&my_walk, ap, flags);
	while (status == UU_WALK_NEXT &&
	    (e = _avl_walk_advance(&my_walk, ap)) != NULL)
		status = (*func)(e, private);
	_avl_walk_fini(&my_walk);

	if (status >= 0)
		return (0);
	uu_set_error(UU_ERROR_CALLBACK_FAILED);
	return (-1);
}

void
uu_avl_remove(uu_avl_t *ap, void *elem)
{
	uu_avl_walk_t *wp;
	uu_avl_pool_t *pp = ap->ua_pool;
	uintptr_t *na = NODE_ARRAY(pp, elem);

	if (ap->ua_debug) {
		/*
		 * invalidate outstanding uu_avl_index_ts.
		 */
		ap->ua_index = INDEX_NEXT(ap->ua_index);
	}

	/*
	 * Robust walkers most be advanced, if we are removing the node
	 * they are currently using.  In debug mode, non-robust walkers
	 * are also on the walker list.
	 */
	for (wp = ap->ua_null_walk.uaw_next; wp != &ap->ua_null_walk;
	    wp = wp->uaw_next) {
		if (wp->uaw_robust) {
			if (elem == wp->uaw_next_result)
				(void) _avl_walk_advance(wp, ap);
		} else if (wp->uaw_next_result != NULL) {
			uu_panic("uu_avl_remove(%p, %p): active non-robust "
			    "walker\n", (void *)ap, elem);
		}
	}

	avl_remove(&ap->ua_tree, elem);

	na[0] = POOL_TO_MARKER(pp);
	na[1] = 0;
}

void *
uu_avl_teardown(uu_avl_t *ap, void **cookie)
{
	void *elem = avl_destroy_nodes(&ap->ua_tree, cookie);

	if (elem != NULL) {
		uu_avl_pool_t *pp = ap->ua_pool;
		uintptr_t *na = NODE_ARRAY(pp, elem);

		na[0] = POOL_TO_MARKER(pp);
		na[1] = 0;
	}
	return (elem);
}

void *
uu_avl_find(uu_avl_t *ap, void *elem, void *private, uu_avl_index_t *out)
{
	struct uu_avl_node_compare_info info;
	void *result;

	info.ac_compare = ap->ua_pool->uap_cmp;
	info.ac_private = private;
	info.ac_right = elem;
	info.ac_found = NULL;

	result = avl_find(&ap->ua_tree, &info, out);
	if (out != NULL)
		*out = INDEX_ENCODE(ap, *out);

	if (ap->ua_debug && result != NULL)
		uu_panic("uu_avl_find: internal error: avl_find succeeded\n");

	return (info.ac_found);
}

void
uu_avl_insert(uu_avl_t *ap, void *elem, uu_avl_index_t idx)
{
	if (ap->ua_debug) {
		uu_avl_pool_t *pp = ap->ua_pool;
		uintptr_t *na = NODE_ARRAY(pp, elem);

		if (na[1] != 0)
			uu_panic("uu_avl_insert(%p, %p, %p): node already "
			    "in tree, or corrupt\n",
			    (void *)ap, elem, (void *)idx);
		if (na[0] == 0)
			uu_panic("uu_avl_insert(%p, %p, %p): node not "
			    "initialized\n",
			    (void *)ap, elem, (void *)idx);
		if (na[0] != POOL_TO_MARKER(pp))
			uu_panic("uu_avl_insert(%p, %p, %p): node from "
			    "other pool, or corrupt\n",
			    (void *)ap, elem, (void *)idx);

		if (!INDEX_VALID(ap, idx))
			uu_panic("uu_avl_insert(%p, %p, %p): %s\n",
			    (void *)ap, elem, (void *)idx,
			    INDEX_CHECK(idx)? "outdated index" :
			    "invalid index");

		/*
		 * invalidate outstanding uu_avl_index_ts.
		 */
		ap->ua_index = INDEX_NEXT(ap->ua_index);
	}
	avl_insert(&ap->ua_tree, elem, INDEX_DECODE(idx));
}

void *
uu_avl_nearest_next(uu_avl_t *ap, uu_avl_index_t idx)
{
	if (ap->ua_debug && !INDEX_VALID(ap, idx))
		uu_panic("uu_avl_nearest_next(%p, %p): %s\n",
		    (void *)ap, (void *)idx, INDEX_CHECK(idx)?
		    "outdated index" : "invalid index");
	return (avl_nearest(&ap->ua_tree, INDEX_DECODE(idx), AVL_AFTER));
}

void *
uu_avl_nearest_prev(uu_avl_t *ap, uu_avl_index_t idx)
{
	if (ap->ua_debug && !INDEX_VALID(ap, idx))
		uu_panic("uu_avl_nearest_prev(%p, %p): %s\n",
		    (void *)ap, (void *)idx, INDEX_CHECK(idx)?
		    "outdated index" : "invalid index");
	return (avl_nearest(&ap->ua_tree, INDEX_DECODE(idx), AVL_BEFORE));
}

/*
 * called from uu_lockup() and uu_release(), as part of our fork1()-safety.
 */
void
uu_avl_lockup(void)
{
	uu_avl_pool_t *pp;

	(void) pthread_mutex_lock(&uu_apool_list_lock);
	for (pp = uu_null_apool.uap_next; pp != &uu_null_apool;
	    pp = pp->uap_next)
		(void) pthread_mutex_lock(&pp->uap_lock);
}

void
uu_avl_release(void)
{
	uu_avl_pool_t *pp;

	for (pp = uu_null_apool.uap_next; pp != &uu_null_apool;
	    pp = pp->uap_next)
		(void) pthread_mutex_unlock(&pp->uap_lock);
	(void) pthread_mutex_unlock(&uu_apool_list_lock);
}
