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 3992           static size_t pool_system_page_size(void)
25             {
26             static size_t size = 0;
27              
28 3992 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 3992           return size;
37             }
38              
39             #ifndef GIT_DEBUG_POOL
40 3992           int git_pool_init(git_pool *pool, size_t item_size)
41             {
42 3992 50         assert(pool);
43 3992 50         assert(item_size >= 1);
44              
45 3992           memset(pool, 0, sizeof(git_pool));
46 3992           pool->item_size = item_size;
47 3992           pool->page_size = pool_system_page_size();
48              
49 3992           return 0;
50             }
51              
52 4466           void git_pool_clear(git_pool *pool)
53             {
54             git_pool_page *scan, *next;
55              
56 5764 100         for (scan = pool->pages; scan != NULL; scan = next) {
57 1298           next = scan->next;
58 1298           git__free(scan);
59             }
60              
61 4466           pool->pages = NULL;
62 4466           }
63              
64 1298           static void *pool_alloc_page(git_pool *pool, size_t size)
65             {
66             git_pool_page *page;
67 1298           const size_t new_page_size = (size <= pool->page_size) ? pool->page_size : size;
68             size_t alloc_size;
69              
70 1298 50         if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) ||
    50          
71 1298           !(page = git__malloc(alloc_size)))
72 0           return NULL;
73              
74 1298           page->size = new_page_size;
75 1298           page->avail = new_page_size - size;
76 1298           page->next = pool->pages;
77              
78 1298           pool->pages = page;
79              
80 1298           return page->data;
81             }
82              
83 4076           static void *pool_alloc(git_pool *pool, size_t size)
84             {
85 4076           git_pool_page *page = pool->pages;
86 4076           void *ptr = NULL;
87              
88 4076 100         if (!page || page->avail < size)
    50          
89 1298           return pool_alloc_page(pool, size);
90              
91 2778           ptr = &page->data[page->size - page->avail];
92 2778           page->avail -= size;
93              
94 2778           return ptr;
95             }
96              
97 0           uint32_t git_pool__open_pages(git_pool *pool)
98             {
99 0           uint32_t ct = 0;
100             git_pool_page *scan;
101 0 0         for (scan = pool->pages; scan != NULL; scan = scan->next) ct++;
102 0           return ct;
103             }
104              
105 0           bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
106             {
107             git_pool_page *scan;
108 0 0         for (scan = pool->pages; scan != NULL; scan = scan->next)
109 0 0         if ((void *)scan->data <= ptr &&
    0          
110 0           (void *)(((char *)scan->data) + scan->size) > ptr)
111 0           return true;
112 0           return false;
113             }
114              
115             #else
116              
117             static int git_pool__ptr_cmp(const void * a, const void * b)
118             {
119             if(a > b) {
120             return 1;
121             }
122             if(a < b) {
123             return -1;
124             }
125             else {
126             return 0;
127             }
128             }
129              
130             int git_pool_init(git_pool *pool, size_t item_size)
131             {
132             assert(pool);
133             assert(item_size >= 1);
134              
135             memset(pool, 0, sizeof(git_pool));
136             pool->item_size = item_size;
137             pool->page_size = git_pool__system_page_size();
138             git_vector_init(&pool->allocations, 100, git_pool__ptr_cmp);
139              
140             return 0;
141             }
142              
143             void git_pool_clear(git_pool *pool)
144             {
145             git_vector_free_deep(&pool->allocations);
146             }
147              
148             static void *pool_alloc(git_pool *pool, size_t size) {
149             void *ptr = NULL;
150             if((ptr = git__malloc(size)) == NULL) {
151             return NULL;
152             }
153             git_vector_insert_sorted(&pool->allocations, ptr, NULL);
154             return ptr;
155             }
156              
157             bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
158             {
159             size_t pos;
160             return git_vector_bsearch(&pos, &pool->allocations, ptr) != GIT_ENOTFOUND;
161             }
162             #endif
163              
164 4           void git_pool_swap(git_pool *a, git_pool *b)
165             {
166             git_pool temp;
167              
168 4 50         if (a == b)
169 0           return;
170              
171 4           memcpy(&temp, a, sizeof(temp));
172 4           memcpy(a, b, sizeof(temp));
173 4           memcpy(b, &temp, sizeof(temp));
174             }
175              
176 4076           static size_t alloc_size(git_pool *pool, size_t count)
177             {
178 4076           const size_t align = sizeof(void *) - 1;
179              
180 4076 100         if (pool->item_size > 1) {
181 1204           const size_t item_size = (pool->item_size + align) & ~align;
182 1204           return item_size * count;
183             }
184              
185 2872           return (count + align) & ~align;
186             }
187              
188 3574           void *git_pool_malloc(git_pool *pool, size_t items)
189             {
190 3574           return pool_alloc(pool, alloc_size(pool, items));
191             }
192              
193 502           void *git_pool_mallocz(git_pool *pool, size_t items)
194             {
195 502           const size_t size = alloc_size(pool, items);
196 502           void *ptr = pool_alloc(pool, size);
197 502 50         if (ptr)
198 502           memset(ptr, 0x0, size);
199 502           return ptr;
200             }
201              
202 1404           char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
203             {
204 1404           char *ptr = NULL;
205              
206 1404 50         assert(pool && str && pool->item_size == sizeof(char));
    50          
    50          
207              
208 1404 50         if (n == SIZE_MAX)
209 0           return NULL;
210              
211 1404 50         if ((ptr = git_pool_malloc(pool, (n + 1))) != NULL) {
212 1404           memcpy(ptr, str, n);
213 1404           ptr[n] = '\0';
214             }
215              
216 1404           return ptr;
217             }
218              
219 610           char *git_pool_strdup(git_pool *pool, const char *str)
220             {
221 610 50         assert(pool && str && pool->item_size == sizeof(char));
    50          
    50          
222 610           return git_pool_strndup(pool, str, strlen(str));
223             }
224              
225 8           char *git_pool_strdup_safe(git_pool *pool, const char *str)
226             {
227 8 50         return str ? git_pool_strdup(pool, str) : NULL;
228             }
229              
230 6           char *git_pool_strcat(git_pool *pool, const char *a, const char *b)
231             {
232             void *ptr;
233             size_t len_a, len_b, total;
234              
235 6 50         assert(pool && pool->item_size == sizeof(char));
    50          
236              
237 6 50         len_a = a ? strlen(a) : 0;
238 6 50         len_b = b ? strlen(b) : 0;
239              
240 12 50         if (GIT_ADD_SIZET_OVERFLOW(&total, len_a, len_b) ||
    50          
241 6           GIT_ADD_SIZET_OVERFLOW(&total, total, 1))
242 0           return NULL;
243              
244 6 50         if ((ptr = git_pool_malloc(pool, total)) != NULL) {
245 6 50         if (len_a)
246 6           memcpy(ptr, a, len_a);
247 6 50         if (len_b)
248 6           memcpy(((char *)ptr) + len_a, b, len_b);
249 6           *(((char *)ptr) + len_a + len_b) = '\0';
250             }
251 6           return ptr;
252             }