summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2012-11-15 21:42:02 +0100
committerThomas Graf <tgraf@suug.ch>2012-11-15 21:42:02 +0100
commitf5af5c5ecd7245bef2f16fcb1e1270abbf435de0 (patch)
tree3394a1fb8a3396dde42e8ec5cbdd69748481ed7c
parent20efa14e5c188738c15a013e092af51b780fde61 (diff)
downloadlibnl-f5af5c5ecd7245bef2f16fcb1e1270abbf435de0.tar.gz
cache: rwlock accesses to cache operations
Puts an rwlock around 'cache_ops'. Signed-off-by: Thomas Graf <tgraf@suug.ch>
-rw-r--r--lib/cache_mngt.c54
1 files changed, 46 insertions, 8 deletions
diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c
index 540c5c1..65c4707 100644
--- a/lib/cache_mngt.c
+++ b/lib/cache_mngt.c
@@ -31,12 +31,24 @@
#include <netlink/utils.h>
static struct nl_cache_ops *cache_ops;
+static NL_RW_LOCK(cache_ops_lock);
/**
* @name Cache Operations Sets
* @{
*/
+struct nl_cache_ops *__nl_cache_ops_lookup(const char *name)
+{
+ struct nl_cache_ops *ops;
+
+ for (ops = cache_ops; ops; ops = ops->co_next)
+ if (!strcmp(ops->co_name, name))
+ return ops;
+
+ return NULL;
+}
+
/**
* Lookup the set cache operations of a certain cache type
* @arg name name of the cache type
@@ -48,11 +60,11 @@ struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
{
struct nl_cache_ops *ops;
- for (ops = cache_ops; ops; ops = ops->co_next)
- if (!strcmp(ops->co_name, name))
- return ops;
+ nl_read_lock(&cache_ops_lock);
+ ops = __nl_cache_ops_lookup(name);
+ nl_read_unlock(&cache_ops_lock);
- return NULL;
+ return ops;
}
/**
@@ -71,14 +83,19 @@ struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
int i;
struct nl_cache_ops *ops;
+ nl_read_lock(&cache_ops_lock);
for (ops = cache_ops; ops; ops = ops->co_next) {
if (ops->co_protocol != protocol)
continue;
- for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
- if (ops->co_msgtypes[i].mt_id == msgtype)
+ for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) {
+ if (ops->co_msgtypes[i].mt_id == msgtype) {
+ nl_read_unlock(&cache_ops_lock);
return ops;
+ }
+ }
}
+ nl_read_unlock(&cache_ops_lock);
return NULL;
}
@@ -104,6 +121,7 @@ struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype)
return NULL;
}
+/* Must hold cache_ops_lock */
static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops)
{
struct nl_cache_ops *ops;
@@ -125,8 +143,10 @@ void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg)
{
struct nl_cache_ops *ops;
+ nl_read_lock(&cache_ops_lock);
for (ops = cache_ops; ops; ops = ops->co_next)
cb(ops, arg);
+ nl_read_unlock(&cache_ops_lock);
}
/**
@@ -156,11 +176,15 @@ int nl_cache_mngt_register(struct nl_cache_ops *ops)
if (!ops->co_name || !ops->co_obj_ops)
return -NLE_INVAL;
- if (nl_cache_ops_lookup(ops->co_name))
+ nl_write_lock(&cache_ops_lock);
+ if (__nl_cache_ops_lookup(ops->co_name)) {
+ nl_write_unlock(&cache_ops_lock);
return -NLE_EXIST;
+ }
ops->co_next = cache_ops;
cache_ops = ops;
+ nl_write_unlock(&cache_ops_lock);
NL_DBG(1, "Registered cache operations %s\n", ops->co_name);
@@ -182,16 +206,22 @@ int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
{
struct nl_cache_ops *t, **tp;
+ nl_write_lock(&cache_ops_lock);
+
for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next)
if (t == ops)
break;
- if (!t)
+ if (!t) {
+ nl_write_unlock(&cache_ops_lock);
return -NLE_NOCACHE;
+ }
NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name);
*tp = t->co_next;
+ nl_write_unlock(&cache_ops_lock);
+
return 0;
}
@@ -214,6 +244,8 @@ void nl_cache_mngt_provide(struct nl_cache *cache)
{
struct nl_cache_ops *ops;
+ nl_write_lock(&cache_ops_lock);
+
ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
if (!ops)
BUG();
@@ -221,6 +253,8 @@ void nl_cache_mngt_provide(struct nl_cache *cache)
nl_cache_get(cache);
ops->co_major_cache = cache;
}
+
+ nl_write_unlock(&cache_ops_lock);
}
/**
@@ -235,6 +269,8 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache)
{
struct nl_cache_ops *ops;
+ nl_write_lock(&cache_ops_lock);
+
ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
if (!ops)
BUG();
@@ -242,6 +278,8 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache)
nl_cache_free(ops->co_major_cache);
ops->co_major_cache = NULL;
}
+
+ nl_write_unlock(&cache_ops_lock);
}
struct nl_cache *__nl_cache_mngt_require(const char *name)