aboutsummaryrefslogtreecommitdiffstats
path: root/src/kern_wg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kern_wg.c')
-rw-r--r--src/kern_wg.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/kern_wg.c b/src/kern_wg.c
index 4cad94a..63eb6a3 100644
--- a/src/kern_wg.c
+++ b/src/kern_wg.c
@@ -168,15 +168,21 @@ void
fm_init(struct fixed_map *fm)
{
bzero(fm, sizeof(*fm));
+ rw_init(&fm->lock, "fixedmap");
fm_resize(fm, 128);
}
void
fm_resize(struct fixed_map *fm, size_t size)
{
- size_t i;
- size_t osize = fm->size;
- struct map_item *omap = fm->map;
+ size_t i;
+ size_t osize;
+ struct map_item *omap;
+
+ /* No lock as fm_resize is only called in fm_init (no lock) or
+ * fm_insert (already locked) */
+ osize = fm->size;
+ omap = fm->map;
for (fm->size = 1; fm->size < size; fm->size <<= 1);
KASSERT(fm->size >= osize);
@@ -193,6 +199,7 @@ void
fm_destroy(struct fixed_map *fm)
{
struct map_item *item;
+ /* No lock, as this is the last reference */
FM_FOREACH_FILLED(item, fm)
refcnt_finalize(&item->cnt, "fm_wait");
free(fm->map, M_DEVBUF, 0);
@@ -203,6 +210,7 @@ fm_insert(struct fixed_map *fm, void *v)
{
struct map_item *item = NULL, *iter;
+ rw_enter_write(&fm->lock);
retry:
FM_FOREACH_EMPTY(iter, fm) {
item = iter;
@@ -220,37 +228,56 @@ retry:
item->value = v;
refcnt_init(&item->cnt);
+ rw_exit_write(&fm->lock);
+
return item->key;
}
void
fm_put(struct fixed_map *fm, uint32_t k)
{
- struct map_item *item = fm->map + (k & (fm->size - 1));
+ struct map_item *item;
+
+ rw_enter_read(&fm->lock);
+ item = fm->map + (k & (fm->size - 1));
if (item->key != k)
panic("unexpected key, should exist");
refcnt_rele_wake(&item->cnt);
+ rw_exit_read(&fm->lock);
}
void *
fm_ref(struct fixed_map *fm, uint32_t k)
{
- struct map_item *item = fm->map + (k & (fm->size - 1));
- if (item->key != k)
- return NULL;
- refcnt_take(&item->cnt);
- return item->value;
+ void *v = NULL;
+ struct map_item *item;
+
+ rw_enter_read(&fm->lock);
+ item = fm->map + (k & (fm->size - 1));
+ if (item->key == k) {
+ v = item->value;
+ refcnt_take(&item->cnt);
+ }
+ rw_exit_read(&fm->lock);
+ return v;
}
void
fm_remove(struct fixed_map *fm, uint32_t k)
{
- struct map_item *item = fm->map + (k & (fm->size - 1));
+ struct map_item *item;
+
+ rw_enter_read(&fm->lock);
+ item = fm->map + (k & (fm->size - 1));
+ refcnt_finalize(&item->cnt, "fm_wait");
+ rw_exit_read(&fm->lock);
+
+ rw_enter_write(&fm->lock);
if (item->key == k) {
- refcnt_finalize(&item->cnt, "fm_wait");
item->state = FM_ITEM_EMPTY;
item->value = NULL;
}
+ rw_exit_write(&fm->lock);
}
/*