/*      $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_ */