Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSAPIRBHeap
0007  *
0008  * @brief This header file provides the Red-Black Tree Heap API.
0009  */
0010 
0011 /*
0012  * Copyright (c) 2012 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifndef _RTEMS_RBHEAP_H
0037 #define _RTEMS_RBHEAP_H
0038 
0039 #include <rtems.h>
0040 #include <rtems/chain.h>
0041 #include <rtems/rbtree.h>
0042 
0043 #ifdef __cplusplus
0044 extern "C" {
0045 #endif
0046 
0047 /**
0048  * @defgroup RTEMSAPIRBHeap Red-Black Tree Heap
0049  *
0050  * @ingroup RTEMSAPI
0051  *
0052  * @brief The red-black tree heap provides a memory allocator using a red-black
0053  *   tree to maintain blocks of memory.
0054  *
0055  * The red-black tree heap provides a memory allocator suitable to implement
0056  * the malloc() and free() interface.  It uses a first-fit allocation strategy.
0057  * In the red-black tree heap the administration data structures are not
0058  * contained in the managed memory area.  Thus writing beyond the boundaries of
0059  * a chunk does not damage the data to maintain the heap.  This can be used for
0060  * example in a task stack allocator which protects the task stacks from access
0061  * by other tasks.  The allocated and free memory parts of the managed area are
0062  * called chunks.  Each chunk needs a descriptor which is stored outside of the
0063  * managed area.
0064  */
0065 /**@{*/
0066 
0067 /**
0068  * @brief Red-black heap chunk descriptor.
0069  */
0070 typedef struct {
0071   /**
0072    * This chain node can be used in two chains
0073    *  - the chain of spare chunk descriptors and
0074    *  - the chain of free chunks in the managed memory area.
0075    *
0076    * In case this chain node is not part of a chain, the chunk represents a
0077    * used chunk in the managed memory area.
0078    */
0079   rtems_chain_node chain_node;
0080 
0081   /**
0082    * Tree node for chunks that represent a part of the managed memory area.
0083    * These chunks are either free or used.
0084    */
0085   rtems_rbtree_node tree_node;
0086 
0087   /**
0088    * Begin address of the chunk.  The address alignment it specified in the
0089    * @ref rtems_rbheap_control.
0090    */
0091   uintptr_t begin;
0092 
0093   /**
0094    * Size of the chunk in bytes.
0095    */
0096   uintptr_t size;
0097 } rtems_rbheap_chunk;
0098 
0099 typedef struct rtems_rbheap_control rtems_rbheap_control;
0100 
0101 /**
0102  * @brief Handler to extend the available chunk descriptors.
0103  *
0104  * This handler is called when no more chunk descriptors are available.  An
0105  * example implementation is this:
0106  *
0107  * @code
0108  * void extend_descriptors_with_malloc(rtems_rbheap_control *control)
0109  * {
0110  *   rtems_rbheap_chunk *chunk = malloc(sizeof(*chunk));
0111  *
0112  *   if (chunk != NULL) {
0113  *     rtems_rbheap_add_to_spare_descriptor_chain(control, chunk);
0114  *   }
0115  * }
0116  * @endcode
0117  *
0118  * @see rtems_rbheap_extend_descriptors_never() and
0119  * rtems_rbheap_extend_descriptors_with_malloc().
0120  */
0121 typedef void (*rtems_rbheap_extend_descriptors)(rtems_rbheap_control *control);
0122 
0123 /**
0124  * @brief Red-black heap control.
0125  */
0126 struct rtems_rbheap_control {
0127   /**
0128    * Chain of free chunks in the managed memory area.
0129    */
0130   rtems_chain_control free_chunk_chain;
0131 
0132   /**
0133    * Chain of free chunk descriptors.  Descriptors are consumed during
0134    * allocation and may be produced during free if contiguous chunks can be
0135    * coalesced.  In case of descriptor starvation the @ref extend_descriptors
0136    * handler will be called.
0137    */
0138   rtems_chain_control spare_descriptor_chain;
0139 
0140   /**
0141    * Tree of chunks representing the state of the managed memory area.
0142    */
0143   rtems_rbtree_control chunk_tree;
0144 
0145   /**
0146    * Minimum chunk begin alignment in bytes.
0147    */
0148   uintptr_t alignment;
0149 
0150   /**
0151    * Handler to extend the available chunk descriptors.
0152    */
0153   rtems_rbheap_extend_descriptors extend_descriptors;
0154 
0155   /**
0156    * User specified argument handler for private handler data.
0157    */
0158   void *handler_arg;
0159 };
0160 
0161 /**
0162  * @brief Initializes the red-black tree heap @a control.
0163  *
0164  * @param[in, out] control The red-black tree heap.
0165  * @param[in] area_begin The managed memory area begin.
0166  * @param[in] area_size The managed memory area size.
0167  * @param[in] alignment The minimum chunk alignment.
0168  * @param[in] extend_descriptors The handler to extend the available chunk
0169  * descriptors.
0170  * @param[in] handler_arg The handler argument.
0171  *
0172  * @retval RTEMS_SUCCESSFUL Successful operation.
0173  * @retval RTEMS_INVALID_ADDRESS The memory area is invalid.
0174  * @retval RTEMS_NO_MEMORY Not enough chunk descriptors.
0175  */
0176 rtems_status_code rtems_rbheap_initialize(
0177   rtems_rbheap_control *control,
0178   void *area_begin,
0179   uintptr_t area_size,
0180   uintptr_t alignment,
0181   rtems_rbheap_extend_descriptors extend_descriptors,
0182   void *handler_arg
0183 );
0184 
0185 /**
0186  * @brief Allocates a chunk of memory of at least @a size bytes from the
0187  * red-black tree heap @a control.
0188  *
0189  * The chunk begin is aligned by the value specified in
0190  * rtems_rbheap_initialize().
0191  *
0192  * @param[in, out] control The red-black tree heap.
0193  * @param[in] size The requested chunk size in bytes.
0194  *
0195  * @retval NULL Not enough free space in the heap.
0196  * @retval otherwise Pointer to allocated chunk of memory.
0197  */
0198 void *rtems_rbheap_allocate(rtems_rbheap_control *control, size_t size);
0199 
0200 /**
0201  * @brief Frees a chunk of memory @a ptr allocated from the red-black tree heap
0202  * @a control.
0203  *
0204  * @param[in, out] control The red-black tree heap.
0205  * @param[in] ptr The pointer to the chunk of memory.
0206  *
0207  * @retval RTEMS_SUCCESSFUL Successful operation.
0208  * @retval RTEMS_INVALID_ID The chunk of memory is not a valid chunk in the
0209  * red-black tree heap.
0210  * @retval RTEMS_INCORRECT_STATE The chunk of memory is not in the right state.
0211  */
0212 rtems_status_code rtems_rbheap_free(rtems_rbheap_control *control, void *ptr);
0213 
0214 static inline rtems_chain_control *rtems_rbheap_get_spare_descriptor_chain(
0215   rtems_rbheap_control *control
0216 )
0217 {
0218   return &control->spare_descriptor_chain;
0219 }
0220 
0221 static inline void rtems_rbheap_add_to_spare_descriptor_chain(
0222   rtems_rbheap_control *control,
0223   rtems_rbheap_chunk *chunk
0224 )
0225 {
0226   rtems_chain_control *chain =
0227     rtems_rbheap_get_spare_descriptor_chain(control);
0228 
0229   rtems_chain_initialize_node(&chunk->chain_node);
0230   rtems_chain_prepend_unprotected(chain, &chunk->chain_node);
0231 }
0232 
0233 static inline void rtems_rbheap_set_extend_descriptors(
0234   rtems_rbheap_control *control,
0235   rtems_rbheap_extend_descriptors extend_descriptors
0236 )
0237 {
0238   control->extend_descriptors = extend_descriptors;
0239 }
0240 
0241 static inline void *rtems_rbheap_get_handler_arg(
0242   const rtems_rbheap_control *control
0243 )
0244 {
0245   return control->handler_arg;
0246 }
0247 
0248 static inline void rtems_rbheap_set_handler_arg(
0249   rtems_rbheap_control *control,
0250   void *handler_arg
0251 )
0252 {
0253   control->handler_arg = handler_arg;
0254 }
0255 
0256 /**
0257  * @brief Chunk descriptor extend handler that does nothing.
0258  */
0259 void rtems_rbheap_extend_descriptors_never(rtems_rbheap_control *control);
0260 
0261 /**
0262  * @brief Chunk descriptor extend handler that uses malloc().
0263  */
0264 void rtems_rbheap_extend_descriptors_with_malloc(
0265   rtems_rbheap_control *control
0266 );
0267 
0268 /** @} */
0269 
0270 /* Private API */
0271 
0272 #define rtems_rbheap_chunk_of_node(node) \
0273   RTEMS_CONTAINER_OF(node, rtems_rbheap_chunk, tree_node)
0274 
0275 static inline bool rtems_rbheap_is_chunk_free(const rtems_rbheap_chunk *chunk)
0276 {
0277   return !rtems_chain_is_node_off_chain(&chunk->chain_node);
0278 }
0279 
0280 #ifdef __cplusplus
0281 }
0282 #endif
0283 
0284 #endif /* _RTEMS_RBHEAP_H */