File Coverage

deps/libgit2/src/pool.c
Criterion Covered Total %
statement 80 95 84.2
branch 34 68 50.0
condition n/a
subroutine n/a
pod n/a
total 114 163 69.9


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
4             * This file is part of libgit2, distributed under the GNU GPL v2 with
5             * a Linking Exception. For full terms see the included COPYING file.
6             */
7              
8             #include "pool.h"
9              
10             #include "posix.h"
11             #ifndef GIT_WIN32
12             #include
13             #endif
14              
15             struct git_pool_page {
16             git_pool_page *next;
17             size_t size;
18             size_t avail;
19             GIT_ALIGN(char data[GIT_FLEX_ARRAY], 8);
20             };
21              
22             static void *pool_alloc_page(git_pool *pool, size_t size);
23              
24 3628           size_t git_pool__system_page_size(void)
25             {
26             static size_t size = 0;
27              
28 3628 100         if (!size) {
29             size_t page_size;
30 27 50         if (git__page_size(&page_size) < 0)
31 0           page_size = 4096;
32             /* allow space for malloc overhead */
33 27           size = (page_size - (2 * sizeof(void *)) - sizeof(git_pool_page));
34             }
35              
36 3628           return size;
37             }
38              
39             #ifndef GIT_DEBUG_POOL
40 3628           void git_pool_init(git_pool *pool, size_t item_size)
41             {
42 3628 50         assert(pool);
43 3628 50         assert(item_size >= 1);
44              
45 3628           memset(pool, 0, sizeof(git_pool));
46 3628           pool->item_size = item_size;
47 3628           pool->page_size = git_pool__system_page_size();
48 3628           }
49              
50 4124           void git_pool_clear(git_pool *pool)
51             {
52             git_pool_page *scan, *next;
53              
54 5421 100         for (scan = pool->pages; scan != NULL; scan = next) {
55 1297           next = scan->next;
56 1297           git__free(scan);
57             }
58              
59 4124           pool->pages = NULL;
60 4124           }
61              
62 1297           static void *pool_alloc_page(git_pool *pool, size_t size)
63             {
64             git_pool_page *page;
65 1297           const size_t new_page_size = (size <= pool->page_size) ? pool->page_size : size;
66             size_t alloc_size;
67              
68 1297 50         if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) ||
    50          
69 1297           !(page = git__malloc(alloc_size)))
70 0           return NULL;
71              
72 1297           page->size = new_page_size;
73 1297           page->avail = new_page_size - size;
74 1297           page->next = pool->pages;
75              
76 1297           pool->pages = page;
77              
78 1297           return page->data;
79             }
80              
81 4074           static void *pool_alloc(git_pool *pool, size_t size)
82             {
83 4074           git_pool_page *page = pool->pages;
84 4074           void *ptr = NULL;
85              
86 4074 100         if (!page || page->avail < size)
    50          
87 1297           return pool_alloc_page(pool, size);
88              
89 2777           ptr = &page->data[page->size - page->avail];
90 2777           page->avail -= size;
91              
92 2777           return ptr;
93             }
94              
95 0           uint32_t git_pool__open_pages(git_pool *pool)
96             {
97 0           uint32_t ct = 0;
98             git_pool_page *scan;
99 0 0         for (scan = pool->pages; scan != NULL; scan = scan->next) ct++;
100 0           return ct;
101             }
102              
103 0           bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
104             {
105             git_pool_page *scan;
106 0 0         for (scan = pool->pages; scan != NULL; scan = scan->next)
107 0 0         if ((void *)scan->data <= ptr &&
    0          
108 0           (void *)(((char *)scan->data) + scan->size) > ptr)
109 0           return true;
110 0           return false;
111             }
112              
113             #else
114              
115             static int git_pool__ptr_cmp(const void * a, const void * b)
116             {
117             if(a > b) {
118             return 1;
119             }
120             if(a < b) {
121             return -1;
122             }
123             else {
124             return 0;
125             }
126             }
127              
128             void git_pool_init(git_pool *pool, size_t item_size)
129             {
130             assert(pool);
131             assert(item_size >= 1);
132              
133             memset(pool, 0, sizeof(git_pool));
134             pool->item_size = item_size;
135             pool->page_size = git_pool__system_page_size();
136             git_vector_init(&pool->allocations, 100, git_pool__ptr_cmp);
137             }
138              
139             void git_pool_clear(git_pool *pool)
140             {
141             git_vector_free_deep(&pool->allocations);
142             }
143              
144             static void *pool_alloc(git_pool *pool, size_t size) {
145             void *ptr = NULL;
146             if((ptr = git__malloc(size)) == NULL) {
147             return NULL;
148             }
149             git_vector_insert_sorted(&pool->allocations, ptr, NULL);
150             return ptr;
151             }
152              
153             bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
154             {
155             size_t pos;
156             return git_vector_bsearch(&pos, &pool->allocations, ptr) != GIT_ENOTFOUND;
157             }
158             #endif
159              
160 4           void git_pool_swap(git_pool *a, git_pool *b)
161             {
162             git_pool temp;
163              
164 4 50         if (a == b)
165 0           return;
166              
167 4           memcpy(&temp, a, sizeof(temp));
168 4           memcpy(a, b, sizeof(temp));
169 4           memcpy(b, &temp, sizeof(temp));
170             }
171              
172 4074           static size_t alloc_size(git_pool *pool, size_t count)
173             {
174 4074           const size_t align = sizeof(void *) - 1;
175              
176 4074 100         if (pool->item_size > 1) {
177 1202           const size_t item_size = (pool->item_size + align) & ~align;
178 1202           return item_size * count;
179             }
180              
181 2872           return (count + align) & ~align;
182             }
183              
184 3574           void *git_pool_malloc(git_pool *pool, size_t items)
185             {
186 3574           return pool_alloc(pool, alloc_size(pool, items));
187             }
188              
189 500           void *git_pool_mallocz(git_pool *pool, size_t items)
190             {
191 500           const size_t size = alloc_size(pool, items);
192 500           void *ptr = pool_alloc(pool, size);
193 500 50         if (ptr)
194 500           memset(ptr, 0x0, size);
195 500           return ptr;
196             }
197              
198 1404           char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
199             {
200 1404           char *ptr = NULL;
201              
202 1404 50         assert(pool && str && pool->item_size == sizeof(char));
    50          
    50          
203              
204 1404 50         if (n == SIZE_MAX)
205 0           return NULL;
206              
207 1404 50         if ((ptr = git_pool_malloc(pool, (n + 1))) != NULL) {
208 1404           memcpy(ptr, str, n);
209 1404           ptr[n] = '\0';
210             }
211              
212 1404           return ptr;
213             }
214              
215 610           char *git_pool_strdup(git_pool *pool, const char *str)
216             {
217 610 50         assert(pool && str && pool->item_size == sizeof(char));
    50          
    50          
218 610           return git_pool_strndup(pool, str, strlen(str));
219             }
220              
221 8           char *git_pool_strdup_safe(git_pool *pool, const char *str)
222             {
223 8 50         return str ? git_pool_strdup(pool, str) : NULL;
224             }
225              
226 6           char *git_pool_strcat(git_pool *pool, const char *a, const char *b)
227             {
228             void *ptr;
229             size_t len_a, len_b, total;
230              
231 6 50         assert(pool && pool->item_size == sizeof(char));
    50          
232              
233 6 50         len_a = a ? strlen(a) : 0;
234 6 50         len_b = b ? strlen(b) : 0;
235              
236 12 50         if (GIT_ADD_SIZET_OVERFLOW(&total, len_a, len_b) ||
    50          
237 6           GIT_ADD_SIZET_OVERFLOW(&total, total, 1))
238 0           return NULL;
239              
240 6 50         if ((ptr = git_pool_malloc(pool, total)) != NULL) {
241 6 50         if (len_a)
242 6           memcpy(ptr, a, len_a);
243 6 50         if (len_b)
244 6           memcpy(((char *)ptr) + len_a, b, len_b);
245 6           *(((char *)ptr) + len_a + len_b) = '\0';
246             }
247 6           return ptr;
248             }