LCOV - code coverage report
Current view: top level - tommyds/tommyds - tommyalloc.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 57 57 100.0 %
Date: 2018-04-02 17:50:51 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved.
       3             :  *
       4             :  * Redistribution and use in source and binary forms, with or without
       5             :  * modification, are permitted provided that the following conditions
       6             :  * are met:
       7             :  *
       8             :  * 1. Redistributions of source code must retain the above copyright
       9             :  *    notice, this list of conditions and the following disclaimer.
      10             :  *
      11             :  * 2. Redistributions in binary form must reproduce the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer in the
      13             :  *    documentation and/or other materials provided with the distribution.
      14             :  *
      15             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      16             :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      17             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      18             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      19             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      20             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      21             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      22             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      23             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      24             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      25             :  * POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : 
      28             : #include "tommyalloc.h"
      29             : 
      30             : /******************************************************************************/
      31             : /* allocator */
      32             : 
      33             : /**
      34             :  * Basic allocation segment.
      35             :  * Smaller of a memory page, to allow also a little heap overread.
      36             :  * The heap manager may put it in a single memory page.
      37             :  */
      38             : #define TOMMY_ALLOCATOR_BLOCK_SIZE (4096 - 64)
      39             : 
      40           5 : void tommy_allocator_init(tommy_allocator* alloc, tommy_size_t block_size, tommy_size_t align_size)
      41             : {
      42             :         /* setup the minimal alignment */
      43           5 :         if (align_size < sizeof(void*))
      44           1 :                 align_size = sizeof(void*);
      45             : 
      46             :         /* ensure that the block_size keeps the alignment */
      47           5 :         if (block_size % align_size != 0)
      48           1 :                 block_size += align_size - block_size % align_size;
      49             : 
      50           5 :         alloc->block_size = block_size;
      51           5 :         alloc->align_size = align_size;
      52             : 
      53           5 :         alloc->count = 0;
      54           5 :         alloc->free_block = 0;
      55           5 :         alloc->used_segment = 0;
      56           5 : }
      57             : 
      58             : /**
      59             :  * Reset the allocator and free all.
      60             :  */
      61           5 : static void allocator_reset(tommy_allocator* alloc)
      62             : {
      63           5 :         tommy_allocator_entry* block = alloc->used_segment;
      64             : 
      65      170519 :         while (block) {
      66      170509 :                 tommy_allocator_entry* block_next = block->next;
      67      170509 :                 tommy_free(block);
      68      170509 :                 block = block_next;
      69             :         }
      70             : 
      71           5 :         alloc->count = 0;
      72           5 :         alloc->free_block = 0;
      73           5 :         alloc->used_segment = 0;
      74           5 : }
      75             : 
      76           5 : void tommy_allocator_done(tommy_allocator* alloc)
      77             : {
      78           5 :         allocator_reset(alloc);
      79           5 : }
      80             : 
      81    10571435 : void* tommy_allocator_alloc(tommy_allocator* alloc)
      82             : {
      83             :         void* ptr;
      84             : 
      85             :         /* if no free block available */
      86    10571435 :         if (!alloc->free_block) {
      87             :                 tommy_uintptr_t off, mis;
      88             :                 tommy_size_t size;
      89             :                 char* data;
      90             :                 tommy_allocator_entry* segment;
      91             : 
      92             :                 /* default allocation size */
      93      170509 :                 size = TOMMY_ALLOCATOR_BLOCK_SIZE;
      94             : 
      95             :                 /* ensure that we can allocate at least one block */
      96      170509 :                 if (size < sizeof(tommy_allocator_entry) + alloc->align_size + alloc->block_size)
      97           1 :                         size = sizeof(tommy_allocator_entry) + alloc->align_size + alloc->block_size;
      98             : 
      99      170509 :                 data = tommy_cast(char*, tommy_malloc(size));
     100      170509 :                 segment = (tommy_allocator_entry*)data;
     101             : 
     102             :                 /* put in the segment list */
     103      170509 :                 segment->next = alloc->used_segment;
     104      170509 :                 alloc->used_segment = segment;
     105      170509 :                 data += sizeof(tommy_allocator_entry);
     106             : 
     107             :                 /* align if not aligned */
     108      170509 :                 off = (tommy_uintptr_t)data;
     109      170509 :                 mis = off % alloc->align_size;
     110      170509 :                 if (mis != 0) {
     111      170509 :                         data += alloc->align_size - mis;
     112      170509 :                         size -= alloc->align_size - mis;
     113             :                 }
     114             : 
     115             :                 /* insert in free list */
     116             :                 do {
     117    10571497 :                         tommy_allocator_entry* free_block = (tommy_allocator_entry*)data;
     118    10571497 :                         free_block->next = alloc->free_block;
     119    10571497 :                         alloc->free_block = free_block;
     120             : 
     121    10571497 :                         data += alloc->block_size;
     122    10571497 :                         size -= alloc->block_size;
     123    10571497 :                 } while (size >= alloc->block_size);
     124             :         }
     125             : 
     126             :         /* remove one from the free list */
     127    10571435 :         ptr = alloc->free_block;
     128    10571435 :         alloc->free_block = alloc->free_block->next;
     129             : 
     130    10571435 :         ++alloc->count;
     131             : 
     132    10571435 :         return ptr;
     133             : }
     134             : 
     135    10571434 : void tommy_allocator_free(tommy_allocator* alloc, void* ptr)
     136             : {
     137    10571434 :         tommy_allocator_entry* free_block = tommy_cast(tommy_allocator_entry*, ptr);
     138             : 
     139             :         /* put it in the free list */
     140    10571434 :         free_block->next = alloc->free_block;
     141    10571434 :         alloc->free_block = free_block;
     142             : 
     143    10571434 :         --alloc->count;
     144    10571434 : }
     145             : 
     146           1 : tommy_size_t tommy_allocator_memory_usage(tommy_allocator* alloc)
     147             : {
     148           1 :         return alloc->count * (tommy_size_t)alloc->block_size;
     149             : }
     150             : 

Generated by: LCOV version 1.13