summaryrefslogtreecommitdiff
path: root/common/lib/libprop
diff options
context:
space:
mode:
authorpooka <pooka@NetBSD.org>2009-01-03 18:31:33 +0000
committerpooka <pooka@NetBSD.org>2009-01-03 18:31:33 +0000
commitb6e6025d0df49896e81e796411de5be0d1cbb00a (patch)
tree07cb9997e882a1df8e425525e7c0edf5df0cfd70 /common/lib/libprop
parent5eea853f3e07fba1057c271d08fc2cce77834368 (diff)
Get rid of locks with static initializers using once and atomic ops.
This makes proplib simplelock-free.
Diffstat (limited to 'common/lib/libprop')
-rw-r--r--common/lib/libprop/prop_bool.c39
-rw-r--r--common/lib/libprop/prop_dictionary.c37
-rw-r--r--common/lib/libprop/prop_number.c38
-rw-r--r--common/lib/libprop/prop_object.c53
-rw-r--r--common/lib/libprop/prop_object_impl.h48
5 files changed, 118 insertions, 97 deletions
diff --git a/common/lib/libprop/prop_bool.c b/common/lib/libprop/prop_bool.c
index 4e2bc2bda37..d9e912b2cc4 100644
--- a/common/lib/libprop/prop_bool.c
+++ b/common/lib/libprop/prop_bool.c
@@ -1,4 +1,4 @@
-/* $NetBSD: prop_bool.c,v 1.16 2008/08/03 04:00:12 thorpej Exp $ */
+/* $NetBSD: prop_bool.c,v 1.17 2009/01/03 18:31:33 pooka Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -40,9 +40,6 @@ struct _prop_bool {
static struct _prop_bool _prop_bool_true;
static struct _prop_bool _prop_bool_false;
-_PROP_MUTEX_DECL_STATIC(_prop_bool_initialized_mutex)
-static bool _prop_bool_initialized;
-
static _prop_object_free_rv_t
_prop_bool_free(prop_stack_t, prop_object_t *);
static bool _prop_bool_externalize(
@@ -109,27 +106,29 @@ _prop_bool_equals(prop_object_t v1, prop_object_t v2,
return (_PROP_OBJECT_EQUALS_FALSE);
}
-static prop_bool_t
-_prop_bool_alloc(bool val)
+_PROP_ONCE_DECL(_prop_bool_init_once)
+
+static int
+_prop_bool_init(void)
{
- prop_bool_t pb;
- if (! _prop_bool_initialized) {
- _PROP_MUTEX_LOCK(_prop_bool_initialized_mutex);
- if (! _prop_bool_initialized) {
- _prop_object_init(&_prop_bool_true.pb_obj,
- &_prop_object_type_bool);
- _prop_bool_true.pb_value = true;
+ _prop_object_init(&_prop_bool_true.pb_obj,
+ &_prop_object_type_bool);
+ _prop_bool_true.pb_value = true;
- _prop_object_init(&_prop_bool_false.pb_obj,
- &_prop_object_type_bool);
- _prop_bool_false.pb_value = false;
+ _prop_object_init(&_prop_bool_false.pb_obj,
+ &_prop_object_type_bool);
+ _prop_bool_false.pb_value = false;
- _prop_bool_initialized = true;
- }
- _PROP_MUTEX_UNLOCK(_prop_bool_initialized_mutex);
- }
+ return 0;
+}
+
+static prop_bool_t
+_prop_bool_alloc(bool val)
+{
+ prop_bool_t pb;
+ _PROP_ONCE_RUN(_prop_bool_init_once, _prop_bool_init);
pb = val ? &_prop_bool_true : &_prop_bool_false;
prop_object_retain(pb);
diff --git a/common/lib/libprop/prop_dictionary.c b/common/lib/libprop/prop_dictionary.c
index 4ccec00e65c..9f0443dca80 100644
--- a/common/lib/libprop/prop_dictionary.c
+++ b/common/lib/libprop/prop_dictionary.c
@@ -1,4 +1,4 @@
-/* $NetBSD: prop_dictionary.c,v 1.33 2008/11/30 00:17:07 haad Exp $ */
+/* $NetBSD: prop_dictionary.c,v 1.34 2009/01/03 18:31:33 pooka Exp $ */
/*-
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
@@ -201,10 +201,20 @@ static const struct rb_tree_ops _prop_dict_keysym_rb_tree_ops = {
};
static struct rb_tree _prop_dict_keysym_tree;
-static bool _prop_dict_keysym_tree_initialized;
+_PROP_ONCE_DECL(_prop_dict_init_once)
_PROP_MUTEX_DECL_STATIC(_prop_dict_keysym_tree_mutex)
+static int
+_prop_dict_init(void)
+{
+
+ _PROP_MUTEX_INIT(_prop_dict_keysym_tree_mutex);
+ _prop_rb_tree_init(&_prop_dict_keysym_tree,
+ &_prop_dict_keysym_rb_tree_ops);
+ return 0;
+}
+
static void
_prop_dict_keysym_put(prop_dictionary_keysym_t pdk)
{
@@ -277,23 +287,19 @@ _prop_dict_keysym_alloc(const char *key)
size_t size;
bool rv;
+ _PROP_ONCE_RUN(_prop_dict_init_once, _prop_dict_init);
+
/*
* Check to see if this already exists in the tree. If it does,
* we just retain it and return it.
*/
_PROP_MUTEX_LOCK(_prop_dict_keysym_tree_mutex);
- if (! _prop_dict_keysym_tree_initialized) {
- _prop_rb_tree_init(&_prop_dict_keysym_tree,
- &_prop_dict_keysym_rb_tree_ops);
- _prop_dict_keysym_tree_initialized = true;
- } else {
- n = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
- if (n != NULL) {
- opdk = RBNODE_TO_PDK(n);
- prop_object_retain(opdk);
- _PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
- return (opdk);
- }
+ n = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
+ if (n != NULL) {
+ opdk = RBNODE_TO_PDK(n);
+ prop_object_retain(opdk);
+ _PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
+ return (opdk);
}
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
@@ -394,6 +400,9 @@ _prop_dictionary_free(prop_stack_t stack, prop_object_t *obj)
static void
_prop_dictionary_lock(void)
{
+
+ /* XXX: once necessary or paranoia? */
+ _PROP_ONCE_RUN(_prop_dict_init_once, _prop_dict_init);
_PROP_MUTEX_LOCK(_prop_dict_keysym_tree_mutex);
}
diff --git a/common/lib/libprop/prop_number.c b/common/lib/libprop/prop_number.c
index 9f5cb18c742..ec1fb123971 100644
--- a/common/lib/libprop/prop_number.c
+++ b/common/lib/libprop/prop_number.c
@@ -1,4 +1,4 @@
-/* $NetBSD: prop_number.c,v 1.20 2008/11/30 00:17:07 haad Exp $ */
+/* $NetBSD: prop_number.c,v 1.21 2009/01/03 18:31:33 pooka Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -147,8 +147,6 @@ static const struct rb_tree_ops _prop_number_rb_tree_ops = {
};
static struct rb_tree _prop_number_tree;
-static bool _prop_number_tree_initialized;
-
_PROP_MUTEX_DECL_STATIC(_prop_number_tree_mutex)
/* ARGSUSED */
@@ -164,9 +162,23 @@ _prop_number_free(prop_stack_t stack, prop_object_t *obj)
return (_PROP_OBJECT_FREE_DONE);
}
+_PROP_ONCE_DECL(_prop_number_init_once)
+
+static int
+_prop_number_init(void)
+{
+
+ _PROP_MUTEX_INIT(_prop_number_tree_mutex);
+ _prop_rb_tree_init(&_prop_number_tree,
+ &_prop_number_rb_tree_ops);
+ return 0;
+}
+
static void
_prop_number_lock()
{
+ /* XXX: init necessary? */
+ _PROP_ONCE_RUN(_prop_number_init_once, _prop_number_init);
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
}
@@ -263,23 +275,19 @@ _prop_number_alloc(const struct _prop_number_value *pnv)
struct rb_node *n;
bool rv;
+ _PROP_ONCE_RUN(_prop_number_init_once, _prop_number_init);
+
/*
* Check to see if this already exists in the tree. If it does,
* we just retain it and return it.
*/
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
- if (! _prop_number_tree_initialized) {
- _prop_rb_tree_init(&_prop_number_tree,
- &_prop_number_rb_tree_ops);
- _prop_number_tree_initialized = true;
- } else {
- n = _prop_rb_tree_find(&_prop_number_tree, pnv);
- if (n != NULL) {
- opn = RBNODE_TO_PN(n);
- prop_object_retain(opn);
- _PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
- return (opn);
- }
+ n = _prop_rb_tree_find(&_prop_number_tree, pnv);
+ if (n != NULL) {
+ opn = RBNODE_TO_PN(n);
+ prop_object_retain(opn);
+ _PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
+ return (opn);
}
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
diff --git a/common/lib/libprop/prop_object.c b/common/lib/libprop/prop_object.c
index 5740a5d72b4..938b11d6317 100644
--- a/common/lib/libprop/prop_object.c
+++ b/common/lib/libprop/prop_object.c
@@ -1,4 +1,4 @@
-/* $NetBSD: prop_object.c,v 1.23 2008/11/30 00:17:07 haad Exp $ */
+/* $NetBSD: prop_object.c,v 1.24 2009/01/03 18:31:34 pooka Exp $ */
/*-
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
@@ -40,6 +40,7 @@
#include <limits.h>
#include <unistd.h>
#endif
+#include <sys/atomic.h>
#ifdef _STANDALONE
void *
@@ -972,24 +973,6 @@ _prop_object_internalize_unmap_file(
#endif /* !_KERNEL && !_STANDALONE */
/*
- * Retain / release serialization --
- *
- * Eventually we would like to use atomic operations. But until we have
- * an MI API for them that is common to userland and the kernel, we will
- * use a lock instead.
- *
- * We use a single global mutex for all serialization. In the kernel, because
- * we are still under a biglock, this will basically never contend (properties
- * cannot be manipulated at interrupt level). In userland, this will cost
- * nothing for single-threaded programs. For multi-threaded programs, there
- * could be contention, but it probably won't cost that much unless the program
- * makes heavy use of property lists.
- */
-_PROP_MUTEX_DECL_STATIC(_prop_refcnt_mutex)
-#define _PROP_REFCNT_LOCK() _PROP_MUTEX_LOCK(_prop_refcnt_mutex)
-#define _PROP_REFCNT_UNLOCK() _PROP_MUTEX_UNLOCK(_prop_refcnt_mutex)
-
-/*
* prop_object_retain --
* Increment the reference count on an object.
*/
@@ -997,13 +980,10 @@ void
prop_object_retain(prop_object_t obj)
{
struct _prop_object *po = obj;
- uint32_t ocnt;
+ uint32_t ncnt;
- _PROP_REFCNT_LOCK();
- ocnt = po->po_refcnt++;
- _PROP_REFCNT_UNLOCK();
-
- _PROP_ASSERT(ocnt != 0xffffffffU);
+ ncnt = atomic_inc_32_nv(&po->po_refcnt);
+ _PROP_ASSERT(ncnt != 0);
}
/*
@@ -1033,11 +1013,11 @@ prop_object_release_emergency(prop_object_t obj)
/* Save pointerto unlock function */
unlock = po->po_type->pot_unlock;
- _PROP_REFCNT_LOCK();
- ocnt = po->po_refcnt--;
- _PROP_REFCNT_UNLOCK();
-
+ /* Dance a bit to make sure we always get the non-racy ocnt */
+ ocnt = atomic_dec_32_nv(&po->po_refcnt);
+ ocnt++;
_PROP_ASSERT(ocnt != 0);
+
if (ocnt != 1) {
if (unlock != NULL)
unlock();
@@ -1056,9 +1036,7 @@ prop_object_release_emergency(prop_object_t obj)
unlock();
parent = po;
- _PROP_REFCNT_LOCK();
- ++po->po_refcnt;
- _PROP_REFCNT_UNLOCK();
+ atomic_inc_32(&po->po_refcnt);
}
_PROP_ASSERT(parent);
/* One object was just freed. */
@@ -1095,11 +1073,10 @@ prop_object_release(prop_object_t obj)
/* Save pointer to object unlock function */
unlock = po->po_type->pot_unlock;
- _PROP_REFCNT_LOCK();
- ocnt = po->po_refcnt--;
- _PROP_REFCNT_UNLOCK();
-
+ ocnt = atomic_dec_32_nv(&po->po_refcnt);
+ ocnt++;
_PROP_ASSERT(ocnt != 0);
+
if (ocnt != 1) {
ret = 0;
if (unlock != NULL)
@@ -1115,9 +1092,7 @@ prop_object_release(prop_object_t obj)
if (ret == _PROP_OBJECT_FREE_DONE)
break;
- _PROP_REFCNT_LOCK();
- ++po->po_refcnt;
- _PROP_REFCNT_UNLOCK();
+ atomic_inc_32(&po->po_refcnt);
} while (ret == _PROP_OBJECT_FREE_RECURSE);
if (ret == _PROP_OBJECT_FREE_FAILED)
prop_object_release_emergency(obj);
diff --git a/common/lib/libprop/prop_object_impl.h b/common/lib/libprop/prop_object_impl.h
index d58ec4a3a29..ac14023e046 100644
--- a/common/lib/libprop/prop_object_impl.h
+++ b/common/lib/libprop/prop_object_impl.h
@@ -1,4 +1,4 @@
-/* $NetBSD: prop_object_impl.h,v 1.28 2008/11/30 00:17:07 haad Exp $ */
+/* $NetBSD: prop_object_impl.h,v 1.29 2009/01/03 18:31:34 pooka Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -231,6 +231,15 @@ struct _prop_object_iterator {
uint32_t pi_version;
};
+#define _PROP_NOTHREAD_ONCE_DECL(x) static bool x = false;
+#define _PROP_NOTHREAD_ONCE_RUN(x,f) \
+ do { \
+ if ((x) == false) { \
+ f(); \
+ x = true; \
+ } \
+ } while (/*CONSTCOND*/0)
+
#if defined(_KERNEL)
/*
@@ -241,8 +250,8 @@ struct _prop_object_iterator {
#include <sys/malloc.h>
#include <sys/pool.h>
#include <sys/systm.h>
-#include <sys/simplelock.h>
#include <sys/rwlock.h>
+#include <sys/once.h>
#define _PROP_ASSERT(x) KASSERT(x)
@@ -260,10 +269,10 @@ struct _prop_object_iterator {
#define _PROP_MALLOC_DEFINE(t, s, l) \
MALLOC_DEFINE(t, s, l);
-#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_MUTEX_DECL_STATIC(x) static kmutex_t x;
+#define _PROP_MUTEX_INIT(x) mutex_init(&(x),MUTEX_DEFAULT,IPL_NONE)
+#define _PROP_MUTEX_LOCK(x) mutex_enter(&(x))
+#define _PROP_MUTEX_UNLOCK(x) mutex_exit(&(x))
#define _PROP_RWLOCK_DECL(x) krwlock_t x ;
#define _PROP_RWLOCK_INIT(x) rw_init(&(x))
@@ -272,6 +281,9 @@ struct _prop_object_iterator {
#define _PROP_RWLOCK_UNLOCK(x) rw_exit(&(x))
#define _PROP_RWLOCK_DESTROY(x) rw_destroy(&(x))
+#define _PROP_ONCE_DECL(x) static ONCE_DECL(x);
+#define _PROP_ONCE_RUN(x,f) RUN_ONCE(&(x), f)
+
#elif defined(_STANDALONE)
/*
@@ -298,6 +310,7 @@ void * _prop_standalone_realloc(void *, size_t);
#define _PROP_MALLOC_DEFINE(t, s, l) /* nothing */
#define _PROP_MUTEX_DECL_STATIC(x) /* nothing */
+#define _PROP_MUTEX_INIT(x) /* nothing */
#define _PROP_MUTEX_LOCK(x) /* nothing */
#define _PROP_MUTEX_UNLOCK(x) /* nothing */
@@ -308,6 +321,9 @@ void * _prop_standalone_realloc(void *, size_t);
#define _PROP_RWLOCK_UNLOCK(x) /* nothing */
#define _PROP_RWLOCK_DESTROY(x) /* nothing */
+#define _PROP_ONCE_DECL(x) _PROP_NOTHREAD_ONCE_DECL(x)
+#define _PROP_ONCE_RUN(x,f) _PROP_NOTHREAD_ONCE_RUN(x,f)
+
#else
/*
@@ -340,7 +356,8 @@ void * _prop_standalone_realloc(void *, size_t);
* 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_DECL_STATIC(x) static mutex_t x;
+#define _PROP_MUTEX_INIT(x) mutex_init(&(x), NULL)
#define _PROP_MUTEX_LOCK(x) mutex_lock(&(x))
#define _PROP_MUTEX_UNLOCK(x) mutex_unlock(&(x))
@@ -350,11 +367,17 @@ void * _prop_standalone_realloc(void *, size_t);
#define _PROP_RWLOCK_WRLOCK(x) rwlock_wrlock(&(x))
#define _PROP_RWLOCK_UNLOCK(x) rwlock_unlock(&(x))
#define _PROP_RWLOCK_DESTROY(x) rwlock_destroy(&(x))
+
+#define _PROP_ONCE_DECL(x) \
+ static pthread_once_t x = PTHREAD_ONCE_INIT;
+#define _PROP_ONCE_RUN(x,f) thr_once(&(x), (void(*)(void))f);
+
#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_INIT(x) /* nothing */
#define _PROP_MUTEX_LOCK(x) /* nothing */
#define _PROP_MUTEX_UNLOCK(x) /* nothing */
@@ -364,13 +387,16 @@ void * _prop_standalone_realloc(void *, size_t);
#define _PROP_RWLOCK_WRLOCK(x) /* nothing */
#define _PROP_RWLOCK_UNLOCK(x) /* nothing */
#define _PROP_RWLOCK_DESTROY(x) /* nothing */
+
+#define _PROP_ONCE_DECL(x) _PROP_NOTHREAD_ONCE_DECL(x)
+#define _PROP_ONCE_RUN(x,f) _PROP_NOTHREAD_ONCE_RUN(x,f)
#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_DECL_STATIC(x) static pthread_mutex_t x;
+#define _PROP_MUTEX_INIT(x) pthread_mutex_init(&(x), NULL)
#define _PROP_MUTEX_LOCK(x) pthread_mutex_lock(&(x))
#define _PROP_MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
@@ -380,6 +406,10 @@ void * _prop_standalone_realloc(void *, size_t);
#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))
+
+#define _PROP_ONCE_DECL(x) \
+ static pthread_once_t x = PTHREAD_ONCE_INIT;
+#define _PROP_ONCE_RUN(x,f) pthread_once(&(x),(void(*)(void))f)
#endif
#endif /* _KERNEL */