Sword 內核隊列二

#ifndef __GTC_FIFO_H_
#define __GTC_FIFO_H_

#ifndef GTC_MAX
#define GTC_MAX(a,b) ((a) > (b) ? (a) : (b))
#endif

#ifndef GTC_MIN
#define GTC_MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

#ifdef __cplusplus
extern "C"
{
#endif

    struct gfifo {
        unsigned char *buffer;    /* the buffer holding the data */
        unsigned int size;    /* the size of the allocated buffer */
        unsigned int in;    /* data is added at offset (in % size) */
        unsigned int out;    /* data is extracted from off. (out % size) */
    };

    //隊列初始化
    int gfifo_alloc(struct gfifo *fifo, unsigned int size);

    //壓入隊列
    unsigned int gfifo_put(struct gfifo *fifo, const unsigned char *buffer, unsigned int len);

    //彈出隊列
    unsigned int gfifo_get(struct gfifo *fifo, unsigned char *buffer, unsigned int len);


#ifdef __cplusplus
}
#endif

#endif
#include "gfifo.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/********************************************************
   Func Name: gfifo_init
Date Created: 2019-4-1
 Description: 初始化
       Input: 
      Output: 
      Return: 
     Caution: 
*********************************************************/
static void gfifo_init(struct gfifo *fifo, void *buffer, unsigned int size)
{
    fifo->buffer = buffer;
    fifo->size = size;
    fifo->in = 0;
    fifo->out = 0;
}

/********************************************************
   Func Name: gfifo_roundup
Date Created: 2019-4-1
 Description: 擴展
       Input: 
      Output: 
      Return: size
     Caution: 
*********************************************************/
static unsigned int gfifo_roundup(unsigned int x)
{
    unsigned int i = 0;
    unsigned int y = 1;

    if (!x)
    {
        return 1;
    }

    for (i = x; i != 0; )
    {
        i >>= 1;
        y <<= 1;
    }

    return y;

}

/********************************************************
   Func Name: gfifo_alloc
Date Created: 2019-4-1
 Description: 內存分配
       Input: 
      Output: 
      Return: error code
     Caution: 
*********************************************************/
int gfifo_alloc(struct gfifo *fifo, unsigned int size)
{
    assert(fifo);

    unsigned char *buffer;

    /*
        size的值老是在調用者傳進來的size參數的基礎上向2的冪擴展,這是內核一向的作法。
    這樣的好處不言而喻--對kfifo->size取模運算能夠轉化爲與運算,以下:
    fifo->in % fifo->size 能夠轉化爲 fifo->in & (fifo->size – 1)
    在kfifo_alloc函數中,使用size & (size – 1)來判斷size 是否爲2冪,若是條件爲真,則表示size不是2的冪,而後調用roundup_pow_of_two將之向上擴展爲2的冪。
    */
    if (size & (size - 1)) 
    {
        size = gfifo_roundup(size);
    }

    buffer = calloc(1, size);
    if (NULL == buffer)
    {
        return -1;
    }

    gfifo_init(fifo, buffer, size);

    return 0;
}

/********************************************************
   Func Name: gfifo_put
Date Created: 2019-4-1
 Description: 壓入隊列
       Input: 
      Output: 
      Return: 壓入隊列數據長度
     Caution: 
*********************************************************/
unsigned int gfifo_put(struct gfifo *fifo, const unsigned char *buffer, unsigned int len)
{
    unsigned int left_over = 0;

    /*
    計算出實際寫入隊列數據大小
        (fifo->in - fifo->out)  已經使用空間大小
        fifo->size - (fifo->in - fifo->out)  能夠使用空間大小
        len  須要寫入數據大小
    */
    len = GTC_MIN(len, fifo->size - (fifo->in - fifo->out)); 

    /*
    計算出在隊列in後面插入數據的大小
        fifo->in & (fifo->size - 1) 等同於 fifo->in % fifo->size
        fifo->size - (fifo->in & (fifo->size - 1))  表示in後面可寫數據的長度
    */
    left_over = GTC_MIN(len, fifo->size - (fifo->in & (fifo->size - 1))); 

    //拷貝數據到in後面
    memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, left_over);

    //將剩餘的數據拷貝到out前面
    memcpy(fifo->buffer, buffer + left_over, len - left_over);
    
    //更新in
    fifo->in += len;

    return len; 
}

/********************************************************
   Func Name: gfifo_get
Date Created: 2019-4-1
 Description: 彈出隊列
       Input: 
      Output: 
      Return: 彈出隊列
     Caution: 
*********************************************************/
unsigned int gfifo_get(struct gfifo *fifo, unsigned char *buffer, unsigned int len)
{
    assert(buffer);

    unsigned int readable_length = 0;

    /*
    計算出實際可讀隊列數據大小
        (fifo->in - fifo->out)  已經使用空間大小
    */

    len = GTC_MIN(len, fifo->in - fifo->out);

    /*
    計算出在隊列out後面插入數據的大小
        fifo->in & (fifo->size - 1) 等同於 fifo->in % fifo->size
        fifo->size - (fifo->out & (fifo->size - 1))  表示out後面可讀數據的長度
    */
    readable_length = GTC_MIN(len, fifo->size - (fifo->out & (fifo->size - 1))); 

    //拷貝數據
    memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), readable_length);

    //拷貝能從頭部獲取的數據
    memcpy(buffer + readable_length, fifo->buffer, len - readable_length);

    //更新out
    fifo->out += len;

    return len; 
}
相關文章
相關標籤/搜索