rte_ring是一個無鎖隊列,無鎖隊列的出隊入隊操作是rte_ring實現的關鍵。因此,本文主要講解dpdk是怎樣使用無鎖機制實現rte_ring的多生產者入隊操作。
rte_atomic32_cmpset()稱為CAS(compare and set)操作,是無鎖隊列實現的關鍵,實現的偽代碼如下:
cmpset(cur, old, next) { if (cur == old) { cur = next; } }
rte_atomic32_cmpset()實現基於gcc內置CAS操作:
__sync_bool_compare_and_swap()
rte_compiler_barrier()
該操作主要保證此語句后的代碼執行順序不被編譯器優化。
多生產者入隊(mp-enqueue)
/* * 該函數保證多個生產者按順序入隊,而第一步則是給多個生產者排序的過程, * 最先移動r->prod.head位置的生產者排序最靠前,排序靠前的生產者也可以 * 優先執行第二步和第三步。 */ mp_do_enqueue(r, obj, n) { /* 1. 搶占移動prod.head */ do { prod_head = r->prod.head; cons_tail = r->cons.tail; /* check that we have enough room in ring */ CHECK_REMAIN_ROOM() prod_next = prod_head + n; success = rte_atomic32_cmpset(&r->prod.head, prod_head, prod_next); } while (success == 0); /* 2. 元素插入合適位置 */ ENQUEUE_PTRS(); rte_compiler_barrier(); /* 3. 順序移動prod.tail */ while (unlikely(r->prod.tail != prod_head)) rte_pause(); r->prod.tail = prod_next; }