模块说明
这个模块是修改自linux kernel的fifo模块,我用在一些裸板程序上,作为基础的数据结构;
数据结构
struct __fifo {
unsigned int in;
unsigned int out;
unsigned int mask;
unsigned int esize;
void *data;
};
初始化函数
参数:
struct __fifo *fifo
: 队列头
void *buffer
:队列的buffer
unsigned int size
:buffer的大小(字节)
size_t esize
每个队列数据节点的大小(字节),比如每个队列的节点是个数据结构体,那这个值时结构体的大小
int fifo_init(struct __fifo *fifo, void *buffer,unsigned int size, size_t esize);
销毁函数
void fifo_free(struct __fifo *fifo);
入队
unsigned int fifo_in(struct __fifo *fifo, const void *buf, unsigned int len);
出队
unsigned int fifo_out(struct __fifo *fifo,void *buf, unsigned int len);
模块源码
H文件
#ifndef __BASEFIFO_H__
#define __BASEFIFO_H__
#include "myself_types.h"
#include <stdint.h>
struct __fifo {
unsigned int in;
unsigned int out;
unsigned int mask;
unsigned int esize;
void *data;
};
int fifo_init(struct __fifo *fifo, void *buffer,
unsigned int size, size_t esize);
void fifo_free(struct __fifo *fifo);
unsigned int fifo_in(struct __fifo *fifo,
const void *buf, unsigned int len);
unsigned int fifo_out(struct __fifo *fifo,
void *buf, unsigned int len);
#endif// __BASEFIFO_H__
C文件
#include "basefifo.h"
#include <stdlib.h>
#include <string.h>
#define EINVAL (1)
#define max(a, b) (a > b ? a : b )
#define min(a, b) (a < b ? a : b )
/*
size 是buffer的大小,esize是fifo数据单元大小
*/
int fifo_init(struct __fifo *fifo, void *buffer,
unsigned int size, size_t esize)
{
/*得到队列深度*/
size /= esize;
/*这里缺少一个宏,需要将size向上扩展成2的幂,其实这里需要做强制判断,或者向下压缩成2的幂
*
*/
//size = roundup_pow_of_two(size);
fifo->in = 0;
fifo->out = 0;
fifo->esize = esize;
fifo->data = buffer;
if (size < 2) {
fifo->mask = 0;
return -EINVAL;
}
fifo->mask = size - 1;
return 0;
}
void fifo_free(struct __fifo *fifo)
{
//kfree(fifo->data);
fifo->in = 0;
fifo->out = 0;
fifo->esize = 0;
fifo->data = NULL;
fifo->mask = 0;
}
STATIC INLINE unsigned int fifo_unused(struct __fifo *fifo)
{
return (fifo->mask + 1) - (fifo->in - fifo->out);
}
static void fifo_copy_in(struct __fifo *fifo, const void *src,
unsigned int len, unsigned int off)
{
unsigned int size = fifo->mask + 1;
unsigned int esize = fifo->esize;
unsigned int l;
off &= fifo->mask;
if (esize != 1) {
off *= esize;
size *= esize;
len *= esize;
}
l = min(len, size - off);
/*! 必须类型强转,不然keil编译不过去 */
memcpy((void*)((unsigned int)(fifo->data) + off), src, l);
memcpy(fifo->data, (void*)((unsigned int)src + l), len - l);
/*
* make sure that the data in the fifo is up to date before
* incrementing the fifo->in index counter
*/
//smp_wmb();
}
unsigned int fifo_in(struct __fifo *fifo,
const void *buf, unsigned int len)
{
unsigned int l;
l = fifo_unused(fifo);
if (len > l)
len = l;
fifo_copy_in(fifo, buf, len, fifo->in);
fifo->in += len;
return len;
}
static void fifo_copy_out(struct __fifo *fifo, void *dst,
unsigned int len, unsigned int off)
{
unsigned int size = fifo->mask + 1;
unsigned int esize = fifo->esize;
unsigned int l;
off &= fifo->mask;
if (esize != 1) {
off *= esize;
size *= esize;
len *= esize;
}
l = min(len, size - off);
/*! 必须类型强转,不然keil编译不过去 */
memcpy(dst, (void *)((unsigned int)(fifo->data) + off), l);
memcpy((void *)((unsigned int)dst + l), fifo->data, len - l);
/*
* make sure that the data is copied before
* incrementing the fifo->out index counter
*/
}
unsigned int fifo_out_peek(struct __fifo *fifo,
void *buf, unsigned int len)
{
unsigned int l;
l = fifo->in - fifo->out;
if (len > l)
len = l;
fifo_copy_out(fifo, buf, len, fifo->out);
return len;
}
unsigned int fifo_out(struct __fifo *fifo,
void *buf, unsigned int len)
{
len = fifo_out_peek(fifo, buf, len);
fifo->out += len;
return len;
}