dpdk_ring剝離(單線程版)

DPDK_RING 剝離(sc)

dpdk中的ring結構的原理在官方的doc中有。詳細的介紹了單線程和多線程下的ring的結構的實現。其中線程安全的ring的出入隊中沒有用到鎖,這個結構是比較巧妙的。
此外,和一般的ring設計相比,dpdk的ring中減少了比較的次數和減法的次數。考慮了很多性能方面的東西。
目前就剝離了單線程版的。
代碼如下:
- daq_ring.h

#ifndef DAQ_RING_H
#define DAQ_RING_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <pthread.h>




typedef struct _daq_ring{
  //  pthread_mutex_t mutex;
    int size;
    int mask;
    int cons_head;
    int cons_tail;
    int prod_head;
    int prod_tail;
    void * ring[0];
};
typedef struct _daq_ring daq_ring;
//create a ring which can contain size's objects.
daq_ring * daq_ring_create(int num);
//fre a ring.
int daq_ring_free(daq_ring * r);
//see whether a ring is empty.
int daq_ring_isEmpty(daq_ring * r);
//see whether a ring is full.
int daq_ring_isFull(daq_ring * r);
//see the number of objects in ring now.
int daq_ring_count(daq_ring * r);
//see the size of a ring.
int daq_ring_getSize(daq_ring *r);
//see the number of objects can be inputed into the ring now.
int daq_ring_freeCount(daq_ring * r);
//enqueue objects into a ring.
int daq_ring_enqueue(daq_ring * r, void * const *obj_table, int num,int mc);
//dequeue objects from a ring.
int daq_ring_dequeue(daq_ring * r, void **obj_table, int num,int mc);

#endif
//end of daq_ring.h

-daq_ring.c

#include "daq_ring.h"

/*typedef struct _daq_ring{
    pthread_mutex_t mutex;
    unsigned int size;
    void * head;
    void * tail;
    void * memhead;
}daq_ring;*/

daq_ring * daq_ring_create(int num){
    daq_ring * r = NULL;
    if(num <=0)return NULL;
    r = (daq_ring *)malloc(sizeof(daq_ring) + num*sizeof(void*));
    if(r == NULL){
        return NULL;
    }
    r->size = num;
    r->mask = num-1;
    r->prod_head = r->prod_tail = r->cons_head = r->cons_tail = 0;
   // pthread_mutex_init(&r->mutex,NULL);
    return r;
}
//fre a ring.
int daq_ring_free(daq_ring * r){
    free(r);
}
//see whether a ring is empty.
int daq_ring_isEmpty(daq_ring * r){
    return r->cons_tail == r->prod_tail;
}
//see whether a ring is full.
int daq_ring_isFull(daq_ring * r){
    return (((r->cons_tail - r->prod_tail -1)&r->mask)==0);
}
//see the number of objects in ring now.
int daq_ring_count(daq_ring * r){
    return ((r->prod_tail - r->cons_tail)&r->mask);
}
//see the size of a ring.
int daq_ring_getSize(daq_ring *r){
    return r->size;
}
//see the number of objects can be inputed into the ring now.
int daq_ring_freeCount(daq_ring * r){
    return ((r->cons_tail - r->prod_tail - 1) & r->mask);
}
//enqueue objects into a ring.
int daq_ring_enqueue(daq_ring * r, void * const *obj_table, int num,int mc){
    int prod_head = r->prod_head;
    int cons_tail = r->cons_tail;
    int prod_next = prod_head +1;
    int mask = r->mask;
    int i ;
    int free = mask + cons_tail -prod_head;
    if(num >free){
        if(free == 0)return 0;
        num = free;
    }
    prod_next = prod_head +num;
    r->prod_head = prod_next;
    {
        const int size = r->size;
        int idx = prod_head & mask;
        if(idx + num < size){
            for (i = 0; i < (num & ((~(unsigned)0x3))); i+=4, idx+=4) { 
                r->ring[idx] = obj_table[i]; 
                r->ring[idx+1] = obj_table[i+1]; 
                r->ring[idx+2] = obj_table[i+2]; 
                r->ring[idx+3] = obj_table[i+3]; 
            }
            switch (num & 0x3) { 
            case 3: r->ring[idx++] = obj_table[i++]; 
            case 2: r->ring[idx++] = obj_table[i++]; 
            case 1: r->ring[idx++] = obj_table[i++]; 
            } 
        }else{
            for (i =0;idx<size;++i,++idx)
                r->ring[idx] = obj_table[i];
            for(idx = 0;i<num;++i,++idx)
                r->ring[idx] = obj_table[i];
        }
    }
    r->prod_tail = prod_next;
    return num;
}
//dequeue objects from a ring.
int daq_ring_dequeue(daq_ring * r, void **obj_table, int num,int mc){
    int cons_head,prod_tail;
    int cons_next,entries;
    int i;
    int mask = r->mask;
    cons_head = r->cons_head;
    prod_tail = r->prod_tail;
    entries = prod_tail - cons_head;
    if(num > entries){
        if(entries == 0)return 0;
        num = entries;
    }
    cons_next = cons_head + num;
    r -> cons_head = cons_next;
    {
        int idx = cons_head & mask;
        int size = r-> size; 
    if (idx + num < size) { 
        for (i = 0; i < (num & (~(unsigned)0x3)); i+=4, idx+=4) {
            obj_table[i] = r->ring[idx]; 
            obj_table[i+1] = r->ring[idx+1]; 
            obj_table[i+2] = r->ring[idx+2]; 
            obj_table[i+3] = r->ring[idx+3]; 
        } 
        switch (num & 0x3) { 
            case 3: obj_table[i++] = r->ring[idx++]; 
            case 2: obj_table[i++] = r->ring[idx++]; 
            case 1: obj_table[i++] = r->ring[idx++]; 
        } 
    } else { 
        for (i = 0; idx < size; i++, idx++) 
            obj_table[i] = r->ring[idx]; 
        for (idx = 0; i < num; i++, idx++) 
            obj_table[i] = r->ring[idx]; 
    } 
    }
    r->cons_tail = cons_next;
    return num;
}

void daq_ring_stat(daq_ring * r){
    printf("***********************************************\n");
    printf("Daq_ring's size is %d\n",daq_ring_getSize(r));
    printf("Daq_ring's objects now is %d.\n",daq_ring_count(r));
    printf("Daq_ring's free space is %d\n",daq_ring_freeCount(r));
    printf("Daq_ring is %s now.\n",daq_ring_isEmpty(r)?"empty":"not empty");
    printf("Daq_ring is %s now.\n",daq_ring_isFull(r)?"full":"not full");
    printf("***********************************************\n");
}

void print_ptr(daq_ring *r){
    printf("r->cons:%p %p\n", r->cons_head, r->cons_tail);
    printf("r->prod:%p %p\n",r->prod_head,r->prod_tail);

    printf("r->ring[0]:%p\n",&r->ring[0]);

}

int test1(){
    char * str[] = {
        "t1","t2","t3","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13"
    };
    void * ctx[12];
    int i;
    for(i =0;i<10;++i)
        printf("%s\n",str[i]);
    daq_ring * r = daq_ring_create(9);
    daq_ring_stat(r);
    print_ptr(r);
    daq_ring_enqueue(r,str,8,1);
    daq_ring_stat(r);
    print_ptr(r);
    daq_ring_dequeue(r,ctx,8,1);
    for(int i =0;i<8;++i)
        printf("%s\n",(char *)ctx[i]);
    daq_ring_stat(r);

print_ptr(r);
    daq_ring_enqueue(r,str,8,1);
    daq_ring_stat(r);
    print_ptr(r);
    daq_ring_dequeue(r,ctx,8,1);
    for(i =0;i<10;++i)
        printf("%s\n",(char *)ctx[i]);
    return 0;
}

int test2(){
    int i;
    char * str[] = {
        "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10", "t11", "t12", "t13", "t14", "t15", "t16", "t17"
    };
    void * ctx[18];
    daq_ring * r = daq_ring_create(16);
    daq_ring_enqueue(r,str,14,1);
    daq_ring_stat(r);
    print_ptr(r);
    daq_ring_dequeue(r,ctx,4,1);
    for(i =0;i<4;++i)
        printf("%s\n",(char *)ctx[i]);
    daq_ring_stat(r);
    print_ptr(r);
    daq_ring_enqueue(r,&str[5],5,1);
    daq_ring_stat(r);
    print_ptr(r);
    daq_ring_dequeue(r,ctx,15,1);
    for(i =0;i<15;++i)
        printf("%s\n",(char *)ctx[i]);
    daq_ring_stat(r);
    print_ptr(r);
}

int main(){
    test2();
    return 0;
}
發佈了25 篇原創文章 · 獲贊 9 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章