]>
git.proxmox.com Git - libgit2.git/blob - src/pool.c
2 * Copyright (C) the libgit2 contributors. All rights reserved.
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.
15 struct git_pool_page
{
19 GIT_ALIGN(char data
[GIT_FLEX_ARRAY
], 8);
22 static void *pool_alloc_page(git_pool
*pool
, size_t size
);
24 #ifndef GIT_DEBUG_POOL
26 static size_t system_page_size
= 0;
28 int git_pool_global_init(void)
30 if (git__page_size(&system_page_size
) < 0)
31 system_page_size
= 4096;
32 /* allow space for malloc overhead */
33 system_page_size
-= (2 * sizeof(void *)) + sizeof(git_pool_page
);
37 int git_pool_init(git_pool
*pool
, size_t item_size
)
40 GIT_ASSERT_ARG(item_size
>= 1);
42 memset(pool
, 0, sizeof(git_pool
));
43 pool
->item_size
= item_size
;
44 pool
->page_size
= system_page_size
;
49 void git_pool_clear(git_pool
*pool
)
51 git_pool_page
*scan
, *next
;
53 for (scan
= pool
->pages
; scan
!= NULL
; scan
= next
) {
61 static void *pool_alloc_page(git_pool
*pool
, size_t size
)
64 const size_t new_page_size
= (size
<= pool
->page_size
) ? pool
->page_size
: size
;
67 if (GIT_ADD_SIZET_OVERFLOW(&alloc_size
, new_page_size
, sizeof(git_pool_page
)) ||
68 !(page
= git__malloc(alloc_size
)))
71 page
->size
= new_page_size
;
72 page
->avail
= new_page_size
- size
;
73 page
->next
= pool
->pages
;
80 static void *pool_alloc(git_pool
*pool
, size_t size
)
82 git_pool_page
*page
= pool
->pages
;
85 if (!page
|| page
->avail
< size
)
86 return pool_alloc_page(pool
, size
);
88 ptr
= &page
->data
[page
->size
- page
->avail
];
94 uint32_t git_pool__open_pages(git_pool
*pool
)
98 for (scan
= pool
->pages
; scan
!= NULL
; scan
= scan
->next
) ct
++;
102 bool git_pool__ptr_in_pool(git_pool
*pool
, void *ptr
)
105 for (scan
= pool
->pages
; scan
!= NULL
; scan
= scan
->next
)
106 if ((void *)scan
->data
<= ptr
&&
107 (void *)(((char *)scan
->data
) + scan
->size
) > ptr
)
114 int git_pool_global_init(void)
119 static int git_pool__ptr_cmp(const void * a
, const void * b
)
132 int git_pool_init(git_pool
*pool
, size_t item_size
)
134 GIT_ASSERT_ARG(pool
);
135 GIT_ASSERT_ARG(item_size
>= 1);
137 memset(pool
, 0, sizeof(git_pool
));
138 pool
->item_size
= item_size
;
139 pool
->page_size
= git_pool__system_page_size();
140 git_vector_init(&pool
->allocations
, 100, git_pool__ptr_cmp
);
145 void git_pool_clear(git_pool
*pool
)
147 git_vector_free_deep(&pool
->allocations
);
150 static void *pool_alloc(git_pool
*pool
, size_t size
) {
152 if((ptr
= git__malloc(size
)) == NULL
) {
155 git_vector_insert_sorted(&pool
->allocations
, ptr
, NULL
);
159 bool git_pool__ptr_in_pool(git_pool
*pool
, void *ptr
)
162 return git_vector_bsearch(&pos
, &pool
->allocations
, ptr
) != GIT_ENOTFOUND
;
166 void git_pool_swap(git_pool
*a
, git_pool
*b
)
173 memcpy(&temp
, a
, sizeof(temp
));
174 memcpy(a
, b
, sizeof(temp
));
175 memcpy(b
, &temp
, sizeof(temp
));
178 static size_t alloc_size(git_pool
*pool
, size_t count
)
180 const size_t align
= sizeof(void *) - 1;
182 if (pool
->item_size
> 1) {
183 const size_t item_size
= (pool
->item_size
+ align
) & ~align
;
184 return item_size
* count
;
187 return (count
+ align
) & ~align
;
190 void *git_pool_malloc(git_pool
*pool
, size_t items
)
192 return pool_alloc(pool
, alloc_size(pool
, items
));
195 void *git_pool_mallocz(git_pool
*pool
, size_t items
)
197 const size_t size
= alloc_size(pool
, items
);
198 void *ptr
= pool_alloc(pool
, size
);
200 memset(ptr
, 0x0, size
);
204 char *git_pool_strndup(git_pool
*pool
, const char *str
, size_t n
)
208 GIT_ASSERT_ARG_WITH_RETVAL(pool
, NULL
);
209 GIT_ASSERT_ARG_WITH_RETVAL(str
, NULL
);
210 GIT_ASSERT_ARG_WITH_RETVAL(pool
->item_size
== sizeof(char), NULL
);
215 if ((ptr
= git_pool_malloc(pool
, (n
+ 1))) != NULL
) {
223 char *git_pool_strdup(git_pool
*pool
, const char *str
)
225 GIT_ASSERT_ARG_WITH_RETVAL(pool
, NULL
);
226 GIT_ASSERT_ARG_WITH_RETVAL(str
, NULL
);
227 GIT_ASSERT_ARG_WITH_RETVAL(pool
->item_size
== sizeof(char), NULL
);
229 return git_pool_strndup(pool
, str
, strlen(str
));
232 char *git_pool_strdup_safe(git_pool
*pool
, const char *str
)
234 return str
? git_pool_strdup(pool
, str
) : NULL
;
237 char *git_pool_strcat(git_pool
*pool
, const char *a
, const char *b
)
240 size_t len_a
, len_b
, total
;
242 GIT_ASSERT_ARG_WITH_RETVAL(pool
, NULL
);
243 GIT_ASSERT_ARG_WITH_RETVAL(pool
->item_size
== sizeof(char), NULL
);
245 len_a
= a
? strlen(a
) : 0;
246 len_b
= b
? strlen(b
) : 0;
248 if (GIT_ADD_SIZET_OVERFLOW(&total
, len_a
, len_b
) ||
249 GIT_ADD_SIZET_OVERFLOW(&total
, total
, 1))
252 if ((ptr
= git_pool_malloc(pool
, total
)) != NULL
) {
254 memcpy(ptr
, a
, len_a
);
256 memcpy(((char *)ptr
) + len_a
, b
, len_b
);
257 *(((char *)ptr
) + len_a
+ len_b
) = '\0';