diff options
author | Florin Coras <fcoras@cisco.com> | 2021-11-27 14:44:59 -0800 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2021-11-29 17:50:40 +0000 |
commit | 02cc719d98b646f3027615430ad74cca53a1fa2d (patch) | |
tree | b76c8b2ea8114b98498307bb52978ab9aeda9737 /src | |
parent | 1a4aaf1c31682650f21a13d0ca2805f916bd010d (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')
-rw-r--r-- | src/vnet/session/segment_manager.c | 27 |
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 |