incubator-nuttx/wireless/pktradio/pktradio_metadata.c

227 lines
6.5 KiB
C

/****************************************************************************
* wireless/pktradio/pktradio_metadata.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mm/iob.h>
#include <nuttx/mutex.h>
#include <nuttx/wireless/pktradio.h>
/****************************************************************************
* Private Data
****************************************************************************/
/* The g_free_metadata is a list of meta-data structures that are available
* for general use. The number of messages in this list is a system
* configuration item.
*/
static FAR struct pktradio_metadata_s *g_free_metadata;
/* Supports mutually exclusive access to the free list */
static mutex_t g_metadata_lock = NXMUTEX_INITIALIZER;
/* Idempotence support */
static bool g_metadata_initialized;
/* Pool of pre-allocated meta-data structures */
static struct pktradio_metadata_s g_metadata_pool[CONFIG_PKTRADIO_NRXMETA];
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pktradio_metadata_initialize
*
* Description:
* This function initializes the meta-data allocator. This function must
* be called early in the initialization sequence before any radios
* begin operation.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void pktradio_metadata_initialize(void)
{
FAR struct pktradio_metadata_s *metadata;
int i;
if (!g_metadata_initialized)
{
/* Initialize g_free_metadata, the list of meta-data structures that
* are available for allocation.
*/
g_free_metadata = NULL;
for (i = 0, metadata = g_metadata_pool;
i < CONFIG_PKTRADIO_NRXMETA;
i++, metadata++)
{
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
metadata->pm_flink = g_free_metadata;
g_free_metadata = metadata;
}
g_metadata_initialized = true;
}
}
/****************************************************************************
* Name: pktradio_metadata_allocate
*
* Description:
* The pktradio_metadata_allocate function will get a free meta-data
* structure for use by the packet radio.
*
* This function will first attempt to allocate from the g_free_metadata
* list. If that the list is empty, then the meta-data structure will be
* allocated from the dynamic memory pool.
*
* Input Parameters:
* None
*
* Returned Value:
* A reference to the allocated metadata structure. All user fields in
* this structure have been zeroed. On a failure to allocate, NULL is
* returned.
*
****************************************************************************/
FAR struct pktradio_metadata_s *pktradio_metadata_allocate(void)
{
FAR struct pktradio_metadata_s *metadata;
uint8_t pool;
/* Get exclusive access to the free list */
nxmutex_lock(&g_metadata_lock);
/* Try the free list first */
if (g_free_metadata != NULL)
{
metadata = g_free_metadata;
g_free_metadata = metadata->pm_flink;
pool = PKTRADIO_POOL_PREALLOCATED;
/* We are finished with the free list */
nxmutex_unlock(&g_metadata_lock);
}
else
{
/* If we cannot get a meta-data instance from the free list, then we
* will have to allocate one from the kernel memory pool. We won't
* access the free list.
*/
nxmutex_unlock(&g_metadata_lock);
metadata = (FAR struct pktradio_metadata_s *)
kmm_malloc((sizeof (struct pktradio_metadata_s)));
pool = PKTRADIO_POOL_DYNAMIC;
}
/* We have successfully allocated memory from some source? */
if (metadata != NULL)
{
/* Zero and tag the allocated meta-data structure. */
memset(metadata, 0, sizeof(struct pktradio_metadata_s));
metadata->pm_pool = pool;
}
return metadata;
}
/****************************************************************************
* Name: pktradio_metadata_free
*
* Description:
* The pktradio_metadata_free function will return a metadata structure
* to the free list of messages if it was a pre-allocated metadata
* structure. If the metadata structure was allocated dynamically it will
* be deallocated.
*
* Input Parameters:
* metadata - metadata structure to free
*
* Returned Value:
* None
*
****************************************************************************/
void pktradio_metadata_free(FAR struct pktradio_metadata_s *metadata)
{
/* Get exclusive access to the free list */
nxmutex_lock(&g_metadata_lock);
/* If this is a pre-allocated meta-data structure, then just put it back
* in the free list.
*/
if (metadata->pm_pool == PKTRADIO_POOL_PREALLOCATED)
{
metadata->pm_flink = g_free_metadata;
g_free_metadata = metadata;
/* We are finished with the free list */
nxmutex_unlock(&g_metadata_lock);
}
else
{
DEBUGASSERT(metadata->pm_pool == PKTRADIO_POOL_DYNAMIC);
/* Otherwise, deallocate it. We won't access the free list */
nxmutex_unlock(&g_metadata_lock);
kmm_free(metadata);
}
}