]>
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 size_t git_pool__system_page_size(void)
26 static size_t size
= 0;
30 if (git__page_size(&page_size
) < 0)
32 /* allow space for malloc overhead */
33 size
= (page_size
- (2 * sizeof(void *)) - sizeof(git_pool_page
));
39 #ifndef GIT_DEBUG_POOL
40 void git_pool_init(git_pool
*pool
, size_t item_size
)
43 assert(item_size
>= 1);
45 memset(pool
, 0, sizeof(git_pool
));
46 pool
->item_size
= item_size
;
47 pool
->page_size
= git_pool__system_page_size();
50 void git_pool_clear(git_pool
*pool
)
52 git_pool_page
*scan
, *next
;
54 for (scan
= pool
->pages
; scan
!= NULL
; scan
= next
) {
62 static void *pool_alloc_page(git_pool
*pool
, size_t size
)
65 const size_t new_page_size
= (size
<= pool
->page_size
) ? pool
->page_size
: size
;
68 if (GIT_ADD_SIZET_OVERFLOW(&alloc_size
, new_page_size
, sizeof(git_pool_page
)) ||
69 !(page
= git__malloc(alloc_size
)))
72 page
->size
= new_page_size
;
73 page
->avail
= new_page_size
- size
;
74 page
->next
= pool
->pages
;
81 static void *pool_alloc(git_pool
*pool
, size_t size
)
83 git_pool_page
*page
= pool
->pages
;
86 if (!page
|| page
->avail
< size
)
87 return pool_alloc_page(pool
, size
);
89 ptr
= &page
->data
[page
->size
- page
->avail
];
95 uint32_t git_pool__open_pages(git_pool
*pool
)
99 for (scan
= pool
->pages
; scan
!= NULL
; scan
= scan
->next
) ct
++;
103 bool git_pool__ptr_in_pool(git_pool
*pool
, void *ptr
)
106 for (scan
= pool
->pages
; scan
!= NULL
; scan
= scan
->next
)
107 if ((void *)scan
->data
<= ptr
&&
108 (void *)(((char *)scan
->data
) + scan
->size
) > ptr
)
115 static int git_pool__ptr_cmp(const void * a
, const void * b
)
128 void git_pool_init(git_pool
*pool
, size_t item_size
)
131 assert(item_size
>= 1);
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
);
139 void git_pool_clear(git_pool
*pool
)
141 git_vector_free_deep(&pool
->allocations
);
144 static void *pool_alloc(git_pool
*pool
, size_t size
) {
146 if((ptr
= git__malloc(size
)) == NULL
) {
149 git_vector_insert_sorted(&pool
->allocations
, ptr
, NULL
);
153 bool git_pool__ptr_in_pool(git_pool
*pool
, void *ptr
)
156 return git_vector_bsearch(&pos
, &pool
->allocations
, ptr
) != GIT_ENOTFOUND
;
160 void git_pool_swap(git_pool
*a
, git_pool
*b
)
167 memcpy(&temp
, a
, sizeof(temp
));
168 memcpy(a
, b
, sizeof(temp
));
169 memcpy(b
, &temp
, sizeof(temp
));
172 static size_t alloc_size(git_pool
*pool
, size_t count
)
174 const size_t align
= sizeof(void *) - 1;
176 if (pool
->item_size
> 1) {
177 const size_t item_size
= (pool
->item_size
+ align
) & ~align
;
178 return item_size
* count
;
181 return (count
+ align
) & ~align
;
184 void *git_pool_malloc(git_pool
*pool
, size_t items
)
186 return pool_alloc(pool
, alloc_size(pool
, items
));
189 void *git_pool_mallocz(git_pool
*pool
, size_t items
)
191 const size_t size
= alloc_size(pool
, items
);
192 void *ptr
= pool_alloc(pool
, size
);
194 memset(ptr
, 0x0, size
);
198 char *git_pool_strndup(git_pool
*pool
, const char *str
, size_t n
)
202 assert(pool
&& str
&& pool
->item_size
== sizeof(char));
207 if ((ptr
= git_pool_malloc(pool
, (n
+ 1))) != NULL
) {
215 char *git_pool_strdup(git_pool
*pool
, const char *str
)
217 assert(pool
&& str
&& pool
->item_size
== sizeof(char));
218 return git_pool_strndup(pool
, str
, strlen(str
));
221 char *git_pool_strdup_safe(git_pool
*pool
, const char *str
)
223 return str
? git_pool_strdup(pool
, str
) : NULL
;
226 char *git_pool_strcat(git_pool
*pool
, const char *a
, const char *b
)
229 size_t len_a
, len_b
, total
;
231 assert(pool
&& pool
->item_size
== sizeof(char));
233 len_a
= a
? strlen(a
) : 0;
234 len_b
= b
? strlen(b
) : 0;
236 if (GIT_ADD_SIZET_OVERFLOW(&total
, len_a
, len_b
) ||
237 GIT_ADD_SIZET_OVERFLOW(&total
, total
, 1))
240 if ((ptr
= git_pool_malloc(pool
, total
)) != NULL
) {
242 memcpy(ptr
, a
, len_a
);
244 memcpy(((char *)ptr
) + len_a
, b
, len_b
);
245 *(((char *)ptr
) + len_a
+ len_b
) = '\0';