Newer
Older
pbuf / inc / pbuf.h
@Razvan Turiac Razvan Turiac on 4 Sep 2020 3 KB Added pbuf_free_queue()
#ifndef _PBUF_H
#define _PBUF_H


#include <stdint.h>
#include <stddef.h>

#include <assert.h>


#ifdef __cplusplus
extern "C"
{
#endif


typedef void (*pbuf_callback_t)(void);		//function pointer that will be called when a pbuf is freed in this pool

struct pbuf_pool_s;

typedef struct pbuf_s
{
	uint8_t* payload;
	uint32_t length;

	uint32_t capacity;
	uint8_t* payload_memory;

	struct pbuf_s *next;			//used to link pbufs
	struct pbuf_pool_s *pool;

	void *user;
}pbuf_t;



typedef struct pbuf_pool_s
{
	pbuf_t* pbuf_memory;
	uint32_t pbuf_count;

	uint8_t* payload_memory;
	uint32_t payload_capacity;
	
	uint32_t pbufs_available;
	pbuf_t* free_list;
	
	pbuf_callback_t free_callback;
}pbuf_pool_t;



#define PBUF_DECLARE_POOL(pool_name, pbuf_count, pbuf_size) \
static uint8_t pool_name##_payload_memory[(pbuf_count) * (pbuf_size)] __attribute__((aligned(4))); \
static pbuf_t pool_name##_memory[pbuf_count]; \
pbuf_pool_t pool_name


#define STATIC_PBUF_DECLARE_POOL(pool_name, pbuf_count, pbuf_size) \
static uint8_t pool_name##_payload_memory[(pbuf_count) * (pbuf_size)] __attribute__((aligned(4))); \
static pbuf_t pool_name##_memory[pbuf_count]; \
static pbuf_pool_t pool_name



#define PBUF_INIT_POOL(pool_name) \
	pbuf_pool_create(&pool_name, \
						sizeof(pool_name##_memory) / sizeof(pbuf_t), \
						pool_name##_memory, \
						sizeof(pool_name##_payload_memory) / (sizeof(pool_name##_memory) / sizeof(pbuf_t)), \
						pool_name##_payload_memory)


/**
	\brief Creates a new pool of pbufs

	\param pool 		Pointer to a pbuf_pool_t structure that will be initialized
	\param pbuf_count	Number of pbufs to create in the pbuf pool
	\param pbuf_memory	Pointer to a statically allocated area of memory for storing the pbuf structures. 
	\param payload_capacity	Size of the pbuf payload.
	\param payload_memory		Pointer to statically allocated memory that will be used for storing the pbuf attached buffers
									
	pbuf_memory needs to be a statically allocated memory chunk of size: pbuf_count * sizeof(pbuf_t) (bytes)
	payload_memory needs to be a statically allocated memory chunk of size: pbuf_count * pbuf_payload_size (bytes)

*/
void pbuf_pool_create(pbuf_pool_t *pool, uint32_t pbuf_count, void *pbuf_memory, uint32_t payload_capacity, void *payload_memory);
void pbuf_pool_reset(pbuf_pool_t *pool);


void pbuf_dump_pool(pbuf_pool_t *pool);


static inline uint32_t pbuf_pool_get_available(pbuf_pool_t *pool)
{
	return pool->pbufs_available;
}


static inline pbuf_t* pbuf_alloc(pbuf_pool_t *pool)
{
	assert(pool);

	pbuf_t* p = pool->free_list;

	if (p)
	{
		pool->free_list = pool->free_list->next;		//remove it from the list
		pool->pbufs_available--;
		
		p->payload = p->payload_memory;
		p->capacity = pool->payload_capacity;
	}

	return p;
}


static inline void pbuf_free(pbuf_t* p)
{
	if (p)
	{
		p->next = p->pool->free_list;		//add it back to the free list
		p->pool->free_list = p;
		p->pool->pbufs_available++;

		if (p->pool->free_callback)				//call the hook if we have one
			p->pool->free_callback();
	}
}


static inline void pbuf_free_queue(pbuf_t* queue)
{
	while(queue)
	{
		pbuf_t *p = queue;
		queue = queue->next;
		
		pbuf_free(p);
	}
}


#ifdef __cplusplus
}
#endif

#endif