/src/htslib/cram/pooled_alloc.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  | Copyright (c) 2009, 2013, 2015, 2018-2019 Genome Research Ltd. | 
| 3 |  | Author: Rob Davies <rmd@sanger.ac.uk> | 
| 4 |  |  | 
| 5 |  | Redistribution and use in source and binary forms, with or without | 
| 6 |  | modification, are permitted provided that the following conditions are met: | 
| 7 |  |  | 
| 8 |  |    1. Redistributions of source code must retain the above copyright notice, | 
| 9 |  | this list of conditions and the following disclaimer. | 
| 10 |  |  | 
| 11 |  |    2. Redistributions in binary form must reproduce the above copyright notice, | 
| 12 |  | this list of conditions and the following disclaimer in the documentation | 
| 13 |  | and/or other materials provided with the distribution. | 
| 14 |  |  | 
| 15 |  |    3. Neither the names Genome Research Ltd and Wellcome Trust Sanger | 
| 16 |  | Institute nor the names of its contributors may be used to endorse or promote | 
| 17 |  | products derived from this software without specific prior written permission. | 
| 18 |  |  | 
| 19 |  | THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS IS" AND | 
| 20 |  | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
| 21 |  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
| 22 |  | DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH LTD OR CONTRIBUTORS BE LIABLE | 
| 23 |  | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
| 24 |  | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
| 25 |  | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
| 26 |  | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
| 27 |  | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 28 |  | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 29 |  | */ | 
| 30 |  |  | 
| 31 |  | #define HTS_BUILDING_LIBRARY // Enables HTSLIB_EXPORT, see htslib/hts_defs.h | 
| 32 |  | #include <config.h> | 
| 33 |  |  | 
| 34 |  | #include <stdlib.h> | 
| 35 |  | #include <stdio.h> | 
| 36 |  | #include <stdint.h> | 
| 37 |  |  | 
| 38 |  | #include "pooled_alloc.h" | 
| 39 |  | #include "misc.h" | 
| 40 |  |  | 
| 41 |  | //#define DISABLE_POOLED_ALLOC | 
| 42 |  | //#define TEST_MAIN | 
| 43 |  |  | 
| 44 |  | #define PSIZE 1024*1024 | 
| 45 |  |  | 
| 46 |  | // credit to http://graphics.stanford.edu/~seander/bithacks.html | 
| 47 | 7.36k | static int next_power_2(unsigned int v) { | 
| 48 | 7.36k |     v--; | 
| 49 | 7.36k |     v |= v >> 1; | 
| 50 | 7.36k |     v |= v >> 2; | 
| 51 | 7.36k |     v |= v >> 4; | 
| 52 | 7.36k |     v |= v >> 8; | 
| 53 | 7.36k |     v |= v >> 16; | 
| 54 | 7.36k |     v++; | 
| 55 |  |  | 
| 56 | 7.36k |     return v; | 
| 57 | 7.36k | } | 
| 58 |  |  | 
| 59 |  | /* | 
| 60 |  |  * Creates a pool. | 
| 61 |  |  * Pool allocations are approx minimum of 1024*dsize or PSIZE. | 
| 62 |  |  * (Assumes we're not trying to use pools for >= 2Gb or more) | 
| 63 |  |  */ | 
| 64 | 3.68k | pool_alloc_t *pool_create(size_t dsize) { | 
| 65 | 3.68k |     pool_alloc_t *p; | 
| 66 |  |  | 
| 67 | 3.68k |     if (NULL == (p = (pool_alloc_t *)malloc(sizeof(*p)))) | 
| 68 | 0 |         return NULL; | 
| 69 |  |  | 
| 70 |  |     /* Minimum size is a pointer, for free list */ | 
| 71 | 3.68k |     dsize = (dsize + sizeof(void *) - 1) & ~(sizeof(void *)-1); | 
| 72 | 3.68k |     if (dsize < sizeof(void *)) | 
| 73 | 0 |         dsize = sizeof(void *); | 
| 74 | 3.68k |     p->dsize = dsize; | 
| 75 | 3.68k |     p->psize = MIN(PSIZE, next_power_2(p->dsize*1024)); | 
| 76 |  |  | 
| 77 | 3.68k |     p->npools = 0; | 
| 78 | 3.68k |     p->pools = NULL; | 
| 79 | 3.68k |     p->free  = NULL; | 
| 80 |  |  | 
| 81 | 3.68k |     return p; | 
| 82 | 3.68k | } | 
| 83 |  |  | 
| 84 | 3.68k | void pool_destroy(pool_alloc_t *p) { | 
| 85 | 3.68k |     size_t i; | 
| 86 |  |  | 
| 87 | 6.54k |     for (i = 0; i < p->npools; i++) { | 
| 88 | 2.86k |         free(p->pools[i].pool); | 
| 89 | 2.86k |     } | 
| 90 | 3.68k |     free(p->pools); | 
| 91 | 3.68k |     free(p); | 
| 92 | 3.68k | } | 
| 93 |  |  | 
| 94 |  | #ifndef DISABLE_POOLED_ALLOC | 
| 95 |  |  | 
| 96 | 2.86k | static pool_t *new_pool(pool_alloc_t *p) { | 
| 97 | 2.86k |     size_t n = p->psize / p->dsize; | 
| 98 | 2.86k |     pool_t *pool; | 
| 99 |  |  | 
| 100 | 2.86k |     pool = realloc(p->pools, (p->npools + 1) * sizeof(*p->pools)); | 
| 101 | 2.86k |     if (NULL == pool) return NULL; | 
| 102 | 2.86k |     p->pools = pool; | 
| 103 | 2.86k |     pool = &p->pools[p->npools]; | 
| 104 |  |  | 
| 105 | 2.86k |     pool->pool = malloc(n * p->dsize); | 
| 106 | 2.86k |     if (NULL == pool->pool) return NULL; | 
| 107 |  |  | 
| 108 | 2.86k |     pool->used = 0; | 
| 109 |  |  | 
| 110 | 2.86k |     p->npools++; | 
| 111 |  |  | 
| 112 | 2.86k |     return pool; | 
| 113 | 2.86k | } | 
| 114 |  |  | 
| 115 | 1.19M | void *pool_alloc(pool_alloc_t *p) { | 
| 116 | 1.19M |     pool_t *pool; | 
| 117 | 1.19M |     void *ret; | 
| 118 |  |  | 
| 119 |  |     /* Look on free list */ | 
| 120 | 1.19M |     if (NULL != p->free) { | 
| 121 | 0 |         ret = p->free; | 
| 122 | 0 |         p->free = *((void **)p->free); | 
| 123 | 0 |         return ret; | 
| 124 | 0 |     } | 
| 125 |  |  | 
| 126 |  |     /* Look for space in the last pool */ | 
| 127 | 1.19M |     if (p->npools) { | 
| 128 | 1.19M |         pool = &p->pools[p->npools - 1]; | 
| 129 | 1.19M |         if (pool->used + p->dsize < p->psize) { | 
| 130 | 1.19M |             ret = ((char *) pool->pool) + pool->used; | 
| 131 | 1.19M |             pool->used += p->dsize; | 
| 132 | 1.19M |             return ret; | 
| 133 | 1.19M |         } | 
| 134 | 1.19M |     } | 
| 135 |  |  | 
| 136 |  |     /* Need a new pool */ | 
| 137 | 2.86k |     pool = new_pool(p); | 
| 138 | 2.86k |     if (NULL == pool) return NULL; | 
| 139 |  |  | 
| 140 | 2.86k |     pool->used = p->dsize; | 
| 141 | 2.86k |     return pool->pool; | 
| 142 | 2.86k | } | 
| 143 |  |  | 
| 144 | 0 | void pool_free(pool_alloc_t *p, void *ptr) { | 
| 145 | 0 |     *(void **)ptr = p->free; | 
| 146 | 0 |     p->free = ptr; | 
| 147 | 0 | } | 
| 148 |  |  | 
| 149 |  | #else | 
| 150 |  |  | 
| 151 |  | void *pool_alloc(pool_alloc_t *p) { | 
| 152 |  |     return malloc(p->dsize); | 
| 153 |  | } | 
| 154 |  |  | 
| 155 |  | void pool_free(pool_alloc_t *p, void *ptr) { | 
| 156 |  |     free(ptr); | 
| 157 |  | } | 
| 158 |  |  | 
| 159 |  | #endif | 
| 160 |  |  | 
| 161 |  | #ifdef TEST_MAIN | 
| 162 |  | typedef struct { | 
| 163 |  |     int x, y, z; | 
| 164 |  | } xyz; | 
| 165 |  |  | 
| 166 |  | #define NP 10000 | 
| 167 |  | int main(void) { | 
| 168 |  |     int i; | 
| 169 |  |     xyz *item; | 
| 170 |  |     xyz **items; | 
| 171 |  |     pool_alloc_t *p = pool_create(sizeof(xyz)); | 
| 172 |  |  | 
| 173 |  |     items = (xyz **)malloc(NP * sizeof(*items)); | 
| 174 |  |  | 
| 175 |  |     for (i = 0; i < NP; i++) { | 
| 176 |  |         item = pool_alloc(p); | 
| 177 |  |         item->x = i; | 
| 178 |  |         item->y = i+1; | 
| 179 |  |         item->z = i+2; | 
| 180 |  |         items[i] = item; | 
| 181 |  |     } | 
| 182 |  |  | 
| 183 |  |     for (i = 0; i < NP; i++) { | 
| 184 |  |         item = items[i]; | 
| 185 |  |         if (i % 3) | 
| 186 |  |             pool_free(p, item); | 
| 187 |  |     } | 
| 188 |  |  | 
| 189 |  |     for (i = 0; i < NP; i++) { | 
| 190 |  |         item = pool_alloc(p); | 
| 191 |  |         item->x = 1000000+i; | 
| 192 |  |         item->y = 1000000+i+1; | 
| 193 |  |         item->z = 1000000+i+2; | 
| 194 |  |     } | 
| 195 |  |  | 
| 196 |  |     for (i = 0; i < NP; i++) { | 
| 197 |  |         item = items[i]; | 
| 198 |  |         printf("%d\t%d\t%d\t%d\n", i, item->x, item->y, item->z); | 
| 199 |  |         pool_free(p, item); | 
| 200 |  |     } | 
| 201 |  |  | 
| 202 |  |     free(items); | 
| 203 |  |     return 0; | 
| 204 |  | } | 
| 205 |  | #endif |