summaryrefslogtreecommitdiffstats
path: root/database/engine/rrdenglocking.c
diff options
context:
space:
mode:
Diffstat (limited to 'database/engine/rrdenglocking.c')
-rw-r--r--database/engine/rrdenglocking.c36
1 files changed, 17 insertions, 19 deletions
diff --git a/database/engine/rrdenglocking.c b/database/engine/rrdenglocking.c
index 0c1d26f25a..754d802a23 100644
--- a/database/engine/rrdenglocking.c
+++ b/database/engine/rrdenglocking.c
@@ -20,7 +20,12 @@ struct page_cache_descr *rrdeng_create_pg_cache_descr(struct rrdengine_instance
void rrdeng_destroy_pg_cache_descr(struct rrdengine_instance *ctx, struct page_cache_descr *pg_cache_descr)
{
+ /* Flush any lock and condition variable users */
+ uv_mutex_lock(&pg_cache_descr->mutex);
+ uv_mutex_unlock(&pg_cache_descr->mutex);
+
uv_cond_destroy(&pg_cache_descr->cond);
+
uv_mutex_destroy(&pg_cache_descr->mutex);
freez(pg_cache_descr);
rrd_stat_atomic_add(&ctx->stats.page_cache_descriptors, -1);
@@ -95,7 +100,7 @@ void rrdeng_page_descr_mutex_lock(struct rrdengine_instance *ctx, struct rrdeng_
void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr)
{
unsigned long old_state, new_state, ret_state, old_users;
- struct page_cache_descr *pg_cache_descr, *delete_pg_cache_descr = NULL;
+ struct page_cache_descr *pg_cache_descr;
uint8_t we_locked;
uv_mutex_unlock(&descr->pg_cache_descr->mutex);
@@ -111,8 +116,7 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
ret_state = ulong_compare_and_swap(&descr->pg_cache_descr_state, old_state, 0);
if (old_state == ret_state) {
/* success */
- rrdeng_destroy_pg_cache_descr(ctx, delete_pg_cache_descr);
- return;
+ break;
}
continue; /* spin */
}
@@ -124,15 +128,12 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
pg_cache_descr = descr->pg_cache_descr;
/* caller is the only page cache descriptor user and there are no pending references on the page */
if ((old_state & PG_CACHE_DESCR_DESTROY) && (1 == old_users) &&
- !pg_cache_descr->flags && !pg_cache_descr->refcnt) {
- assert(!pg_cache_descr->waiters);
-
+ !pg_cache_descr->flags && !pg_cache_descr->refcnt && !pg_cache_descr->waiters) {
new_state = PG_CACHE_DESCR_LOCKED;
ret_state = ulong_compare_and_swap(&descr->pg_cache_descr_state, old_state, new_state);
if (old_state == ret_state) {
we_locked = 1;
- delete_pg_cache_descr = pg_cache_descr;
- descr->pg_cache_descr = NULL;
+ rrdeng_destroy_pg_cache_descr(ctx, pg_cache_descr);
/* retry */
continue;
}
@@ -149,6 +150,7 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
}
/* spin */
}
+
}
/*
@@ -159,11 +161,11 @@ void rrdeng_page_descr_mutex_unlock(struct rrdengine_instance *ctx, struct rrden
void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr)
{
unsigned long old_state, new_state, ret_state, old_users;
- struct page_cache_descr *pg_cache_descr = NULL;
- uint8_t just_locked, can_free, must_unlock;
+ struct page_cache_descr *pg_cache_descr;
+ uint8_t just_locked, we_freed, must_unlock;
just_locked = 0;
- can_free = 0;
+ we_freed = 0;
must_unlock = 0;
while (1) { /* spin */
old_state = descr->pg_cache_descr_state;
@@ -175,11 +177,9 @@ void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct
must_unlock = 1;
just_locked = 0;
/* Try deallocate if there are no pending references on the page */
- if (!pg_cache_descr->flags && !pg_cache_descr->refcnt) {
- assert(!pg_cache_descr->waiters);
-
- descr->pg_cache_descr = NULL;
- can_free = 1;
+ if (!pg_cache_descr->flags && !pg_cache_descr->refcnt && !pg_cache_descr->waiters) {
+ rrdeng_destroy_pg_cache_descr(ctx, pg_cache_descr);
+ we_freed = 1;
/* success */
continue;
}
@@ -188,7 +188,7 @@ void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct
if (unlikely(must_unlock)) {
assert(0 == old_users);
- if (can_free) {
+ if (we_freed) {
/* success */
new_state = 0;
} else {
@@ -198,8 +198,6 @@ void rrdeng_try_deallocate_pg_cache_descr(struct rrdengine_instance *ctx, struct
ret_state = ulong_compare_and_swap(&descr->pg_cache_descr_state, old_state, new_state);
if (old_state == ret_state) {
/* unlocked */
- if (can_free)
- rrdeng_destroy_pg_cache_descr(ctx, pg_cache_descr);
return;
}
continue; /* spin */