X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fsvm%2Fsvm_fifo.c;h=975a82026f7bb008051c4b51a389867ee7370c2f;hb=ff63798ae42309e9d53ace34d57a880a872a4ab0;hp=56f53a3d339542103d9cb722ad7d65d31d8cadb7;hpb=eaacce4753c33342a6512039fe4153b15b476fb3;p=vpp.git diff --git a/src/svm/svm_fifo.c b/src/svm/svm_fifo.c index 56f53a3d339..975a82026f7 100644 --- a/src/svm/svm_fifo.c +++ b/src/svm/svm_fifo.c @@ -400,7 +400,7 @@ svm_fifo_init (svm_fifo_t * f, u32 size) f->ooos_list_head = OOO_SEGMENT_INVALID_INDEX; f->segment_index = SVM_FIFO_INVALID_INDEX; f->refcnt = 1; - f->flags = 0; + f->head = f->tail = f->flags = 0; f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = f->start_chunk; } @@ -590,6 +590,95 @@ svm_fifo_add_chunk (svm_fifo_t * f, svm_fifo_chunk_t * c) f->flags |= SVM_FIFO_F_MULTI_CHUNK; } + /* If fifo is not wrapped, update the size now */ + if (!svm_fifo_is_wrapped (f)) + { + /* Initialize chunks and add to lookup rbtree */ + cur = c; + if (f->new_chunks) + { + prev = f->new_chunks; + while (prev->next) + prev = prev->next; + prev->next = c; + } + else + prev = f->end_chunk; + + while (cur) + { + cur->start_byte = prev->start_byte + prev->length; + rb_tree_add2 (&f->chunk_lookup, cur->start_byte, + pointer_to_uword (cur)); + prev = cur; + cur = cur->next; + } + + ASSERT (!f->new_chunks); + svm_fifo_grow (f, c); + return; + } + + /* Wrapped */ + if (f->flags & SVM_FIFO_F_SINGLE_THREAD_OWNED) + { + ASSERT (f->master_thread_index == os_get_thread_index ()); + + if (!f->new_chunks && f->head_chunk != f->tail_chunk) + { + u32 head = 0, tail = 0; + f_load_head_tail_cons (f, &head, &tail); + + svm_fifo_chunk_t *tmp = f->tail_chunk->next; + + prev = f->tail_chunk; + u32 add_bytes = 0; + cur = prev->next; + while (cur != f->start_chunk) + { + /* remove any existing rb_tree entry */ + rb_tree_del (&f->chunk_lookup, cur->start_byte); + cur = cur->next; + } + + /* insert new chunk after the tail_chunk */ + f->tail_chunk->next = c; + while (c) + { + add_bytes += c->length; + c->start_byte = prev->start_byte + prev->length; + rb_tree_add2 (&f->chunk_lookup, c->start_byte, + pointer_to_uword (c)); + + prev = c; + c = c->next; + } + prev->next = tmp; + + /* shift existing chunks along */ + cur = tmp; + while (cur != f->start_chunk) + { + cur->start_byte = prev->start_byte + prev->length; + rb_tree_add2 (&f->chunk_lookup, cur->start_byte, + pointer_to_uword (cur)); + prev = cur; + cur = cur->next; + } + + f->size += add_bytes; + f->nitems = f->size - 1; + f->new_chunks = 0; + head += add_bytes; + + clib_atomic_store_rel_n (&f->head, head); + ASSERT (svm_fifo_is_sane (f)); + + return; + } + } + + /* Wrapped, and optimization of single-thread-owned fifo cannot be applied */ /* Initialize chunks and add to lookup rbtree */ cur = c; if (f->new_chunks) @@ -611,14 +700,6 @@ svm_fifo_add_chunk (svm_fifo_t * f, svm_fifo_chunk_t * c) cur = cur->next; } - /* If fifo is not wrapped, update the size now */ - if (!svm_fifo_is_wrapped (f)) - { - ASSERT (!f->new_chunks); - svm_fifo_grow (f, c); - return; - } - /* Postpone size update */ if (!f->new_chunks) { @@ -967,6 +1048,9 @@ svm_fifo_dequeue_drop (svm_fifo_t * f, u32 len) if (!svm_fifo_chunk_includes_pos (f->head_chunk, head)) f->head_chunk = svm_fifo_find_chunk (f, head); + if (PREDICT_FALSE (f->flags & SVM_FIFO_F_GROW)) + svm_fifo_try_grow (f, head); + /* store-rel: consumer owned index (paired with load-acq in producer) */ clib_atomic_store_rel_n (&f->head, head); @@ -982,6 +1066,9 @@ svm_fifo_dequeue_drop_all (svm_fifo_t * f) if (!svm_fifo_chunk_includes_pos (f->head_chunk, tail)) f->head_chunk = svm_fifo_find_chunk (f, tail); + if (PREDICT_FALSE (f->flags & SVM_FIFO_F_GROW)) + svm_fifo_try_grow (f, tail); + /* store-rel: consumer owned index (paired with load-acq in producer) */ clib_atomic_store_rel_n (&f->head, tail); } @@ -1146,6 +1233,25 @@ svm_fifo_is_sane (svm_fifo_t * f) return 1; } +u8 +svm_fifo_set_single_thread_owned (svm_fifo_t * f) +{ + if (f->flags & SVM_FIFO_F_SINGLE_THREAD_OWNED) + { + if (f->master_thread_index == os_get_thread_index ()) + { + /* just a duplicate call */ + return 0; + } + + /* already owned by another thread */ + return 1; + } + + f->flags |= SVM_FIFO_F_SINGLE_THREAD_OWNED; + return 0; +} + u8 * format_ooo_segment (u8 * s, va_list * args) {