summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2022-03-14 13:04:38 +0100
committerFlorin Coras <florin.coras@gmail.com>2022-03-14 18:33:32 +0000
commitd1bd9af16ed6575e08871d1cadd429f2d5925220 (patch)
tree24698c66736780d0e2a8c6d5e8526ca1dd43b467 /src
parent85a9c101bffe99da141b496f95966258b922a440 (diff)
stats: support recursive locking
Type: improvement Change-Id: I85dd3d34bcb175dd68dda34a58cd454848a0fc2b Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src')
-rw-r--r--src/vlib/stats/init.c2
-rw-r--r--src/vlib/stats/stats.c33
-rw-r--r--src/vlib/stats/stats.h2
3 files changed, 32 insertions, 5 deletions
diff --git a/src/vlib/stats/init.c b/src/vlib/stats/init.c
index d81916a288d..d24c1580a88 100644
--- a/src/vlib/stats/init.c
+++ b/src/vlib/stats/init.c
@@ -88,6 +88,8 @@ vlib_stats_init (vlib_main_t *vm)
shared_header->base = memaddr;
sm->stat_segment_lockp = clib_mem_alloc (sizeof (clib_spinlock_t));
+ sm->locking_thread_index = ~0;
+ sm->n_locks = 0;
clib_spinlock_init (sm->stat_segment_lockp);
oldheap = clib_mem_set_heap (sm->heap);
diff --git a/src/vlib/stats/stats.c b/src/vlib/stats/stats.c
index 19edaf0866d..97f84006eaf 100644
--- a/src/vlib/stats/stats.c
+++ b/src/vlib/stats/stats.c
@@ -7,24 +7,47 @@
vlib_stats_main_t vlib_stats_main;
-/*
- * Used only by VPP writers
- */
-
void
vlib_stats_segment_lock (void)
{
+ vlib_main_t *vm = vlib_get_main ();
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
+
+ /* already locked by us */
+ if (sm->shared_header->in_progress &&
+ vm->thread_index == sm->locking_thread_index)
+ goto done;
+
+ ASSERT (sm->locking_thread_index == ~0);
+ ASSERT (sm->shared_header->in_progress == 0);
+ ASSERT (sm->n_locks == 0);
+
clib_spinlock_lock (sm->stat_segment_lockp);
+
sm->shared_header->in_progress = 1;
+ sm->locking_thread_index = vm->thread_index;
+done:
+ sm->n_locks++;
}
void
vlib_stats_segment_unlock (void)
{
+ vlib_main_t *vm = vlib_get_main ();
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
+
+ ASSERT (sm->shared_header->in_progress == 1);
+ ASSERT (sm->locking_thread_index == vm->thread_index);
+ ASSERT (sm->n_locks > 0);
+
+ sm->n_locks--;
+
+ if (sm->n_locks > 0)
+ return;
+
sm->shared_header->epoch++;
- sm->shared_header->in_progress = 0;
+ __atomic_store_n (&sm->shared_header->in_progress, 0, __ATOMIC_RELEASE);
+ sm->locking_thread_index = ~0;
clib_spinlock_unlock (sm->stat_segment_lockp);
}
diff --git a/src/vlib/stats/stats.h b/src/vlib/stats/stats.h
index 25d7c4ba484..faaa37a7ec2 100644
--- a/src/vlib/stats/stats.h
+++ b/src/vlib/stats/stats.h
@@ -82,6 +82,8 @@ typedef struct
f64 update_interval;
clib_spinlock_t *stat_segment_lockp;
+ u32 locking_thread_index;
+ u32 n_locks;
clib_socket_t *socket;
u8 *socket_name;
ssize_t memory_size;