1 /* |
1 /* |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 * |
3 * |
4 * Copyright 2016 Olaf Wintermann. All rights reserved. |
4 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. |
5 * |
5 * |
6 * Redistribution and use in source and binary forms, with or without |
6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions are met: |
7 * modification, are permitted provided that the following conditions are met: |
8 * |
8 * |
9 * 1. Redistributions of source code must retain the above copyright |
9 * 1. Redistributions of source code must retain the above copyright |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
|
29 #include "ucx/mempool.h" |
|
30 |
29 #include <stdlib.h> |
31 #include <stdlib.h> |
30 #include <string.h> |
32 #include <string.h> |
31 #include <stdio.h> |
33 #include <stdio.h> |
32 #ifdef __cplusplus |
34 #ifdef __cplusplus |
33 #define __STDC_FORMAT_MACROS |
35 #define __STDC_FORMAT_MACROS |
34 #endif |
36 #endif |
35 #include <inttypes.h> |
37 #include <inttypes.h> |
36 |
|
37 #include "mempool.h" |
|
38 |
38 |
39 /** Capsule for destructible memory chunks. */ |
39 /** Capsule for destructible memory chunks. */ |
40 typedef struct { |
40 typedef struct { |
41 /** The destructor for the memory chunk. */ |
41 /** The destructor for the memory chunk. */ |
42 ucx_destructor destructor; |
42 ucx_destructor destructor; |
54 ucx_destructor destructor; |
54 ucx_destructor destructor; |
55 /** A pointer to the data. */ |
55 /** A pointer to the data. */ |
56 void *ptr; |
56 void *ptr; |
57 } ucx_regdestr; |
57 } ucx_regdestr; |
58 |
58 |
59 UCX_EXTERN void ucx_mempool_shared_destr(void* ptr) { |
59 #ifdef __cplusplus |
|
60 extern "C" |
|
61 #endif |
|
62 void ucx_mempool_shared_destr(void* ptr) { |
60 ucx_regdestr *rd = (ucx_regdestr*)ptr; |
63 ucx_regdestr *rd = (ucx_regdestr*)ptr; |
61 rd->destructor(rd->ptr); |
64 rd->destructor(rd->ptr); |
62 } |
65 } |
63 |
66 |
64 UcxMempool *ucx_mempool_new(size_t n) { |
67 UcxMempool *ucx_mempool_new(size_t n) { |
|
68 size_t poolsz; |
|
69 if(ucx_szmul(n, sizeof(void*), &poolsz)) { |
|
70 return NULL; |
|
71 } |
|
72 |
65 UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool)); |
73 UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool)); |
66 if (!pool) { |
74 if (!pool) { |
67 return NULL; |
75 return NULL; |
68 } |
76 } |
69 |
77 |
70 pool->data = (void**) malloc(n * sizeof(void*)); |
78 pool->data = (void**) malloc(poolsz); |
71 if (pool->data == NULL) { |
79 if (pool->data == NULL) { |
72 free(pool); |
80 free(pool); |
73 return NULL; |
81 return NULL; |
74 } |
82 } |
75 |
83 |
91 |
99 |
92 return pool; |
100 return pool; |
93 } |
101 } |
94 |
102 |
95 int ucx_mempool_chcap(UcxMempool *pool, size_t newcap) { |
103 int ucx_mempool_chcap(UcxMempool *pool, size_t newcap) { |
96 void **data = (void**) realloc(pool->data, newcap*sizeof(void*)); |
104 if (newcap < pool->ndata) { |
|
105 return 1; |
|
106 } |
|
107 |
|
108 size_t newcapsz; |
|
109 if(ucx_szmul(newcap, sizeof(void*), &newcapsz)) { |
|
110 return 1; |
|
111 } |
|
112 |
|
113 void **data = (void**) realloc(pool->data, newcapsz); |
97 if (data) { |
114 if (data) { |
98 pool->data = data; |
115 pool->data = data; |
99 pool->size = newcap; |
116 pool->size = newcap; |
100 return EXIT_SUCCESS; |
117 return 0; |
101 } else { |
118 } else { |
102 return EXIT_FAILURE; |
119 return 1; |
103 } |
120 } |
104 } |
121 } |
105 |
122 |
106 void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { |
123 void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { |
|
124 if(((size_t)-1) - sizeof(ucx_destructor) < n) { |
|
125 return NULL; |
|
126 } |
|
127 |
107 if (pool->ndata >= pool->size) { |
128 if (pool->ndata >= pool->size) { |
108 // The hard coded 16 is documented for this function and ucx_mempool_new |
129 size_t newcap = pool->size*2; |
109 if (ucx_mempool_chcap(pool, pool->size + 16) == EXIT_FAILURE) { |
130 if (newcap < pool->size || ucx_mempool_chcap(pool, newcap)) { |
110 return NULL; |
131 return NULL; |
111 } |
132 } |
112 } |
133 } |
113 |
134 |
114 ucx_memchunk *mem = (ucx_memchunk*)malloc(sizeof(ucx_destructor) + n); |
135 void *p = malloc(sizeof(ucx_destructor) + n); |
|
136 ucx_memchunk *mem = (ucx_memchunk*)p; |
115 if (!mem) { |
137 if (!mem) { |
116 return NULL; |
138 return NULL; |
117 } |
139 } |
118 |
140 |
119 mem->destructor = NULL; |
141 mem->destructor = NULL; |
122 |
144 |
123 return &(mem->c); |
145 return &(mem->c); |
124 } |
146 } |
125 |
147 |
126 void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) { |
148 void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) { |
127 void *ptr = ucx_mempool_malloc(pool, nelem*elsize); |
149 size_t msz; |
|
150 if(ucx_szmul(nelem, elsize, &msz)) { |
|
151 return NULL; |
|
152 } |
|
153 |
|
154 void *ptr = ucx_mempool_malloc(pool, msz); |
128 if (!ptr) { |
155 if (!ptr) { |
129 return NULL; |
156 return NULL; |
130 } |
157 } |
131 memset(ptr, 0, nelem * elsize); |
158 memset(ptr, 0, nelem * elsize); |
132 return ptr; |
159 return ptr; |
133 } |
160 } |
134 |
161 |
135 void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) { |
162 void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) { |
|
163 if(((size_t)-1) - sizeof(ucx_destructor) < n) { |
|
164 return NULL; |
|
165 } |
|
166 |
136 char *mem = ((char*)ptr) - sizeof(ucx_destructor); |
167 char *mem = ((char*)ptr) - sizeof(ucx_destructor); |
137 char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor)); |
168 char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor)); |
138 if (!newm) { |
169 if (!newm) { |
139 return NULL; |
170 return NULL; |
140 } |
171 } |
145 return newm + sizeof(ucx_destructor); |
176 return newm + sizeof(ucx_destructor); |
146 } |
177 } |
147 } |
178 } |
148 fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", |
179 fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", |
149 (intptr_t)ptr, (intptr_t)pool); |
180 (intptr_t)ptr, (intptr_t)pool); |
150 exit(EXIT_FAILURE); |
181 abort(); |
151 } else { |
182 } else { |
152 return newm + sizeof(ucx_destructor); |
183 return newm + sizeof(ucx_destructor); |
153 } |
184 } |
154 } |
185 } |
155 |
186 |
170 return; |
201 return; |
171 } |
202 } |
172 } |
203 } |
173 fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", |
204 fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", |
174 (intptr_t)ptr, (intptr_t)pool); |
205 (intptr_t)ptr, (intptr_t)pool); |
175 exit(EXIT_FAILURE); |
206 abort(); |
176 } |
207 } |
177 |
208 |
178 void ucx_mempool_destroy(UcxMempool *pool) { |
209 void ucx_mempool_destroy(UcxMempool *pool) { |
179 ucx_memchunk *chunk; |
210 ucx_memchunk *chunk; |
180 for(size_t i=0 ; i<pool->ndata ; i++) { |
211 for(size_t i=0 ; i<pool->ndata ; i++) { |