• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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