dpdk-prog-guide阅读笔记--Ring_Library

3 篇文章 0 订阅
3 篇文章 0 订阅

1. Ring Library

通过操作时将ring中的变量复制到本地的方式来完成无锁操作

1.1 Ring struct

struct rte_ring {
    char name[RTE_MEMZONE_NAMESIZE];      // name of the ring\n
    int flags;                            // Flags supplied at creation
    const struct rte_memzone *memzone;    // memzone, if any, containing the ret_ring
    
    struct prod {
        uint32_t watermark;               // maximum items before EDQUOT
        uint32_t sp_enqueue;              // true, if single producer
        uint32_t size;                    // size of ring
        uint32_t mask;                    // mask(size - 1) of ring
        volatile uint32_t head;           // producer head
        volatile uint32_t tail;           // producer tail
    }
    
    struct cons {
        uint32_t sc_dequeue;              // true, if single consumer
        uint32_t size;                    // size of the ring
        uint32_t mask;                    // mask(size - 1) of ring
        volatile uint32_t head;           // consumer head
        volatile uint32_t tail;           // consumer tail
    }
}

1.2 Single Producer Enqueue

单生产者的模式比较简单:
1. 将下标ring->prod_head、ring->cons_tail复制到本地变量m_prod_head和m_cons_tail,然后在本地创建一个m_prod_next变量,指向prod_head + n(n≥1,表示需要入队的数据个数),标记下一次消费的位置。若m_prod_next ≥ m_cons_tail,则表示队列没有足够的空间用来存放这些数据,则返回一个error。
2. 将m_prod_next赋给ring->prod_head,先完成数据存放位置的预定,然后再做入队操作,将需要enqueue的数据加入队列,m_prod_head递增。
3. 数据全部存入队列后,将ring->prod_head赋给ring->prod_tail,结束入队操作。

1.3 Single Consumer Dequeue

与单生产者的入队方式类似,单消费者的出队模式也比较简单:
1. 将下标ring->cons_head和ring_prod_tail复制到本地变量m_cons_head和m_constail,然后在本地创建一个m_cons_next变量,指向m_cons_head + n(n≥1,表示要出队的数据个数),标记下一次消费的位置。若m_cons_next ≥ m_prod_head,则表示没有足够的数据能被取走,则返回一个error。
2. 将m_cons_next赋给ring->cons_head,先完成数据提取的位置预定,然后做数据提取,将数据取走,m_cons_head递增。
3. 数据全部出队后,将ring->cons_head赋给ring->cons_tail,结束出队操作。

1.4 Multiple Producers Enqueue

假设有两位生产者a, b同时进行入队操作:
1. 两位生产者都将下标ring->prod_head和ring->cons_tail拷贝到本的a->prod_head、a->cons_tail和b->prod_head、b->cons_tail,并创建本地变量a->prod_next = a->prod_head + na、b->prod_next = b->prod_head + nb,(na,nb ≥ 1,表示需要入队的数据个数)。若*->prod_next ≥ *->cons_tail,表示没有足够的位置存放数据,则返回一个error。
2. 将a->cons_tail赋给ring->prod_head完成数据存放位置的预取,这里依赖一个原子操作Compare And Swap (CAS):  
    2.1 若a->prod_head与ring->prod_head不一致,CAS失败,则返回第一步操作。  
    2.2 否则,将ring->prod_head指向a->prod_next,CAS结束
3. 若a先完成CAS操作,则b第一次CAS操作尝试失败,第二次重新尝试时操作成功(反之亦然)。然后根据本地的a->prod_head和a->prod_next进行数据入队操作,a->prod_head递增。
4. 入队完成后,每个生产者都希望跟新ring->prod_tail,但只有a生产者发现ring->prod_tail与自身的a->prod_head相等时,才能将ring->prod_tail更新为a->prod_head,生产者a的入队操作完成。
5. 同理操作消费者b。

1.5 Modulo 32-bit Indexes

虽然Ring是一个环形队列,但在使用的时候无需关心prod_head等参数的回环问题。该库实现时设立了一个mask参数:mask = size(ring) - 1,然后根据mask自动计算prod_head等参数在ring中的具体下标,自动完成取余操作。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值