Line Flow Count Block(s) Source
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 <unistd.h>
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 211755 2 static size_t pool_system_page_size(void)
25 - {
26 - static size_t size = 0;
27 -
28 211755 2 if (!size) {
29 - size_t page_size;
30 5 3,4 if (git__page_size(&page_size) < 0)
31 ##### 5 page_size = 4096;
32 - /* allow space for malloc overhead */
33 5 6 size = (page_size - (2 * sizeof(void *)) - sizeof(git_pool_page));
34 - }
35 -
36 211755 7 return size;
37 - }
38 -
39 - #ifndef GIT_DEBUG_POOL
40 211787 2 int git_pool_init(git_pool *pool, size_t item_size)
41 - {
42 211787 2,3 assert(pool);
43 211787 4,5 assert(item_size >= 1);
44 -
45 211787 6 memset(pool, 0, sizeof(git_pool));
46 211787 6 pool->item_size = item_size;
47 211787 6 pool->page_size = pool_system_page_size();
48 -
49 211757 7 return 0;
50 - }
51 -
52 231772 2 void git_pool_clear(git_pool *pool)
53 - {
54 - git_pool_page *scan, *next;
55 -
56 266425 2,4,5 for (scan = pool->pages; scan != NULL; scan = next) {
57 34650 3 next = scan->next;
58 34650 3 git__free(scan);
59 - }
60 -
61 231775 6 pool->pages = NULL;
62 231775 6 }
63 -
64 34652 2 static void *pool_alloc_page(git_pool *pool, size_t size)
65 - {
66 - git_pool_page *page;
67 34652 2 const size_t new_page_size = (size <= pool->page_size) ? pool->page_size : size;
68 - size_t alloc_size;
69 -
70 34653 2-6 if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) ||
71 34651 5 !(page = git__malloc(alloc_size)))
72 ##### 7 return NULL;
73 -
74 34653 8 page->size = new_page_size;
75 34653 8 page->avail = new_page_size - size;
76 34653 8 page->next = pool->pages;
77 -
78 34653 8 pool->pages = page;
79 -
80 34653 8 return page->data;
81 - }
82 -
83 873867 2 static void *pool_alloc(git_pool *pool, size_t size)
84 - {
85 873867 2 git_pool_page *page = pool->pages;
86 873867 2 void *ptr = NULL;
87 -
88 873867 2,3 if (!page || page->avail < size)
89 34538 4 return pool_alloc_page(pool, size);
90 -
91 839329 5 ptr = &page->data[page->size - page->avail];
92 839329 5 page->avail -= size;
93 -
94 839329 5 return ptr;
95 - }
96 -
97 3 2 uint32_t git_pool__open_pages(git_pool *pool)
98 - {
99 3 2 uint32_t ct = 0;
100 - git_pool_page *scan;
101 1224 2-4 for (scan = pool->pages; scan != NULL; scan = scan->next) ct++;
102 3 5 return ct;
103 - }
104 -
105 28 2 bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
106 - {
107 - git_pool_page *scan;
108 48 2,6,7 for (scan = pool->pages; scan != NULL; scan = scan->next)
109 34 3,4 if ((void *)scan->data <= ptr &&
110 34 4 (void *)(((char *)scan->data) + scan->size) > ptr)
111 14 5 return true;
112 14 8 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 65 2 void git_pool_swap(git_pool *a, git_pool *b)
165 - {
166 - git_pool temp;
167 -
168 65 2 if (a == b)
169 65 3,5 return;
170 -
171 65 4 memcpy(&temp, a, sizeof(temp));
172 65 4 memcpy(a, b, sizeof(temp));
173 65 4 memcpy(b, &temp, sizeof(temp));
174 - }
175 -
176 873946 2 static size_t alloc_size(git_pool *pool, size_t count)
177 - {
178 873946 2 const size_t align = sizeof(void *) - 1;
179 -
180 873946 2 if (pool->item_size > 1) {
181 755339 3 const size_t item_size = (pool->item_size + align) & ~align;
182 755339 3 return item_size * count;
183 - }
184 -
185 118607 4 return (count + align) & ~align;
186 - }
187 -
188 843259 2 void *git_pool_malloc(git_pool *pool, size_t items)
189 - {
190 843259 2 return pool_alloc(pool, alloc_size(pool, items));
191 - }
192 -
193 30842 2 void *git_pool_mallocz(git_pool *pool, size_t items)
194 - {
195 30842 2 const size_t size = alloc_size(pool, items);
196 30719 3 void *ptr = pool_alloc(pool, size);
197 30797 4 if (ptr)
198 30774 5 memset(ptr, 0x0, size);
199 30797 6 return ptr;
200 - }
201 -
202 - 2 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files)char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
203 - {
204 - 2 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) char *ptr = NULL;
205 -
206 - 2-5 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) assert(pool && str && pool->item_size == sizeof(char));
207 -
208 - 6 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) if (n == SIZE_MAX)
209 - 7 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) return NULL;
210 -
211 - 8,9 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) if ((ptr = git_pool_malloc(pool, (n + 1))) != NULL) {
212 - 10 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) memcpy(ptr, str, n);
213 - 10 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) ptr[n] = '\0';
214 - }
215 -
216 - 11 suppressed: function cannot be solved git_pool_strndup (automatic due to inconsistent arc counts in .gcda files) return ptr;
217 - }
218 -
219 32785 2 char *git_pool_strdup(git_pool *pool, const char *str)
220 - {
221 32785 2-5 assert(pool && str && pool->item_size == sizeof(char));
222 32785 6 return git_pool_strndup(pool, str, strlen(str));
223 - }
224 -
225 130 2 char *git_pool_strdup_safe(git_pool *pool, const char *str)
226 - {
227 130 2 return str ? git_pool_strdup(pool, str) : NULL;
228 - }
229 -
230 62 2 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 62 2-4 assert(pool && pool->item_size == sizeof(char));
236 -
237 62 5-7 len_a = a ? strlen(a) : 0;
238 62 8-10 len_b = b ? strlen(b) : 0;
239 -
240 62 11-13,15 if (GIT_ADD_SIZET_OVERFLOW(&total, len_a, len_b) ||
241 62 14,16 GIT_ADD_SIZET_OVERFLOW(&total, total, 1))
242 ##### 17 return NULL;
243 -
244 62 18,19 if ((ptr = git_pool_malloc(pool, total)) != NULL) {
245 62 20 if (len_a)
246 62 21 memcpy(ptr, a, len_a);
247 62 22 if (len_b)
248 62 23 memcpy(((char *)ptr) + len_a, b, len_b);
249 62 24 *(((char *)ptr) + len_a + len_b) = '\0';
250 - }
251 62 25 return ptr;
252 - }