aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/session/segment_manager.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2021-11-27 14:44:59 -0800
committerDave Barach <openvpp@barachs.net>2021-11-29 17:50:40 +0000
commit02cc719d98b646f3027615430ad74cca53a1fa2d (patch)
treeb76c8b2ea8114b98498307bb52978ab9aeda9737 /src/vnet/session/segment_manager.c
parent1a4aaf1c31682650f21a13d0ca2805f916bd010d (diff)
session: remove segment if empty after writer lock
Make sure segment is empty after writer lock acquired. Other workers might add fifos in between empty test and writer lock acquire. Type: fix Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: I3400fdd14be98d9d8fb4e415d3a849be1d255241
Diffstat (limited to 'src/vnet/session/segment_manager.c')
-rw-r--r--src/vnet/session/segment_manager.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index 2d8e657ef98..bfb44a26053 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -244,7 +244,8 @@ segment_manager_get_segment_if_valid (segment_manager_t * sm,
* Removes segment after acquiring writer lock
*/
static inline void
-sm_lock_and_del_segment_inline (segment_manager_t * sm, u32 fs_index)
+sm_lock_and_del_segment_inline (segment_manager_t *sm, u32 fs_index,
+ u8 check_if_empty)
{
fifo_segment_t *fs;
u8 is_prealloc;
@@ -255,6 +256,9 @@ sm_lock_and_del_segment_inline (segment_manager_t * sm, u32 fs_index)
if (!fs)
goto done;
+ if (check_if_empty && fifo_segment_has_fifos (fs))
+ goto done;
+
is_prealloc = fifo_segment_flags (fs) & FIFO_SEGMENT_F_IS_PREALLOCATED;
if (is_prealloc && !segment_manager_app_detached (sm))
goto done;
@@ -268,7 +272,7 @@ done:
void
segment_manager_lock_and_del_segment (segment_manager_t * sm, u32 fs_index)
{
- sm_lock_and_del_segment_inline (sm, fs_index);
+ sm_lock_and_del_segment_inline (sm, fs_index, 0 /* check_if_empty */);
}
/**
@@ -836,6 +840,7 @@ segment_manager_dealloc_fifos (svm_fifo_t * rx_fifo, svm_fifo_t * tx_fifo)
segment_manager_t *sm;
fifo_segment_t *fs;
u32 segment_index;
+ u8 try_delete = 0;
if (!rx_fifo || !tx_fifo)
return;
@@ -851,26 +856,30 @@ segment_manager_dealloc_fifos (svm_fifo_t * rx_fifo, svm_fifo_t * tx_fifo)
fifo_segment_free_fifo (fs, tx_fifo);
/*
- * Try to remove svm segment if it has no fifos. This can be done only if
+ * Try to remove fifo segment if it has no fifos. This can be done only if
* the segment is not the first in the segment manager or if it is first
* and it is not protected. Moreover, if the segment is first and the app
* has detached from the segment manager, remove the segment manager.
*/
if (!fifo_segment_has_fifos (fs))
{
- segment_manager_segment_reader_unlock (sm);
+ /* If first, remove only if not protected */
+ try_delete = segment_index != 0 || !sm->first_is_protected;
+ }
- /* Remove segment if it holds no fifos or first but not protected */
- if (segment_index != 0 || !sm->first_is_protected)
- sm_lock_and_del_segment_inline (sm, segment_index);
+ segment_manager_segment_reader_unlock (sm);
+
+ if (PREDICT_FALSE (try_delete))
+ {
+ /* Only remove if empty after writer lock acquired */
+ sm_lock_and_del_segment_inline (sm, segment_index,
+ 1 /* check_if_empty */);
/* Remove segment manager if no sessions and detached from app */
if (segment_manager_app_detached (sm)
&& !segment_manager_has_fifos (sm))
segment_manager_free_safe (sm);
}
- else
- segment_manager_segment_reader_unlock (sm);
}
void