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 create 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
DympSetConsSafe(DympoolType * pool,FILLP_BOOL safe)110 void DympSetConsSafe(DympoolType *pool, FILLP_BOOL safe)
111 {
112 FillpQueueSetConsSafe(pool->mp, safe);
113 }
114
DympSetProdSafe(DympoolType * pool,FILLP_BOOL safe)115 void DympSetProdSafe(DympoolType *pool, FILLP_BOOL safe)
116 {
117 FillpQueueSetProdSafe(pool->mp, safe);
118 }
119
DympExpandMemory(DympoolType * pool,int stepSizeWork)120 static int DympExpandMemory(DympoolType *pool, int stepSizeWork)
121 {
122 int i;
123 char *dataPointer = FILLP_NULL_PTR;
124 DympMemory *mem = FILLP_NULL_PTR;
125
126 if (((FILLP_INT)((size_t)pool->itemSize + sizeof(DympItemType)) == 0) ||
127 ((FILLP_INT)(FILLP_MAX_INT_VALUE - sizeof(DympMemory)) /
128 (FILLP_INT)((size_t)pool->itemSize + sizeof(DympItemType))) < stepSizeWork) {
129 FILLP_LOGERR("Error to ask memory, because ask size too big");
130 return -1;
131 }
132 int askSize = (int)((size_t)stepSizeWork * ((size_t)pool->itemSize + sizeof(DympItemType)) + sizeof(DympMemory));
133 mem = (DympMemory *)SpungeAlloc(1, (FILLP_SIZE_T)((FILLP_UINT)askSize), (FILLP_INT)SPUNGE_ALLOC_TYPE_MALLOC);
134 if (mem == FILLP_NULL_PTR) {
135 FILLP_LOGERR("Fail to alloc memory");
136 return -1;
137 }
138
139 dataPointer = (char *)((char *)mem + sizeof(DympMemory));
140
141 HLIST_INIT_NODE(&mem->hnode);
142 HlistAddTail(&pool->mlist, &mem->hnode);
143 int itemCount = 0;
144 for (i = 0; i < stepSizeWork; i++) {
145 FILLP_INT err = 0;
146 DympItemType *item = (DympItemType *)(dataPointer);
147 int offset = (int)(pool->itemSize + ((int)sizeof(DympItemType)));
148 dataPointer += offset;
149
150 item->mp = pool->mp;
151
152 if (pool->itemOperaCb.createCb != FILLP_NULL_PTR) {
153 err = pool->itemOperaCb.createCb(item);
154 }
155
156 if (err != FILLP_OK) {
157 continue;
158 }
159
160 (void)FillpQueuePush(item->mp, (void *)&item, FILLP_FALSE, 1);
161 itemCount++;
162 }
163
164 pool->currentSize += itemCount;
165 if (itemCount != 0) {
166 mem->itemCnt = itemCount;
167 FILLP_LOGINF("stepSize:%d, Current pool size:%d", itemCount, pool->currentSize);
168 } else {
169 HlistDelete(&pool->mlist, &mem->hnode);
170 SpungeFree(mem, SPUNGE_ALLOC_TYPE_MALLOC);
171 }
172
173 return itemCount;
174 }
175
DympAskMoreMemory(DympoolType * pool,int stepSize,int throttleGrow)176 int DympAskMoreMemory(DympoolType *pool, int stepSize, int throttleGrow)
177 {
178 int stepSizeWork = stepSize;
179 int maxSizeRemain;
180 int tempMax;
181
182 FILLP_UNUSED_PARA(throttleGrow);
183
184 if ((pool == FILLP_NULL_PTR) || (stepSize <= 0)) {
185 FILLP_LOGERR("Wrong to ask memory, stepSize:%d", stepSize);
186 return -1;
187 }
188
189 tempMax = pool->maxSize;
190
191 maxSizeRemain = tempMax - pool->currentSize;
192 if (maxSizeRemain <= 0) {
193 FILLP_LOGDBG("maxSizeRemain=%d is invalid, unable to expand memory", maxSizeRemain);
194 return 0;
195 }
196
197 if (stepSizeWork > maxSizeRemain) {
198 stepSizeWork = maxSizeRemain;
199 }
200 return DympExpandMemory(pool, stepSizeWork);
201 }
202
203
DympAlloc(DympoolType * pool,void ** data,int throttleGrow)204 int DympAlloc(DympoolType *pool, void **data, int throttleGrow)
205 {
206 DympItemType *tmp = FILLP_NULL_PTR;
207 FILLP_INT ret = 0;
208 int i;
209
210 if ((pool == FILLP_NULL_PTR) || (data == FILLP_NULL_PTR)) {
211 FILLP_LOGERR("MemPool pointer is invalid \n");
212 return ERR_NULLPTR;
213 }
214
215 for (i = 0; i < pool->maxSize; i++) {
216 ret = FillpQueuePop(pool->mp, (void *)&tmp, 1);
217 if ((ret <= 0) && (pool->autoExpand == FILLP_TRUE) && (pool->currentSize < pool->maxSize) &&
218 (DympAskMoreMemory(pool, pool->initSize, throttleGrow) > 0)) {
219 continue;
220 }
221
222 break;
223 }
224
225 if (ret <= 0) {
226 return ERR_NOBUFS;
227 }
228
229 *data = (char *)tmp + sizeof(DympItemType);
230 return ERR_OK;
231 }
232
DympFree(void * data)233 void DympFree(void *data)
234 {
235 DympItemType *item = FILLP_NULL_PTR;
236 if (data == FILLP_NULL_PTR) {
237 return;
238 }
239
240 item = (DympItemType *)DYMP_GET_ITEM_FROM_DATA(data);
241 if (FillpQueuePush(item->mp, (void *)&item, FILLP_FALSE, 1) != ERR_OK) {
242 FILLP_LOGWAR("Mem Pool free enqueue Error \n");
243 return;
244 }
245
246 return;
247 }
248
249 #ifdef __cplusplus
250 }
251 #endif
252