Merge pull request #15839 from maribu/gnrc_pktbuf_release_error
sys/net/gnrc_pktbuf: deduplicate code
This commit is contained in:
commit
8e47621e7c
@ -35,6 +35,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cpu_conf.h"
|
||||
#include "mutex.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/neterr.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
|
||||
@ -3,3 +3,6 @@ USED_PKTBUF_IMPLEMENTATIONS := $(filter-out gnrc_pktbuf_cmd,$(filter gnrc_pktbuf
|
||||
ifneq (1,$(words $(USED_PKTBUF_IMPLEMENTATIONS)))
|
||||
$(error Only one implementation of gnrc_pktbuf should be used. Currently using: $(USED_PKTBUF_IMPLEMENTATIONS))
|
||||
endif
|
||||
|
||||
USEMODULE_INCLUDES_gnrc_pktbuf := $(LAST_MAKEFILEDIR)/include
|
||||
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_gnrc_pktbuf)
|
||||
|
||||
@ -13,8 +13,16 @@
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include "mutex.h"
|
||||
#include "net/gnrc/pktbuf.h"
|
||||
|
||||
#include "pktbuf_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
mutex_t gnrc_pktbuf_mutex = MUTEX_INIT;
|
||||
|
||||
gnrc_pktsnip_t *gnrc_pktbuf_remove_snip(gnrc_pktsnip_t *pkt,
|
||||
gnrc_pktsnip_t *snip)
|
||||
{
|
||||
@ -76,4 +84,27 @@ int gnrc_pktbuf_merge(gnrc_pktsnip_t *pkt)
|
||||
return res;
|
||||
}
|
||||
|
||||
void gnrc_pktbuf_release_error(gnrc_pktsnip_t *pkt, uint32_t err)
|
||||
{
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
while (pkt) {
|
||||
gnrc_pktsnip_t *tmp;
|
||||
assert(gnrc_pktbuf_contains(pkt));
|
||||
assert(pkt->users > 0);
|
||||
tmp = pkt->next;
|
||||
if (pkt->users == 1) {
|
||||
pkt->users = 0; /* not necessary but to be on the safe side */
|
||||
gnrc_pktbuf_free_internal(pkt->data, pkt->size);
|
||||
gnrc_pktbuf_free_internal(pkt, sizeof(gnrc_pktsnip_t));
|
||||
}
|
||||
else {
|
||||
pkt->users--;
|
||||
}
|
||||
DEBUG("pktbuf: report status code %" PRIu32 "\n", err);
|
||||
gnrc_neterr_report(pkt, err);
|
||||
pkt = tmp;
|
||||
}
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
117
sys/net/gnrc/pktbuf/include/pktbuf_internal.h
Normal file
117
sys/net/gnrc/pktbuf/include/pktbuf_internal.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* 2015 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup net_gnrc_pktbuf
|
||||
* @brief Internal stuff for gnrc_pktbuf
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Interface definition for the global network buffer. Network devices
|
||||
* and layers can allocate space for packets here.
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
#ifndef PKTBUF_INTERNAL_H
|
||||
#define PKTBUF_INTERNAL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mutex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Mutex used to provide mutually exclusive access to packet buffer
|
||||
* data structures
|
||||
*
|
||||
* @warning This mutex will be ***internally*** locked and unlocked and should
|
||||
* not be touched by external code
|
||||
*/
|
||||
extern mutex_t gnrc_pktbuf_mutex;
|
||||
|
||||
#if IS_USED(MODULE_GNRC_PKTBUF_STATIC) || DOXYGEN
|
||||
/**
|
||||
* @brief The actual static buffer used when module gnrc_pktbuf_static is used
|
||||
*
|
||||
* @warning This is an internal buffer and should not be touched by external code
|
||||
*/
|
||||
extern uint8_t *gnrc_pktbuf_static_buf;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Check if the given pointer is indeed part of the packet buffer
|
||||
*
|
||||
* @warning This function is ***internal***.
|
||||
*
|
||||
* @param ptr pointer to check
|
||||
*
|
||||
* @retval true It is plausible, that this pointer belongs to data in
|
||||
* the packet buffer
|
||||
* @retval false @p ptr does not point to data in the packet buffer
|
||||
*/
|
||||
static inline bool gnrc_pktbuf_contains(void *ptr)
|
||||
{
|
||||
#if IS_USED(MODULE_GNRC_PKTBUF_STATIC)
|
||||
return (unsigned)((uint8_t *)ptr - gnrc_pktbuf_static_buf) < CONFIG_GNRC_PKTBUF_SIZE;
|
||||
#else
|
||||
(void)ptr;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_GNRC_PKTBUF_STATIC) || DOXYGEN
|
||||
/**
|
||||
* @brief Release an internal buffer
|
||||
*
|
||||
* @warning This function is ***internal***. Use @ref gnrc_pktbuf_release to
|
||||
* release a packet buffer
|
||||
*
|
||||
* @param data pointer to the internal buffer to release
|
||||
* @param size size of @p data in bytes
|
||||
*/
|
||||
void gnrc_pktbuf_free_internal(void *data, size_t size);
|
||||
#else
|
||||
static inline void gnrc_pktbuf_free_internal(void *data, size_t size)
|
||||
{
|
||||
(void)size;
|
||||
free(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* for testing */
|
||||
#ifdef TEST_SUITES
|
||||
/**
|
||||
* @brief Checks if packet buffer is empty
|
||||
*
|
||||
* @return true, if packet buffer is empty
|
||||
* @return false, if packet buffer is not empty
|
||||
*/
|
||||
bool gnrc_pktbuf_is_empty(void);
|
||||
|
||||
/**
|
||||
* @brief Checks if the implementation's internal invariants still uphold
|
||||
*
|
||||
* @return true, the packet buffer is sane.
|
||||
* @return false, the packet buffer is insane.
|
||||
*/
|
||||
bool gnrc_pktbuf_is_sane(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PKTBUF_INTERNAL_H */
|
||||
/** @} */
|
||||
@ -33,11 +33,11 @@
|
||||
#include "net/gnrc/nettype.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
|
||||
#include "pktbuf_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
static mutex_t _mutex = MUTEX_INIT;
|
||||
|
||||
#ifdef MODULE_FUZZING
|
||||
extern gnrc_pktsnip_t *gnrc_pktbuf_fuzzptr;
|
||||
#endif
|
||||
@ -106,9 +106,9 @@ gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, const void *data, size_t s
|
||||
(unsigned)size, CONFIG_GNRC_PKTBUF_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
pkt = _create_snip(next, data, size, type);
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
@ -162,9 +162,9 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
|
||||
{
|
||||
gnrc_pktsnip_t *new;
|
||||
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
new = _mark(pkt, size, type);
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return new;
|
||||
}
|
||||
|
||||
@ -200,53 +200,27 @@ int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size)
|
||||
{
|
||||
int res;
|
||||
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
res = _realloc_data(pkt, size);
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
void gnrc_pktbuf_hold(gnrc_pktsnip_t *pkt, unsigned int num)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
while (pkt) {
|
||||
pkt->users += num;
|
||||
pkt = pkt->next;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
}
|
||||
|
||||
static void _release_error_locked(gnrc_pktsnip_t *pkt, uint32_t err)
|
||||
{
|
||||
while (pkt) {
|
||||
gnrc_pktsnip_t *tmp;
|
||||
tmp = pkt->next;
|
||||
if (pkt->users == 1) {
|
||||
pkt->users = 0; /* not necessary but to be on the safe side */
|
||||
_free(pkt->data);
|
||||
_free(pkt);
|
||||
}
|
||||
else {
|
||||
pkt->users--;
|
||||
}
|
||||
DEBUG("pktbuf: report status code %" PRIu32 "\n", err);
|
||||
gnrc_neterr_report(pkt, err);
|
||||
pkt = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void gnrc_pktbuf_release_error(gnrc_pktsnip_t *pkt, uint32_t err)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
_release_error_locked(pkt, err);
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_pktbuf_start_write(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
if (pkt == NULL) {
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return NULL;
|
||||
}
|
||||
if (pkt->users > 1) {
|
||||
@ -255,10 +229,10 @@ gnrc_pktsnip_t *gnrc_pktbuf_start_write(gnrc_pktsnip_t *pkt)
|
||||
if (new != NULL) {
|
||||
pkt->users--;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return new;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
#include "net/gnrc/nettype.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
|
||||
#include "pktbuf_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
@ -40,12 +42,11 @@ typedef struct _unused {
|
||||
unsigned int size;
|
||||
} _unused_t;
|
||||
|
||||
static mutex_t _mutex = MUTEX_INIT;
|
||||
/* The static buffer needs to be aligned to word size, so that its start
|
||||
* address can be casted to `_unused_t *` safely. Just allocating an array of
|
||||
* (word sized) uintptr_t is a trivial way to do this */
|
||||
static uintptr_t _pktbuf_buf[CONFIG_GNRC_PKTBUF_SIZE / sizeof(uintptr_t)];
|
||||
static uint8_t *_pktbuf = (uint8_t *)_pktbuf_buf;
|
||||
uint8_t *gnrc_pktbuf_static_buf = (uint8_t *)_pktbuf_buf;
|
||||
static _unused_t *_first_unused;
|
||||
|
||||
#ifdef DEVELHELP
|
||||
@ -57,12 +58,6 @@ static uint16_t max_byte_count = 0;
|
||||
static gnrc_pktsnip_t *_create_snip(gnrc_pktsnip_t *next, const void *data, size_t size,
|
||||
gnrc_nettype_t type);
|
||||
static void *_pktbuf_alloc(size_t size);
|
||||
static void _pktbuf_free(void *data, size_t size);
|
||||
|
||||
static inline bool _pktbuf_contains(void *ptr)
|
||||
{
|
||||
return (unsigned)((uint8_t *)ptr - _pktbuf) < CONFIG_GNRC_PKTBUF_SIZE;
|
||||
}
|
||||
|
||||
/* fits size to byte alignment */
|
||||
static inline size_t _align(size_t size)
|
||||
@ -85,11 +80,11 @@ static inline void _set_pktsnip(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *next,
|
||||
|
||||
void gnrc_pktbuf_init(void)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
_first_unused = (_unused_t *)_pktbuf_buf;
|
||||
_first_unused->next = NULL;
|
||||
_first_unused->size = sizeof(_pktbuf_buf);
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, const void *data, size_t size,
|
||||
@ -102,9 +97,9 @@ gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, const void *data, size_t s
|
||||
(unsigned)size, CONFIG_GNRC_PKTBUF_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
pkt = _create_snip(next, data, size, type);
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
@ -115,20 +110,20 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
|
||||
size_t required_new_size = _align(size);
|
||||
void *new_data_marked;
|
||||
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
if ((size == 0) || (pkt == NULL) || (size > pkt->size) || (pkt->data == NULL)) {
|
||||
DEBUG("pktbuf: size == 0 (was %u) or pkt == NULL (was %p) or "
|
||||
"size > pkt->size (was %u) or pkt->data == NULL (was %p)\n",
|
||||
(unsigned)size, (void *)pkt, (pkt ? (unsigned)pkt->size : 0),
|
||||
(pkt ? pkt->data : NULL));
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return NULL;
|
||||
}
|
||||
/* create new snip descriptor for marked data */
|
||||
marked_snip = _pktbuf_alloc(sizeof(gnrc_pktsnip_t));
|
||||
if (marked_snip == NULL) {
|
||||
DEBUG("pktbuf: could not reallocate marked section.\n");
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return NULL;
|
||||
}
|
||||
/* marked data would not fit _unused_t marker => move data around to allow
|
||||
@ -138,21 +133,21 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
|
||||
new_data_marked = _pktbuf_alloc(size);
|
||||
if (new_data_marked == NULL) {
|
||||
DEBUG("pktbuf: could not reallocate marked section.\n");
|
||||
_pktbuf_free(marked_snip, sizeof(gnrc_pktsnip_t));
|
||||
mutex_unlock(&_mutex);
|
||||
gnrc_pktbuf_free_internal(marked_snip, sizeof(gnrc_pktsnip_t));
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return NULL;
|
||||
}
|
||||
new_data_rest = _pktbuf_alloc(pkt->size - size);
|
||||
if (new_data_rest == NULL) {
|
||||
DEBUG("pktbuf: could not reallocate remaining section.\n");
|
||||
_pktbuf_free(marked_snip, sizeof(gnrc_pktsnip_t));
|
||||
_pktbuf_free(new_data_marked, size);
|
||||
mutex_unlock(&_mutex);
|
||||
gnrc_pktbuf_free_internal(marked_snip, sizeof(gnrc_pktsnip_t));
|
||||
gnrc_pktbuf_free_internal(new_data_marked, size);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(new_data_marked, pkt->data, size);
|
||||
memcpy(new_data_rest, ((uint8_t *)pkt->data) + size, pkt->size - size);
|
||||
_pktbuf_free(pkt->data, pkt->size);
|
||||
gnrc_pktbuf_free_internal(pkt->data, pkt->size);
|
||||
marked_snip->data = new_data_marked;
|
||||
pkt->data = new_data_rest;
|
||||
}
|
||||
@ -165,7 +160,7 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
|
||||
pkt->size -= size;
|
||||
_set_pktsnip(marked_snip, pkt->next, new_data_marked, size, type);
|
||||
pkt->next = marked_snip;
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return marked_snip;
|
||||
}
|
||||
|
||||
@ -173,20 +168,20 @@ int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size)
|
||||
{
|
||||
size_t aligned_size = _align(size);
|
||||
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
assert(pkt != NULL);
|
||||
assert(((pkt->size == 0) && (pkt->data == NULL)) ||
|
||||
((pkt->size > 0) && (pkt->data != NULL) && _pktbuf_contains(pkt->data)));
|
||||
((pkt->size > 0) && (pkt->data != NULL) && gnrc_pktbuf_contains(pkt->data)));
|
||||
/* new size and old size are equal */
|
||||
if (size == pkt->size) {
|
||||
/* nothing to do */
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return 0;
|
||||
}
|
||||
/* new size is 0 and data pointer isn't already NULL */
|
||||
if ((size == 0) && (pkt->data != NULL)) {
|
||||
/* set data pointer to NULL */
|
||||
_pktbuf_free(pkt->data, pkt->size);
|
||||
gnrc_pktbuf_free_internal(pkt->data, pkt->size);
|
||||
pkt->data = NULL;
|
||||
}
|
||||
/* if new size is bigger than old size */
|
||||
@ -194,67 +189,39 @@ int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size)
|
||||
void *new_data = _pktbuf_alloc(size);
|
||||
if (new_data == NULL) {
|
||||
DEBUG("pktbuf: error allocating new data section\n");
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return ENOMEM;
|
||||
}
|
||||
if (pkt->data != NULL) { /* if old data exist */
|
||||
memcpy(new_data, pkt->data, (pkt->size < size) ? pkt->size : size);
|
||||
}
|
||||
_pktbuf_free(pkt->data, pkt->size);
|
||||
gnrc_pktbuf_free_internal(pkt->data, pkt->size);
|
||||
pkt->data = new_data;
|
||||
}
|
||||
else if (_align(pkt->size) > aligned_size) {
|
||||
_pktbuf_free(((uint8_t *)pkt->data) + aligned_size,
|
||||
gnrc_pktbuf_free_internal(((uint8_t *)pkt->data) + aligned_size,
|
||||
pkt->size - aligned_size);
|
||||
}
|
||||
pkt->size = size;
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gnrc_pktbuf_hold(gnrc_pktsnip_t *pkt, unsigned int num)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
while (pkt) {
|
||||
pkt->users += num;
|
||||
pkt = pkt->next;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
}
|
||||
|
||||
static void _release_error_locked(gnrc_pktsnip_t *pkt, uint32_t err)
|
||||
{
|
||||
while (pkt) {
|
||||
gnrc_pktsnip_t *tmp;
|
||||
assert(_pktbuf_contains(pkt));
|
||||
assert(pkt->users > 0);
|
||||
tmp = pkt->next;
|
||||
if (pkt->users == 1) {
|
||||
pkt->users = 0; /* not necessary but to be on the safe side */
|
||||
_pktbuf_free(pkt->data, pkt->size);
|
||||
_pktbuf_free(pkt, sizeof(gnrc_pktsnip_t));
|
||||
}
|
||||
else {
|
||||
pkt->users--;
|
||||
}
|
||||
DEBUG("pktbuf: report status code %" PRIu32 "\n", err);
|
||||
gnrc_neterr_report(pkt, err);
|
||||
pkt = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void gnrc_pktbuf_release_error(gnrc_pktsnip_t *pkt, uint32_t err)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
_release_error_locked(pkt, err);
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_pktbuf_start_write(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
mutex_lock(&gnrc_pktbuf_mutex);
|
||||
if (pkt == NULL) {
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return NULL;
|
||||
}
|
||||
if (pkt->users > 1) {
|
||||
@ -263,10 +230,10 @@ gnrc_pktsnip_t *gnrc_pktbuf_start_write(gnrc_pktsnip_t *pkt)
|
||||
if (new != NULL) {
|
||||
pkt->users--;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return new;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
mutex_unlock(&gnrc_pktbuf_mutex);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
@ -303,11 +270,13 @@ void gnrc_pktbuf_stats(void)
|
||||
{
|
||||
#ifdef MODULE_OD
|
||||
_unused_t *ptr = _first_unused;
|
||||
uint8_t *chunk = &_pktbuf[0];
|
||||
uint8_t *chunk = &gnrc_pktbuf_static_buf[0];
|
||||
int count = 0;
|
||||
|
||||
printf("packet buffer: first byte: %p, last byte: %p (size: %u)\n",
|
||||
(void *)&_pktbuf[0], (void *)&_pktbuf[CONFIG_GNRC_PKTBUF_SIZE], CONFIG_GNRC_PKTBUF_SIZE);
|
||||
(void *)&gnrc_pktbuf_static_buf[0],
|
||||
(void *)&gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE],
|
||||
CONFIG_GNRC_PKTBUF_SIZE);
|
||||
printf(" position of last byte used: %" PRIu16 "\n", max_byte_count);
|
||||
if (ptr == NULL) { /* packet buffer is completely full */
|
||||
_print_chunk(chunk, CONFIG_GNRC_PKTBUF_SIZE, count++);
|
||||
@ -321,8 +290,8 @@ void gnrc_pktbuf_stats(void)
|
||||
|
||||
while (ptr) {
|
||||
size_t size = ((uint8_t *)ptr) - chunk;
|
||||
if ((size == 0) && (!_pktbuf_contains(ptr)) &&
|
||||
(!_pktbuf_contains(chunk)) && (size > CONFIG_GNRC_PKTBUF_SIZE)) {
|
||||
if ((size == 0) && (!gnrc_pktbuf_contains(ptr)) &&
|
||||
(!gnrc_pktbuf_contains(chunk)) && (size > CONFIG_GNRC_PKTBUF_SIZE)) {
|
||||
puts("ERROR");
|
||||
return;
|
||||
}
|
||||
@ -332,8 +301,8 @@ void gnrc_pktbuf_stats(void)
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
if (chunk <= &_pktbuf[CONFIG_GNRC_PKTBUF_SIZE - 1]) {
|
||||
_print_chunk(chunk, &_pktbuf[CONFIG_GNRC_PKTBUF_SIZE] - chunk, count);
|
||||
if (chunk <= &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE - 1]) {
|
||||
_print_chunk(chunk, &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE] - chunk, count);
|
||||
}
|
||||
#else
|
||||
DEBUG("pktbuf: needs od module\n");
|
||||
@ -344,7 +313,7 @@ void gnrc_pktbuf_stats(void)
|
||||
#ifdef TEST_SUITES
|
||||
bool gnrc_pktbuf_is_empty(void)
|
||||
{
|
||||
return (_first_unused == (_unused_t *)_pktbuf) &&
|
||||
return (_first_unused == (_unused_t *)gnrc_pktbuf_static_buf) &&
|
||||
(_first_unused->size == sizeof(_pktbuf_buf));
|
||||
}
|
||||
|
||||
@ -355,22 +324,25 @@ bool gnrc_pktbuf_is_sane(void)
|
||||
/* Invariants of this implementation:
|
||||
* - the head of _unused_t list is _first_unused
|
||||
* - if _unused_t list is empty the packet buffer is full and _first_unused is NULL
|
||||
* - forall ptr_in _unused_t list: &_pktbuf[0] < ptr < &_pktbuf[CONFIG_GNRC_PKTBUF_SIZE]
|
||||
* - forall ptr_in _unused_t list: &gnrc_pktbuf_static_buf[0] < ptr
|
||||
* && ptr < &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE]
|
||||
* - forall ptr in _unused_t list: ptr->next == NULL || ptr < ptr->next
|
||||
* - forall ptr in _unused_t list: (ptr->next != NULL && ptr->size <= (ptr->next - ptr)) ||
|
||||
* (ptr->next == NULL && ptr->size == (CONFIG_GNRC_PKTBUF_SIZE - (ptr - &_pktbuf[0])))
|
||||
* (ptr->next == NULL
|
||||
* && ptr->size == (CONFIG_GNRC_PKTBUF_SIZE - pos_in_buf))
|
||||
*/
|
||||
|
||||
while (ptr) {
|
||||
if (&_pktbuf[0] >= (uint8_t *)ptr && (uint8_t *)ptr >= &_pktbuf[CONFIG_GNRC_PKTBUF_SIZE]) {
|
||||
if ((&gnrc_pktbuf_static_buf[0] >= (uint8_t *)ptr)
|
||||
&& ((uint8_t *)ptr >= &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE])) {
|
||||
return false;
|
||||
}
|
||||
if ((ptr->next != NULL) && (ptr >= ptr->next)) {
|
||||
return false;
|
||||
}
|
||||
if (((ptr->next == NULL) || (ptr->size > (size_t)((uint8_t *)(ptr->next) - (uint8_t *)ptr))) &&
|
||||
((ptr->next != NULL) ||
|
||||
(ptr->size != (size_t)(CONFIG_GNRC_PKTBUF_SIZE - ((uint8_t *)ptr - &_pktbuf[0]))))) {
|
||||
size_t pos_in_buf = (uint8_t *)ptr - &gnrc_pktbuf_static_buf[0];
|
||||
if (((ptr->next == NULL) || (ptr->size > (size_t)((uint8_t *)(ptr->next) - (uint8_t *)ptr)))
|
||||
&& ((ptr->next != NULL) || (ptr->size != CONFIG_GNRC_PKTBUF_SIZE - pos_in_buf))) {
|
||||
return false;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
@ -394,7 +366,7 @@ static gnrc_pktsnip_t *_create_snip(gnrc_pktsnip_t *next, const void *data, size
|
||||
_data = _pktbuf_alloc(size);
|
||||
if (_data == NULL) {
|
||||
DEBUG("pktbuf: error allocating data for new packet snip\n");
|
||||
_pktbuf_free(pkt, sizeof(gnrc_pktsnip_t));
|
||||
gnrc_pktbuf_free_internal(pkt, sizeof(gnrc_pktsnip_t));
|
||||
return NULL;
|
||||
}
|
||||
if (data != NULL) {
|
||||
@ -432,7 +404,8 @@ static void *_pktbuf_alloc(size_t size)
|
||||
* We cast to uintptr_t as intermediate step to silence -Wcast-align */
|
||||
_unused_t *new = (_unused_t *)((uintptr_t)ptr + size);
|
||||
|
||||
if (((((uint8_t *)new) - &(_pktbuf[0])) + sizeof(_unused_t)) > CONFIG_GNRC_PKTBUF_SIZE) {
|
||||
if (((((uint8_t *)new) - &(gnrc_pktbuf_static_buf[0])) + sizeof(_unused_t))
|
||||
> CONFIG_GNRC_PKTBUF_SIZE) {
|
||||
/* content of new would exceed packet buffer size so set to NULL */
|
||||
_first_unused = NULL;
|
||||
}
|
||||
@ -446,7 +419,7 @@ static void *_pktbuf_alloc(size_t size)
|
||||
new->size = ptr->size - size;
|
||||
}
|
||||
#ifdef DEVELHELP
|
||||
uint16_t last_byte = (uint16_t)((((uint8_t *)ptr) + size) - &(_pktbuf[0]));
|
||||
uint16_t last_byte = (uint16_t)((((uint8_t *)ptr) + size) - &(gnrc_pktbuf_static_buf[0]));
|
||||
if (last_byte > max_byte_count) {
|
||||
max_byte_count = last_byte;
|
||||
}
|
||||
@ -468,12 +441,12 @@ static inline _unused_t *_merge(_unused_t *a, _unused_t *b)
|
||||
return a;
|
||||
}
|
||||
|
||||
static void _pktbuf_free(void *data, size_t size)
|
||||
void gnrc_pktbuf_free_internal(void *data, size_t size)
|
||||
{
|
||||
size_t bytes_at_end;
|
||||
_unused_t *new = (_unused_t *)data, *prev = NULL, *ptr = _first_unused;
|
||||
|
||||
if (!_pktbuf_contains(data)) {
|
||||
if (!gnrc_pktbuf_contains(data)) {
|
||||
return;
|
||||
}
|
||||
while (ptr && (((void *)ptr) < data)) {
|
||||
@ -484,7 +457,8 @@ static void _pktbuf_free(void *data, size_t size)
|
||||
new->size = _align(size);
|
||||
/* calculate number of bytes between new _unused_t chunk and end of packet
|
||||
* buffer */
|
||||
bytes_at_end = ((&_pktbuf[0] + CONFIG_GNRC_PKTBUF_SIZE) - (((uint8_t *)new) + new->size));
|
||||
bytes_at_end = ((&gnrc_pktbuf_static_buf[0] + CONFIG_GNRC_PKTBUF_SIZE)
|
||||
- (((uint8_t *)new) + new->size));
|
||||
if (bytes_at_end < sizeof(_unused_t)) {
|
||||
/* new is very last segment and there is a little bit of memory left
|
||||
* that wouldn't fit _unused_t (cut of in _pktbuf_alloc()) => re-add it */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user