1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dympool.h"
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
DympCreatePool(int initSize,int maxSize,int itemSize,FILLP_BOOL autoExpand,DympoolItemOperaCbSt * itemOperaCb)21 DympoolType *DympCreatePool(int initSize, int maxSize, int itemSize, FILLP_BOOL autoExpand,
22 DympoolItemOperaCbSt *itemOperaCb)
23 {
24 DympoolType *pool = FILLP_NULL_PTR;
25 if ((initSize <= 0) || (maxSize <= 0) || (itemSize <= 0)) {
26 FILLP_LOGERR("Error to crate pool initSize:%d,maxSize:%d,itemSize:%d", initSize, maxSize, itemSize);
27 return FILLP_NULL_PTR;
28 }
29
30 pool = SpungeAlloc(1, sizeof(DympoolType), SPUNGE_ALLOC_TYPE_MALLOC);
31 if (pool == FILLP_NULL_PTR) {
32 FILLP_LOGERR("Can't alloc dympool");
33 goto CREATE_FAIL;
34 }
35
36 pool->maxSize = maxSize;
37 pool->itemSize = itemSize;
38 pool->currentSize = 0;
39 pool->itemOperaCb.createCb = itemOperaCb->createCb;
40 pool->itemOperaCb.destroyCb = itemOperaCb->destroyCb;
41 pool->autoExpand = autoExpand;
42 pool->initSize = initSize;
43
44 HLIST_INIT(&pool->mlist);
45
46 pool->mp = FillpQueueCreate("dymp_memory_pool", (FILLP_SIZE_T)(unsigned int)maxSize, SPUNGE_ALLOC_TYPE_MALLOC);
47 if (pool->mp == FILLP_NULL_PTR) {
48 FILLP_LOGERR("Can't alloc queue");
49 goto CREATE_FAIL;
50 }
51
52 pool->currentSize = DympAskMoreMemory(pool, initSize, FILLP_FALSE);
53 if (pool->currentSize <= 0) {
54 FILLP_LOGERR("Initial memory fail");
55 goto CREATE_FAIL;
56 }
57
58 FILLP_LOGINF("Create pool success, maxSize:%d, currentSize:%d, itemSize:%d",
59 maxSize, pool->currentSize, itemSize);
60
61 return pool;
62
63 CREATE_FAIL:
64 if (pool != FILLP_NULL_PTR) {
65 if (pool->mp != FILLP_NULL_PTR) {
66 FillpQueueDestroy(pool->mp);
67 pool->mp = FILLP_NULL_PTR;
68 }
69 SpungeFree(pool, SPUNGE_ALLOC_TYPE_MALLOC);
70 }
71
72 return FILLP_NULL_PTR;
73 }
74
DympDestroyPool(DympoolType * pool)75 void DympDestroyPool(DympoolType *pool)
76 {
77 struct HlistNode *node = FILLP_NULL_PTR;
78 DympMemory *mem = FILLP_NULL_PTR;
79
80 if (pool == FILLP_NULL_PTR) {
81 return;
82 }
83
84 node = HLIST_FIRST(&pool->mlist);
85 while (node != FILLP_NULL_PTR) {
86 mem = DympMemoryNodeEntry(node);
87 if (pool->itemOperaCb.destroyCb != FILLP_NULL_PTR) {
88 char *dataPointer = (char *)((char *)mem + sizeof(DympMemory));
89 int i;
90 for (i = 0; i < mem->itemCnt; i++) {
91 DympItemType *item = (DympItemType *)(dataPointer);
92 pool->itemOperaCb.destroyCb(item);
93 item->mp = FILLP_NULL_PTR;
94 int offset = (int)(pool->itemSize + ((int)sizeof(DympItemType)));
95 dataPointer += offset;
96 }
97 }
98
99 node = node->next;
100 SpungeFree(mem, SPUNGE_ALLOC_TYPE_MALLOC);
101 }
102
103 if (pool->mp != FILLP_NULL_PTR) {
104 FillpQueueDestroy(pool->mp);
105 }
106
107 SpungeFree(pool, SPUNGE_ALLOC_TYPE_MALLOC);
108
109 return;
110 }
111
DympSetConsSafe(DympoolType * pool,FILLP_BOOL safe)112 void DympSetConsSafe(DympoolType *pool, FILLP_BOOL safe)
113 {
114 FillpQueueSetConsSafe(pool->mp, safe);
115 }
116
DympSetProdSafe(DympoolType * pool,FILLP_BOOL safe)117 void DympSetProdSafe(DympoolType *pool, FILLP_BOOL safe)
118 {
119 FillpQueueSetProdSafe(pool->mp, safe);
120 }
121
DympExpandMemory(DympoolType * pool,int stepSizeWork)122 static int DympExpandMemory(DympoolType *pool, int stepSizeWork)
123 {
124 int i;
125 char *dataPointer = FILLP_NULL_PTR;
126 DympMemory *mem = FILLP_NULL_PTR;
127
128 if (((FILLP_INT)((size_t)pool->itemSize + sizeof(DympItemType)) == 0) ||
129 ((FILLP_INT)(FILLP_MAX_INT_VALUE - sizeof(DympMemory)) /
130 (FILLP_INT)((size_t)pool->itemSize + sizeof(DympItemType))) < stepSizeWork) {
131 FILLP_LOGERR("Error to ask memory, because ask size too big");
132 return -1;
133 }
134 int askSize = (int)((size_t)stepSizeWork * ((size_t)pool->itemSize + sizeof(DympItemType)) + sizeof(DympMemory));
135 mem = (DympMemory *)SpungeAlloc(1, (FILLP_SIZE_T)((FILLP_UINT)askSize), (FILLP_INT)SPUNGE_ALLOC_TYPE_MALLOC);
136 if (mem == FILLP_NULL_PTR) {
137 FILLP_LOGERR("Fail to alloc memory");
138 return -1;
139 }
140
141 dataPointer = (char *)((char *)mem + sizeof(DympMemory));
142
143 HLIST_INIT_NODE(&mem->hnode);
144 HlistAddTail(&pool->mlist, &mem->hnode);
145 int itemCount = 0;
146 for (i = 0; i < stepSizeWork; i++) {
147 FILLP_INT err = 0;
148 DympItemType *item = (DympItemType *)(dataPointer);
149 int offset = (int)(pool->itemSize + ((int)sizeof(DympItemType)));
150 dataPointer += offset;
151
152 item->mp = pool->mp;
153
154 if (pool->itemOperaCb.createCb != FILLP_NULL_PTR) {
155 err = pool->itemOperaCb.createCb(item);
156 }
157
158 if (err != FILLP_OK) {
159 continue;
160 }
161
162 (void)FillpQueuePush(item->mp, (void *)&item, FILLP_FALSE, 1);
163 itemCount++;
164 }
165
166 pool->currentSize += itemCount;
167 if (itemCount != 0) {
168 mem->itemCnt = itemCount;
169 FILLP_LOGINF("stepSize:%d, Current pool size:%d", itemCount, pool->currentSize);
170 } else {
171 HlistDelete(&pool->mlist, &mem->hnode);
172 SpungeFree(mem, SPUNGE_ALLOC_TYPE_MALLOC);
173 }
174
175 return itemCount;
176 }
177
DympAskMoreMemory(DympoolType * pool,int stepSize,int throttleGrow)178 int DympAskMoreMemory(DympoolType *pool, int stepSize, int throttleGrow)
179 {
180 int stepSizeWork = stepSize;
181 int maxSizeRemain;
182 int tempMax;
183
184 FILLP_UNUSED_PARA(throttleGrow);
185
186 if ((pool == FILLP_NULL_PTR) || (stepSize <= 0)) {
187 FILLP_LOGERR("Wrong to ask memory, stepSize:%d", stepSize);
188 return -1;
189 }
190
191 tempMax = pool->maxSize;
192
193 maxSizeRemain = tempMax - pool->currentSize;
194 if (maxSizeRemain <= 0) {
195 FILLP_LOGDBG("maxSizeRemain=%d is invalid, unable to expand memory", maxSizeRemain);
196 return 0;
197 }
198
199 if (stepSizeWork > maxSizeRemain) {
200 stepSizeWork = maxSizeRemain;
201 }
202 return DympExpandMemory(pool, stepSizeWork);
203 }
204
205
DympAlloc(DympoolType * pool,void ** data,int throttleGrow)206 int DympAlloc(DympoolType *pool, void **data, int throttleGrow)
207 {
208 DympItemType *tmp = FILLP_NULL_PTR;
209 FILLP_INT ret = 0;
210 int i;
211
212 if ((pool == FILLP_NULL_PTR) || (data == FILLP_NULL_PTR)) {
213 FILLP_LOGERR("MemPool pointer is invalid \n");
214 return ERR_NULLPTR;
215 }
216
217 for (i = 0; i < pool->maxSize; i++) {
218 ret = FillpQueuePop(pool->mp, (void *)&tmp, 1);
219 if ((ret <= 0) && (pool->autoExpand == FILLP_TRUE) && (pool->currentSize < pool->maxSize) &&
220 (DympAskMoreMemory(pool, pool->initSize, throttleGrow) > 0)) {
221 continue;
222 }
223
224 break;
225 }
226
227 if (ret <= 0) {
228 return ERR_NOBUFS;
229 }
230
231 *data = (char *)tmp + sizeof(DympItemType);
232 return ERR_OK;
233 }
234
DympFree(void * data)235 void DympFree(void *data)
236 {
237 DympItemType *item = FILLP_NULL_PTR;
238 if (data == FILLP_NULL_PTR) {
239 return;
240 }
241
242 item = (DympItemType *)DYMP_GET_ITEM_FROM_DATA(data);
243 if (FillpQueuePush(item->mp, (void *)&item, FILLP_FALSE, 1) != ERR_OK) {
244 FILLP_LOGWAR("Mem Pool free enqueue Error \n");
245 return;
246 }
247
248 return;
249 }
250
251 #ifdef __cplusplus
252 }
253 #endif
254