Coverage Report

Created: 2023-01-17 06:24

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