6 mpret_t
mpool_init(mpool_t
**mpool
, size_t maxlogsize
, size_t minlogsize
)
12 if (maxlogsize
< minlogsize
)
15 /* Allocate memory for memory pool data structure */
16 if ((*mpool
= malloc(sizeof **mpool
)) == NULL
)
19 (*mpool
)->maxlogsize
= maxlogsize
;
20 (*mpool
)->minlogsize
= minlogsize
;
21 (*mpool
)->nblocks
= (*mpool
)->maxlogsize
- (*mpool
)->minlogsize
+ 1;
23 /* Allocate the actual memory of the pool */
24 printf("Allocating %u bytes for pool\n", 1 << maxlogsize
);
25 printf("maxlogsize = %u\tminlogsize = %u\tnblocks = %u\n",
29 if (((*mpool
)->mem
= malloc(1 << maxlogsize
)) == NULL
) {
34 /* Allocate memory for block lists */
35 if (((*mpool
)->blktable
= malloc((*mpool
)->nblocks
* sizeof *(*mpool
)->blktable
)) == NULL
) {
41 /* Initialize block lists */
42 for (i
= 0; i
< (*mpool
)->nblocks
; i
++)
43 LIST_INIT(&(*mpool
)->blktable
[i
]);
46 * Initially, before any storage has been requested,
47 * we have a single available block of length 2^maxlogsize
50 if ((pblknode
= malloc(sizeof *pblknode
)) == NULL
) {
51 free((*mpool
)->blktable
);
56 pblknode
->ptr
= (*mpool
)->mem
;
58 pblknode
->logsize
= maxlogsize
;
60 LIST_INSERT_HEAD(&(*mpool
)->blktable
[0], pblknode
, next_block
);
62 mpool_printblks(*mpool
);
67 void *mpool_alloc(mpool_t
*mpool
, size_t size
)
71 blknode_t
*pavailnode
;
73 unsigned int i
, newpos
;
75 printf("\n\n=======================================================\n\n");
76 printf("Searching for block of bytes: %u\n", size
);
79 * Find the most suitable 2^j bytes block for the requested size of bytes.
80 * The condition 2^j >= size must be satisfied for the smallest possible value
81 * of j and the block must be marked as available ofcourse.
84 for (i
= 0; i
< mpool
->nblocks
; i
++) {
85 printf("Searcing block: %u\n", i
);
86 phead
= &mpool
->blktable
[i
];
87 if ((pnode
= LIST_FIRST(phead
)) != NULL
) {
88 if ((unsigned)(1 << pnode
->logsize
) >= size
) {
89 LIST_FOREACH(pnode
, phead
, next_block
) {
90 if (pnode
->avail
!= 0) {
100 /* Failure, no available block */
101 if (pavailnode
== NULL
) {
102 printf("No available block found\n");
105 printf("Found block of bytes %u\n", 1 << pavailnode
->logsize
);
107 /* Is a split required ? */
109 printf("size = %u\tp = %u\tp-1 = %u\n",
111 1 << pavailnode
->logsize
,
112 1 << (pavailnode
->logsize
- 1));
115 * We don't need to split the chunk we just found,
116 * if one the following statements is true:
118 * - `size' bytes fit exactly in the chunk
119 * - `size' bytes won't fit in the divided chunk
120 * - `minlogsize' constraint will be violated if we split
122 * NOTE: log2(size/2) = log2(size) - log2(2) = log2(size) - 1
124 if ((size
== (unsigned)(1 << pavailnode
->logsize
))
125 || (size
> (unsigned)(1 << (pavailnode
->logsize
- 1)))
126 || (mpool
->minlogsize
> (pavailnode
->logsize
- 1))) {
127 printf("No split required\n");
128 pavailnode
->avail
= 0; /* Mark as no longer available */
129 mpool_printblks(mpool
);
130 return pavailnode
->ptr
;
133 printf("Splitting...\n");
135 /* Remove old block */
136 printf("Removing old chunk from list\n");
137 LIST_REMOVE(pavailnode
, next_block
);
138 mpool_printblks(mpool
);
139 pavailnode
->logsize
--;
141 printf("New size is now: %u bytes\n", 1 << pavailnode
->logsize
);
142 printf("Moving old chunk to new position\n");
143 newpos
= mpool
->nblocks
- pavailnode
->logsize
- 1;
144 LIST_INSERT_HEAD(&mpool
->blktable
[newpos
], pavailnode
, next_block
);
145 mpool_printblks(mpool
);
148 printf("Will add new item with bytes: %u\n", 1 << pavailnode
->logsize
);
149 if ((pnewnode
= malloc(sizeof *pnewnode
)) == NULL
)
151 pnewnode
->ptr
= (char *)pavailnode
->ptr
+ (1 << pavailnode
->logsize
);
153 pnewnode
->logsize
= pavailnode
->logsize
;
154 LIST_INSERT_HEAD(&mpool
->blktable
[newpos
], pnewnode
, next_block
);
155 mpool_printblks(mpool
);
161 void mpool_free(mpool_t
*mpool
, void *ptr
)
163 const blkhead_t
*phead
;
167 printf("Freeing ptr: %p\n", ptr
);
169 /* Coalesce has not been implemented yet */
170 for (i
= 0; i
< mpool
->nblocks
; i
++) {
171 printf("Block: %u\n", i
);
172 phead
= &mpool
->blktable
[i
];
173 LIST_FOREACH(pnode
, phead
, next_block
) {
174 if (pnode
->ptr
== ptr
) {
176 LIST_REMOVE(pnode
, next_block
);
185 void mpool_destroy(mpool_t
*mpool
)
187 const blkhead_t
*phead
;
191 /* Free all nodes in all block lists */
192 for (i
= 0; i
< mpool
->nblocks
; i
++) {
193 phead
= &mpool
->blktable
[i
];
194 while ((pnode
= LIST_FIRST(phead
)) != NULL
) {
195 LIST_REMOVE(pnode
, next_block
);
200 free(mpool
->blktable
);
205 void mpool_printblks(const mpool_t
*mpool
)
207 const blkhead_t
*phead
;
208 const blknode_t
*pnode
;
211 for (i
= 0; i
< mpool
->nblocks
; i
++) {
212 printf("Block: %u\t", i
);
214 phead
= &mpool
->blktable
[i
];
215 LIST_FOREACH(pnode
, phead
, next_block
) {
216 printf("chunk(addr = %p, bytes = %u, av = %d)\t",
218 (unsigned) (1 << pnode
->logsize
),
226 void mpool_stat_get_nodes(const mpool_t
*mpool
, size_t *avail
, size_t *used
)
228 const blkhead_t
*phead
;
229 const blknode_t
*pnode
;
234 for (i
= 0; i
< mpool
->nblocks
; i
++) {
235 phead
= &mpool
->blktable
[i
];
236 LIST_FOREACH(pnode
, phead
, next_block
) {
237 if (pnode
->avail
== 1)
245 void mpool_stat_get_bytes(const mpool_t
*mpool
, size_t *avail
, size_t *used
)
247 const blkhead_t
*phead
;
248 const blknode_t
*pnode
;
251 for (i
= 0; i
< mpool
->nblocks
; i
++) {
252 phead
= &mpool
->blktable
[i
];
253 LIST_FOREACH(pnode
, phead
, next_block
) {
254 if (pnode
->avail
== 1)
255 *avail
+= 1 << pnode
->logsize
;
257 *used
+= 1 << pnode
->logsize
;
266 size_t an
= 1, un
= 0, ab
= 1, ub
= 0;
269 if (mpool_init(&mpool
, 15, 1) == MP_ENOMEM
) {
270 fprintf(stderr
, "Not enough memory\n");
274 for (i
= 0; i
< 10; i
++) {
275 if ((p
[i
] = mpool_alloc(mpool
, 1 << ((rand() % 10)))) == NULL
)
278 mpool_free(mpool
, p
[i
]);
281 mpool_stat_get_nodes(mpool
, &an
, &un
);
282 mpool_stat_get_bytes(mpool
, &ab
, &ub
);
283 printf("avail nodes = %u\tused nodes = %u\tfree(%%) = %f\n", an
, un
, (float)an
/ (an
+ un
));
284 printf("avail bytes = %u\tused bytes = %u\tfree(%%) = %f\n", ab
, ub
, (float)ab
/ (ab
+ ub
));
286 mpool_destroy(mpool
);