/*	$NetBSD$ */

/*-
 * Copyright (c) 2006 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the NetBSD
 *      Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _PROPLIB_PROP_SYSTEM_IMPL_H_
#define	_PROPLIB_PROP_SYSTEM_IMPL_H_

#if defined(_KERNEL)

/*
 * proplib in the kernel...
 */

#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/pool.h>
#include <sys/systm.h>
#include <sys/lock.h>

#define	_PROP_ASSERT(x)		KASSERT(x)

#define	_PROP_MALLOC(s, t)	malloc((s), (t), M_WAITOK)
#define	_PROP_CALLOC(s, t)	malloc((s), (t), M_WAITOK | M_ZERO)
#define	_PROP_REALLOC(v, s, t)	realloc((v), (s), (t), M_WAITOK)
#define	_PROP_FREE(v, t)	free((v), (t))

#define	_PROP_POOL_GET(p)	pool_get(&(p), PR_WAITOK)
#define	_PROP_POOL_PUT(p, v)	pool_put(&(p), (v))

#define	_PROP_POOL_INIT(p, s, d)					\
		POOL_INIT(p, s, 0, 0, 0, d, &pool_allocator_nointr, IPL_NONE);

#define	_PROP_MALLOC_DEFINE(t, s, l)					\
		MALLOC_DEFINE(t, s, l);
#define _PROP_MALLOC_DECLARE(t) 					\
		MALLOC_DECLARE(t);

#define	_PROP_MUTEX_DECL_STATIC(x)					\
		static struct simplelock x = SIMPLELOCK_INITIALIZER;
#define	_PROP_MUTEX_LOCK(x)	simple_lock(&(x))
#define	_PROP_MUTEX_UNLOCK(x)	simple_unlock(&(x))

#define	_PROP_RWLOCK_DECL(x)	struct lock x ;
#define	_PROP_RWLOCK_INIT(x)	lockinit(&(x), PZERO, "proprwlk", 0, 0)
#define	_PROP_RWLOCK_RDLOCK(x)	lockmgr(&(x), LK_SHARED, NULL)
#define	_PROP_RWLOCK_WRLOCK(x)	lockmgr(&(x), LK_EXCLUSIVE, NULL)
#define	_PROP_RWLOCK_UNLOCK(x)	lockmgr(&(x), LK_RELEASE, NULL)
#define	_PROP_RWLOCK_DESTROY(x)	lockmgr(&(x), LK_DRAIN, NULL)

#elif defined(_STANDALONE)

/*
 * proplib in a standalone environment...
 */

#include <lib/libsa/stand.h>

void *		_prop_standalone_calloc(size_t);
void *		_prop_standalone_realloc(void *, size_t);

#define	_PROP_ASSERT(x)		/* nothing */

#define	_PROP_MALLOC(s, t)	alloc((s))
#define	_PROP_CALLOC(s, t)	_prop_standalone_calloc((s))
#define	_PROP_REALLOC(v, s, t)	_prop_standalone_realloc((v), (s))
#define	_PROP_FREE(v, t)	dealloc((v), 0)		/* XXX */

#define	_PROP_POOL_GET(p)	alloc((p))
#define	_PROP_POOL_PUT(p, v)	dealloc((v), (p))

#define	_PROP_POOL_INIT(p, s, d)	static const size_t p = s;

#define	_PROP_MALLOC_DEFINE(t, s, l)	/* nothing */
#define _PROP_MALLOC_DECLARE(t) 	/* nothing */

#define	_PROP_MUTEX_DECL_STATIC(x)	/* nothing */
#define	_PROP_MUTEX_LOCK(x)		/* nothing */
#define	_PROP_MUTEX_UNLOCK(x)		/* nothing */

#define	_PROP_RWLOCK_DECL(x)	/* nothing */
#define	_PROP_RWLOCK_INIT(x)	/* nothing */
#define	_PROP_RWLOCK_RDLOCK(x)	/* nothing */
#define	_PROP_RWLOCK_WRLOCK(x)	/* nothing */
#define	_PROP_RWLOCK_UNLOCK(x)	/* nothing */
#define	_PROP_RWLOCK_DESTROY(x)	/* nothing */

#else

/*
 * proplib in user space...
 */

#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

#define	_PROP_ASSERT(x)		/*LINTED*/assert(x)

#define	_PROP_MALLOC(s, t)	malloc((s))
#define	_PROP_CALLOC(s, t)	calloc(1, (s))
#define	_PROP_REALLOC(v, s, t)	realloc((v), (s))
#define	_PROP_FREE(v, t)	free((v))

#define	_PROP_POOL_GET(p)	malloc((p))
#define	_PROP_POOL_PUT(p, v)	free((v))

#define	_PROP_POOL_INIT(p, s, d)	static const size_t p = s;

#define	_PROP_MALLOC_DEFINE(t, s, l)	/* nothing */
#define _PROP_MALLOC_DECLARE(t) 	/* nothing */

#if defined(__NetBSD__) && defined(_LIBPROP)
/*
 * Use the same mechanism as libc; we get pthread mutexes for threaded
 * programs and do-nothing stubs for non-threaded programs.
 */
#include "reentrant.h"
#define	_PROP_MUTEX_DECL_STATIC(x)	static mutex_t x = MUTEX_INITIALIZER;
#define	_PROP_MUTEX_LOCK(x)		mutex_lock(&(x))
#define	_PROP_MUTEX_UNLOCK(x)		mutex_unlock(&(x))

#define	_PROP_RWLOCK_DECL(x)	rwlock_t x ;
#define	_PROP_RWLOCK_INIT(x)	rwlock_init(&(x), NULL)
#define	_PROP_RWLOCK_RDLOCK(x)	rwlock_rdlock(&(x))
#define	_PROP_RWLOCK_WRLOCK(x)	rwlock_wrlock(&(x))
#define	_PROP_RWLOCK_UNLOCK(x)	rwlock_unlock(&(x))
#define	_PROP_RWLOCK_DESTROY(x)	rwlock_destroy(&(x))
#elif defined(HAVE_NBTOOL_CONFIG_H)
/*
 * None of NetBSD's build tools are multi-threaded.
 */
#define	_PROP_MUTEX_DECL_STATIC(x)	/* nothing */
#define	_PROP_MUTEX_LOCK(x)		/* nothing */
#define	_PROP_MUTEX_UNLOCK(x)		/* nothing */

#define	_PROP_RWLOCK_DECL(x)	/* nothing */
#define	_PROP_RWLOCK_INIT(x)	/* nothing */
#define	_PROP_RWLOCK_RDLOCK(x)	/* nothing */
#define	_PROP_RWLOCK_WRLOCK(x)	/* nothing */
#define	_PROP_RWLOCK_UNLOCK(x)	/* nothing */
#define	_PROP_RWLOCK_DESTROY(x)	/* nothing */
#else
/*
 * Use pthread mutexes everywhere else.
 */
#include <pthread.h>
#define	_PROP_MUTEX_DECL_STATIC(x)					\
		static pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
#define	_PROP_MUTEX_LOCK(x)	pthread_mutex_lock(&(x))
#define	_PROP_MUTEX_UNLOCK(x)	pthread_mutex_unlock(&(x))

#define	_PROP_RWLOCK_DECL(x)	pthread_rwlock_t x ;
#define	_PROP_RWLOCK_INIT(x)	pthread_rwlock_init(&(x), NULL)
#define	_PROP_RWLOCK_RDLOCK(x)	pthread_rwlock_rdlock(&(x))
#define	_PROP_RWLOCK_WRLOCK(x)	pthread_rwlock_wrlock(&(x))
#define	_PROP_RWLOCK_UNLOCK(x)	pthread_rwlock_unlock(&(x))
#define	_PROP_RWLOCK_DESTROY(x)	pthread_rwlock_destroy(&(x))
#endif

#endif /* _KERNEL */

/*
 * Language features.
 */
#if defined(__NetBSD__)
#include <sys/cdefs.h>
#define	_PROP_ARG_UNUSED	__unused
#else
#define	_PROP_ARG_UNUSED	/* delete */
#endif /* __NetBSD__ */

#endif /* _PROPLIB_PROP_SYSTEM_IMPL_H_ */
