diff options
Diffstat (limited to 'src/svm/svm_fifo.h')
-rw-r--r-- | src/svm/svm_fifo.h | 130 |
1 files changed, 58 insertions, 72 deletions
diff --git a/src/svm/svm_fifo.h b/src/svm/svm_fifo.h index 560628d2d07..7ea114f8702 100644 --- a/src/svm/svm_fifo.h +++ b/src/svm/svm_fifo.h @@ -34,7 +34,7 @@ typedef enum svm_fifo_deq_ntf_ SVM_FIFO_NO_DEQ_NOTIF = 0, /**< No notification requested */ SVM_FIFO_WANT_DEQ_NOTIF = 1, /**< Notify on dequeue */ SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL = 2, /**< Notify on transition from full */ - SVM_FIFO_WANT_DEQ_NOTIF_IF_EMPTY = 4, /**< Notify on transition to empty */ + SVM_FIFO_WANT_DEQ_NOTIF_IF_EMPTY = 4, /**< Notify on transition to empty */ } svm_fifo_deq_ntf_t; typedef enum svm_fifo_flag_ @@ -431,8 +431,8 @@ void svm_fifo_dequeue_drop_all (svm_fifo_t * f); * @param max_bytes max bytes to be mapped to fifo segments * @return number of bytes in fifo segments or SVM_FIFO_EEMPTY */ -int svm_fifo_segments (svm_fifo_t * f, u32 offset, svm_fifo_seg_t * fs, - u32 n_segs, u32 max_bytes); +int svm_fifo_segments (svm_fifo_t *f, u32 offset, svm_fifo_seg_t *fs, + u32 *n_segs, u32 max_bytes); /** * Add io events subscriber to list * @@ -640,63 +640,6 @@ u32 svm_fifo_max_read_chunk (svm_fifo_t * f); u32 svm_fifo_max_write_chunk (svm_fifo_t * f); /** - * Fifo head chunk getter - * - * @param f fifo - * @return head chunk pointer - */ -static inline svm_fifo_chunk_t * -svm_fifo_head_chunk (svm_fifo_t * f) -{ - return f_head_cptr (f); -} - -/** - * Fifo head pointer getter - * - * @param f fifo - * @return head pointer - */ -static inline u8 * -svm_fifo_head (svm_fifo_t * f) -{ - svm_fifo_chunk_t *head_chunk; - if (!f->shr->head_chunk) - return 0; - /* load-relaxed: consumer owned index */ - head_chunk = f_head_cptr (f); - return (head_chunk->data + (f->shr->head - head_chunk->start_byte)); -} - -/** - * Fifo tail chunk getter - * - * @param f fifo - * @return tail chunk pointer - */ -static inline svm_fifo_chunk_t * -svm_fifo_tail_chunk (svm_fifo_t * f) -{ - return f_tail_cptr (f); -} - -/** - * Fifo tail pointer getter - * - * @param f fifo - * @return tail pointer - */ -static inline u8 * -svm_fifo_tail (svm_fifo_t * f) -{ - svm_fifo_chunk_t *tail_chunk; - - /* load-relaxed: producer owned index */ - tail_chunk = f_tail_cptr (f); - return (tail_chunk->data + (f->shr->tail - tail_chunk->start_byte)); -} - -/** * Fifo number of subscribers getter * * @param f fifo @@ -816,7 +759,7 @@ svm_fifo_unset_event (svm_fifo_t * f) static inline void svm_fifo_add_want_deq_ntf (svm_fifo_t * f, u8 ntf_type) { - f->shr->want_deq_ntf |= ntf_type; + __atomic_or_fetch (&f->shr->want_deq_ntf, ntf_type, __ATOMIC_RELEASE); } /** @@ -830,7 +773,21 @@ svm_fifo_add_want_deq_ntf (svm_fifo_t * f, u8 ntf_type) static inline void svm_fifo_del_want_deq_ntf (svm_fifo_t * f, u8 ntf_type) { - f->shr->want_deq_ntf &= ~ntf_type; + __atomic_and_fetch (&f->shr->want_deq_ntf, ~ntf_type, __ATOMIC_RELEASE); +} + +/** + * Get want notification flag + * + * Done atomically with acquire memory ordering + * + * @param f fifo + * @return value of want_deq_ntf flag + */ +static inline u32 +svm_fifo_get_want_deq_ntf (svm_fifo_t *f) +{ + return clib_atomic_load_acq_n (&f->shr->want_deq_ntf); } /** @@ -847,10 +804,27 @@ svm_fifo_del_want_deq_ntf (svm_fifo_t * f, u8 ntf_type) static inline void svm_fifo_clear_deq_ntf (svm_fifo_t * f) { - /* Set the flag if want_notif_if_full was the only ntf requested */ - f->shr->has_deq_ntf = - f->shr->want_deq_ntf == SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL; - svm_fifo_del_want_deq_ntf (f, SVM_FIFO_WANT_DEQ_NOTIF); + u32 want_deq_ntf = svm_fifo_get_want_deq_ntf (f); + /* Set the flag if want ntf if full or empty was requested */ + if (want_deq_ntf & + (SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL | SVM_FIFO_WANT_DEQ_NOTIF_IF_EMPTY)) + clib_atomic_store_rel_n (&f->shr->has_deq_ntf, 1); + if (want_deq_ntf & SVM_FIFO_WANT_DEQ_NOTIF) + svm_fifo_del_want_deq_ntf (f, SVM_FIFO_WANT_DEQ_NOTIF); +} + +/** + * Get has dequeue notification flag + * + * Done atomically with acquire memory ordering + * + * @param f fifo + * @return has_deq_ntf flag + */ +static inline u32 +svm_fifo_has_deq_ntf (svm_fifo_t *f) +{ + return clib_atomic_load_acq_n (&f->shr->has_deq_ntf); } /** @@ -881,28 +855,40 @@ svm_fifo_reset_has_deq_ntf (svm_fifo_t * f) static inline u8 svm_fifo_needs_deq_ntf (svm_fifo_t * f, u32 n_last_deq) { - u8 want_ntf = f->shr->want_deq_ntf; + u32 want_ntf = svm_fifo_get_want_deq_ntf (f); - if (PREDICT_TRUE (want_ntf == SVM_FIFO_NO_DEQ_NOTIF)) + if (want_ntf == SVM_FIFO_NO_DEQ_NOTIF) return 0; else if (want_ntf & SVM_FIFO_WANT_DEQ_NOTIF) - return 1; + return (svm_fifo_max_enqueue (f) >= f->shr->deq_thresh); if (want_ntf & SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL) { u32 max_deq = svm_fifo_max_dequeue_cons (f); u32 size = f->shr->size; - if (!f->shr->has_deq_ntf && max_deq < size && - max_deq + n_last_deq >= size) + if (max_deq < size && max_deq + n_last_deq >= size && + !svm_fifo_has_deq_ntf (f)) return 1; } if (want_ntf & SVM_FIFO_WANT_DEQ_NOTIF_IF_EMPTY) { - if (!f->shr->has_deq_ntf && svm_fifo_is_empty (f)) + if (!svm_fifo_has_deq_ntf (f) && svm_fifo_is_empty (f)) return 1; } return 0; } +/** + * Set the fifo dequeue threshold which will be used for notifications. + * + * Note: If not set, by default threshold is zero, equivalent to + * generating notification on each dequeue event. + */ +static inline void +svm_fifo_set_deq_thresh (svm_fifo_t *f, u32 thresh) +{ + f->shr->deq_thresh = thresh; +} + #endif /* __included_ssvm_fifo_h__ */ /* |