"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/file-process/file_mempool.c" (16 Oct 2020, 8407 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "file_mempool.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.9.16.1_vs_2.9.17.

    1 /*
    2  **
    3  **
    4  **  Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    5  **  Copyright (C) 2013-2013 Sourcefire, Inc.
    6  **
    7  **  This program is free software; you can redistribute it and/or modify
    8  **  it under the terms of the GNU General Public License Version 2 as
    9  **  published by the Free Software Foundation.  You may not use, modify or
   10  **  distribute this program under any other version of the GNU General
   11  **  Public License.
   12  **
   13  **  This program is distributed in the hope that it will be useful,
   14  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  **  GNU General Public License for more details.
   17  **
   18  **  You should have received a copy of the GNU General Public License
   19  **  along with this program; if not, write to the Free Software
   20  **  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   21  **
   22  **  This mempool implementation has very efficient alloc/free operations.
   23  **  In addition, it provides thread-safe alloc/free for one allocation/free
   24  **  thread and one release thread. One more bonus: Double free detection is
   25  **  also added into this library
   26  **
   27  **  Author(s):  Hui Cao <hcao@sourcefire.com>
   28  **
   29  **  NOTES
   30  **  5.25.13 - Initial Source Code. Hui Cao
   31  **
   32  **  A
   33  */
   34 
   35 #include <stdlib.h>
   36 #include <stdio.h>
   37 #include <assert.h>
   38 #include "file_mempool.h"
   39 #include "util.h"
   40 
   41 /*This magic is used for double free detection*/
   42 
   43 #define FREE_MAGIC    0x2525252525252525
   44 typedef uint64_t      MagicType;
   45 #ifdef DEBUG_MSGS
   46 
   47 static inline void safe_mempool_verify(SafeMemPool *mempool)
   48 {
   49     uint64_t free_size;
   50     uint64_t release_size;
   51 
   52     free_size = cbuffer_used(mempool->free_list);
   53     release_size = cbuffer_used(mempool->released_list);
   54 
   55     if (free_size > cbuffer_size(mempool->free_list))
   56     {
   57         ErrorMessage("%s(%d) safe_mempool: failed to verify free list!\n",
   58                 __FILE__, __LINE__ );
   59     }
   60 
   61     if (release_size > cbuffer_size(mempool->released_list))
   62     {
   63         ErrorMessage("%s(%d) safe_mempool: failed to verify release list!\n",
   64                 __FILE__, __LINE__ );
   65     }
   66 
   67     /* The free mempool and size of release mempool should be smaller than
   68      * or equal to the size of mempool
   69      */
   70     if (free_size + release_size > mempool->total)
   71     {
   72         ErrorMessage("%s(%d) safe_mempool: failed to verify mempool size!\n",
   73                 __FILE__, __LINE__ );
   74     }
   75 }
   76 
   77 #endif
   78 
   79 static inline void safe_mempool_free_pools(SafeMemPool *mempool)
   80 {
   81     if (mempool == NULL)
   82         return;
   83 
   84     if (mempool->datapool != NULL)
   85     {
   86         free(mempool->datapool);
   87         mempool->datapool = NULL;
   88     }
   89 
   90     cbuffer_free(mempool->free_list);
   91     cbuffer_free(mempool->released_list);
   92 
   93 }
   94 
   95 /* Function: int safe_mempool_init(SafeMemPool *SafeMemPool,
   96  *                            PoolCount num_objects, size_t obj_size)
   97  *
   98  * Purpose: initialize a SafeMemPool object and allocate memory for it
   99  * Args:
  100  *   SafeMemPool - pointer to a SafeMemPool struct
  101  *   num_objects - number of items in this pool
  102  *   obj_size    - size of the items
  103  *
  104  * Returns:
  105  *   SAFE_MEM_SUCCESS
  106  *   SAFE_MEM_FAIL
  107  */
  108 
  109 int safe_mempool_init(SafeMemPool *mempool, uint64_t num_objects, size_t obj_size)
  110 {
  111     unsigned int i;
  112 
  113     if ((mempool == NULL) || (num_objects < 1) || (obj_size < 1))
  114         return SAFE_MEM_FAIL;
  115 
  116     mempool->obj_size = obj_size;
  117 
  118     /* this is the basis pool that represents all the *data pointers
  119      * in the list
  120      */
  121     mempool->datapool = calloc(num_objects, obj_size);
  122     if(mempool->datapool == NULL)
  123     {
  124         ErrorMessage("%s(%d) safe_mempool_init(): Failed to init datapool\n",
  125                 __FILE__, __LINE__);
  126         safe_mempool_free_pools(mempool);
  127         return SAFE_MEM_FAIL;
  128     }
  129 
  130     /* sets up the memory list */
  131     mempool->free_list = cbuffer_init(num_objects);
  132     if (!mempool->free_list)
  133     {
  134         ErrorMessage("%s(%d) safe_mempool_init(): Failed to init free list\n",
  135                 __FILE__, __LINE__);
  136         safe_mempool_free_pools(mempool);
  137         return SAFE_MEM_FAIL;
  138     }
  139 
  140     mempool->released_list = cbuffer_init(num_objects);
  141     if (!mempool->released_list)
  142     {
  143         ErrorMessage("%s(%d) safe_mempool_init(): "
  144                 "Failed to init release list\n", __FILE__, __LINE__);
  145         safe_mempool_free_pools(mempool);
  146         return SAFE_MEM_FAIL;
  147 
  148     }
  149 
  150     for(i=0; i<num_objects; i++)
  151     {
  152         void *data = ((char *) mempool->datapool) + (i * mempool->obj_size);
  153 
  154         if (cbuffer_write(mempool->free_list,  data))
  155         {
  156             ErrorMessage("%s(%d) safe_mempool_init(): "
  157                     "Failed to add to free list\n",
  158                     __FILE__, __LINE__);
  159             safe_mempool_free_pools(mempool);
  160             return SAFE_MEM_FAIL;
  161         }
  162         *(MagicType *)data = (uint64_t)FREE_MAGIC;
  163          mempool->total++;
  164     }
  165 
  166     return SAFE_MEM_SUCCESS;
  167 }
  168 
  169 
  170 
  171 /*
  172  * Destroy a set of SafeMemPool objects
  173  *
  174  * Args:
  175  *   SafeMemPool: pointer to a SafeMemPool struct
  176  *
  177  * Return:
  178  *   SAFE_MEM_SUCCESS
  179  *   SAFE_MEM_FAIL
  180  */
  181 int safe_mempool_destroy(SafeMemPool *mempool)
  182 {
  183     if(mempool == NULL)
  184         return SAFE_MEM_FAIL;
  185 
  186     safe_mempool_free_pools(mempool);
  187 
  188     return SAFE_MEM_SUCCESS;
  189 }
  190 
  191 
  192 /*
  193  * Allocate a new object from the SafeMemPool
  194  *
  195  * Args:
  196  *   SafeMemPool: pointer to a SafeMemPool struct
  197  *
  198  * Returns: a pointer to the SafeMemPool object on success, NULL on failure
  199  */
  200 
  201 void *safe_mempool_alloc(SafeMemPool *mempool)
  202 {
  203 
  204     void  *b = NULL;
  205 
  206     if(mempool == NULL)
  207     {
  208         return NULL;
  209     }
  210 
  211     if(cbuffer_read(mempool->free_list, &b))
  212     {
  213         if(cbuffer_read(mempool->released_list, &b))
  214         {
  215             return NULL;
  216         }
  217     }
  218 
  219     if (*(MagicType *)b != ((uint64_t)FREE_MAGIC))
  220     {
  221         ErrorMessage("%s(%d) safe_mempool_alloc(): Possible memory corruption! \n",
  222                 __FILE__, __LINE__);
  223     }
  224 
  225     DEBUG_WRAP(safe_mempool_verify(mempool););
  226 
  227     return b;
  228 }
  229 
  230 /*
  231  * Free a new object from the buffer
  232  * We use circular buffer to synchronize one reader and one writer
  233  *
  234  * Args:
  235  *   SafeMemPool: pointer to a circular buffer struct
  236  *   void *obj  : memory object
  237  *
  238  * Return:
  239  *   SAFE_MEM_SUCCESS
  240  *   SAFE_MEM_FAIL
  241  */
  242 static inline int _safe__mempool_remove(CircularBuffer *cb, void *obj)
  243 {
  244     if (obj == NULL)
  245         return SAFE_MEM_FAIL;
  246 
  247     if (*(MagicType *)obj == ((uint64_t)FREE_MAGIC))
  248     {
  249         DEBUG_WRAP(ErrorMessage("%s(%d) safe_mempool_remove(): Double free! \n",
  250                 __FILE__, __LINE__););
  251         return SAFE_MEM_FAIL;
  252     }
  253 
  254     if (cbuffer_write(cb, obj))
  255     {
  256         return SAFE_MEM_FAIL;
  257     }
  258 
  259     *(MagicType *)obj = (uint64_t)FREE_MAGIC;
  260 
  261     return SAFE_MEM_SUCCESS;
  262 }
  263 
  264 /*
  265  * Free a new object from the SafeMemPool
  266  *
  267  * Args:
  268  *   SafeMemPool: pointer to a SafeMemPool struct
  269  *   void *obj  : memory object
  270  *
  271  * Return:
  272  *   SAFE_MEM_SUCCESS
  273  *   SAFE_MEM_FAIL
  274  */
  275 
  276 int safe_mempool_free(SafeMemPool *mempool, void *obj)
  277 {
  278     int ret;
  279 
  280     assert(mempool);
  281 
  282     ret = _safe__mempool_remove(mempool->free_list, obj);
  283 
  284     DEBUG_WRAP(safe_mempool_verify(mempool););
  285 
  286     return ret;
  287 }
  288 
  289 /*
  290  * Release a new object from the SafeMemPool
  291  * This can be called by a different thread calling
  292  * safe_mempool_alloc()
  293  *  *
  294  * Args:
  295  *   SafeMemPool: pointer to a SafeMemPool struct
  296  *   void *obj  : memory object
  297  *
  298  * Return:
  299  *   SAFE_MEM_SUCCESS
  300  *   SAFE_MEM_FAIL
  301  */
  302 
  303 int safe_mempool_release(SafeMemPool *mempool, void *obj)
  304 {
  305     int ret;
  306 
  307     if (mempool == NULL)
  308         return SAFE_MEM_FAIL;
  309 
  310     /*A writer that might from different thread*/
  311     ret = _safe__mempool_remove(mempool->released_list, obj);
  312 
  313     DEBUG_WRAP(safe_mempool_verify(mempool););
  314 
  315     return ret;
  316 }
  317 
  318 /* Returns number of elements allocated in current buffer*/
  319 uint64_t safe_mempool_allocated(SafeMemPool *mempool)
  320 {
  321     uint64_t total_freed =
  322             safe_mempool_released(mempool) + safe_mempool_freed(mempool);
  323     return (mempool->total - total_freed);
  324 }
  325 
  326 /* Returns number of elements freed in current buffer*/
  327 uint64_t safe_mempool_freed(SafeMemPool *mempool)
  328 {
  329     return (cbuffer_used(mempool->free_list));
  330 }
  331 
  332 /* Returns number of elements released in current buffer*/
  333 uint64_t safe_mempool_released(SafeMemPool *mempool)
  334 {
  335     return (cbuffer_used(mempool->released_list));
  336 }
  337 
  338 
  339 
  340