diff options
| author | pooka <pooka@NetBSD.org> | 2009-01-03 18:31:33 +0000 |
|---|---|---|
| committer | pooka <pooka@NetBSD.org> | 2009-01-03 18:31:33 +0000 |
| commit | b6e6025d0df49896e81e796411de5be0d1cbb00a (patch) | |
| tree | 07cb9997e882a1df8e425525e7c0edf5df0cfd70 /common/lib/libprop | |
| parent | 5eea853f3e07fba1057c271d08fc2cce77834368 (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.c | 39 | ||||
| -rw-r--r-- | common/lib/libprop/prop_dictionary.c | 37 | ||||
| -rw-r--r-- | common/lib/libprop/prop_number.c | 38 | ||||
| -rw-r--r-- | common/lib/libprop/prop_object.c | 53 | ||||
| -rw-r--r-- | common/lib/libprop/prop_object_impl.h | 48 |
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 */ |
