Coverage Report

Created: 2025-10-10 07:28

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
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
108k
static int next_power_2(unsigned int v) {
48
108k
    v--;
49
108k
    v |= v >> 1;
50
108k
    v |= v >> 2;
51
108k
    v |= v >> 4;
52
108k
    v |= v >> 8;
53
108k
    v |= v >> 16;
54
108k
    v++;
55
56
108k
    return v;
57
108k
}
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
54.1k
pool_alloc_t *pool_create(size_t dsize) {
65
54.1k
    pool_alloc_t *p;
66
67
54.1k
    if (NULL == (p = (pool_alloc_t *)malloc(sizeof(*p))))
68
0
        return NULL;
69
70
    /* Minimum size is a pointer, for free list */
71
54.1k
    dsize = (dsize + sizeof(void *) - 1) & ~(sizeof(void *)-1);
72
54.1k
    if (dsize < sizeof(void *))
73
0
        dsize = sizeof(void *);
74
54.1k
    p->dsize = dsize;
75
54.1k
    p->psize = MIN(PSIZE, next_power_2(p->dsize*1024));
76
77
54.1k
    p->npools = 0;
78
54.1k
    p->pools = NULL;
79
54.1k
    p->free  = NULL;
80
81
54.1k
    return p;
82
54.1k
}
83
84
54.1k
void pool_destroy(pool_alloc_t *p) {
85
54.1k
    size_t i;
86
87
80.4k
    for (i = 0; i < p->npools; i++) {
88
26.2k
        free(p->pools[i].pool);
89
26.2k
    }
90
54.1k
    free(p->pools);
91
54.1k
    free(p);
92
54.1k
}
93
94
#ifndef DISABLE_POOLED_ALLOC
95
96
26.2k
static pool_t *new_pool(pool_alloc_t *p) {
97
26.2k
    size_t n = p->psize / p->dsize;
98
26.2k
    pool_t *pool;
99
100
26.2k
    pool = realloc(p->pools, (p->npools + 1) * sizeof(*p->pools));
101
26.2k
    if (NULL == pool) return NULL;
102
26.2k
    p->pools = pool;
103
26.2k
    pool = &p->pools[p->npools];
104
105
26.2k
    pool->pool = malloc(n * p->dsize);
106
26.2k
    if (NULL == pool->pool) return NULL;
107
108
26.2k
    pool->used = 0;
109
110
26.2k
    p->npools++;
111
112
26.2k
    return pool;
113
26.2k
}
114
115
1.34M
void *pool_alloc(pool_alloc_t *p) {
116
1.34M
    pool_t *pool;
117
1.34M
    void *ret;
118
119
    /* Look on free list */
120
1.34M
    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.34M
    if (p->npools) {
128
1.32M
        pool = &p->pools[p->npools - 1];
129
1.32M
        if (pool->used + p->dsize < p->psize) {
130
1.31M
            ret = ((char *) pool->pool) + pool->used;
131
1.31M
            pool->used += p->dsize;
132
1.31M
            return ret;
133
1.31M
        }
134
1.32M
    }
135
136
    /* Need a new pool */
137
26.2k
    pool = new_pool(p);
138
26.2k
    if (NULL == pool) return NULL;
139
140
26.2k
    pool->used = p->dsize;
141
26.2k
    return pool->pool;
142
26.2k
}
143
144
217k
void pool_free(pool_alloc_t *p, void *ptr) {
145
217k
    *(void **)ptr = p->free;
146
217k
    p->free = ptr;
147
217k
}
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