Coverage Report

Created: 2026-06-08 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/htslib/cram/pooled_alloc.c
Line
Count
Source
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
#include "../htslib/hts_alloc.h"
41
42
//#define DISABLE_POOLED_ALLOC
43
//#define TEST_MAIN
44
45
#define PSIZE 1024*1024
46
47
// credit to http://graphics.stanford.edu/~seander/bithacks.html
48
155k
static int next_power_2(unsigned int v) {
49
155k
    v--;
50
155k
    v |= v >> 1;
51
155k
    v |= v >> 2;
52
155k
    v |= v >> 4;
53
155k
    v |= v >> 8;
54
155k
    v |= v >> 16;
55
155k
    v++;
56
57
155k
    return v;
58
155k
}
59
60
/*
61
 * Creates a pool.
62
 * Pool allocations are approx minimum of 1024*dsize or PSIZE.
63
 * (Assumes we're not trying to use pools for >= 2Gb or more)
64
 */
65
77.8k
pool_alloc_t *pool_create(size_t dsize) {
66
77.8k
    pool_alloc_t *p;
67
68
77.8k
    if (NULL == (p = (pool_alloc_t *)malloc(sizeof(*p))))
69
0
        return NULL;
70
71
    /* Minimum size is a pointer, for free list */
72
77.8k
    dsize = (dsize + sizeof(void *) - 1) & ~(sizeof(void *)-1);
73
77.8k
    if (dsize < sizeof(void *))
74
0
        dsize = sizeof(void *);
75
77.8k
    p->dsize = dsize;
76
77.8k
    p->psize = MIN(PSIZE, next_power_2(p->dsize*1024));
77
78
77.8k
    p->npools = 0;
79
77.8k
    p->pools = NULL;
80
77.8k
    p->free  = NULL;
81
82
77.8k
    return p;
83
77.8k
}
84
85
77.8k
void pool_destroy(pool_alloc_t *p) {
86
77.8k
    size_t i;
87
88
115k
    for (i = 0; i < p->npools; i++) {
89
37.5k
        free(p->pools[i].pool);
90
37.5k
    }
91
77.8k
    free(p->pools);
92
77.8k
    free(p);
93
77.8k
}
94
95
#ifndef DISABLE_POOLED_ALLOC
96
97
37.5k
static pool_t *new_pool(pool_alloc_t *p) {
98
37.5k
    size_t n = p->psize / p->dsize;
99
37.5k
    pool_t *pool;
100
101
37.5k
    pool = hts_realloc_ps(p->pools, sizeof(*p->pools), p->npools, 1);
102
37.5k
    if (NULL == pool) return NULL;
103
37.5k
    p->pools = pool;
104
37.5k
    pool = &p->pools[p->npools];
105
106
37.5k
    pool->pool = hts_malloc_p(p->dsize, n);
107
37.5k
    if (NULL == pool->pool) return NULL;
108
109
37.5k
    pool->used = 0;
110
111
37.5k
    p->npools++;
112
113
37.5k
    return pool;
114
37.5k
}
115
116
6.38M
void *pool_alloc(pool_alloc_t *p) {
117
6.38M
    pool_t *pool;
118
6.38M
    void *ret;
119
120
    /* Look on free list */
121
6.38M
    if (NULL != p->free) {
122
0
        ret = p->free;
123
0
        p->free = *((void **)p->free);
124
0
        return ret;
125
0
    }
126
127
    /* Look for space in the last pool */
128
6.38M
    if (p->npools) {
129
6.35M
        pool = &p->pools[p->npools - 1];
130
6.35M
        if (pool->used + p->dsize < p->psize) {
131
6.35M
            ret = ((char *) pool->pool) + pool->used;
132
6.35M
            pool->used += p->dsize;
133
6.35M
            return ret;
134
6.35M
        }
135
6.35M
    }
136
137
    /* Need a new pool */
138
37.5k
    pool = new_pool(p);
139
37.5k
    if (NULL == pool) return NULL;
140
141
37.5k
    pool->used = p->dsize;
142
37.5k
    return pool->pool;
143
37.5k
}
144
145
796k
void pool_free(pool_alloc_t *p, void *ptr) {
146
796k
    *(void **)ptr = p->free;
147
796k
    p->free = ptr;
148
796k
}
149
150
#else
151
152
void *pool_alloc(pool_alloc_t *p) {
153
    return malloc(p->dsize);
154
}
155
156
void pool_free(pool_alloc_t *p, void *ptr) {
157
    free(ptr);
158
}
159
160
#endif
161
162
#ifdef TEST_MAIN
163
typedef struct {
164
    int x, y, z;
165
} xyz;
166
167
#define NP 10000
168
int main(void) {
169
    int i;
170
    xyz *item;
171
    xyz **items;
172
    pool_alloc_t *p = pool_create(sizeof(xyz));
173
174
    items = (xyz **)malloc(NP * sizeof(*items));
175
176
    for (i = 0; i < NP; i++) {
177
        item = pool_alloc(p);
178
        item->x = i;
179
        item->y = i+1;
180
        item->z = i+2;
181
        items[i] = item;
182
    }
183
184
    for (i = 0; i < NP; i++) {
185
        item = items[i];
186
        if (i % 3)
187
            pool_free(p, item);
188
    }
189
190
    for (i = 0; i < NP; i++) {
191
        item = pool_alloc(p);
192
        item->x = 1000000+i;
193
        item->y = 1000000+i+1;
194
        item->z = 1000000+i+2;
195
    }
196
197
    for (i = 0; i < NP; i++) {
198
        item = items[i];
199
        printf("%d\t%d\t%d\t%d\n", i, item->x, item->y, item->z);
200
        pool_free(p, item);
201
    }
202
203
    free(items);
204
    return 0;
205
}
206
#endif