1 /*
2 * Copyright 2023-2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stdlib.h>
9 #include "mem_pool.h"
10
11 #if CONFIG_MEM_POOLS
CalculateAndVerifyAlignment(int Alignment)12 static int CalculateAndVerifyAlignment(int Alignment)
13 {
14 /*********************************/
15 int i;
16 int alignmentBit = 0x1;
17 /*********************************/
18
19 /**
20 * Guarantee that the alignment is the size of a pointer.
21 */
22 if (Alignment < (int)sizeof(unsigned char *))
23 {
24 Alignment = (int)sizeof(unsigned char *);
25 }
26
27 for (i = 0; i < 31; i++)
28 {
29 if (Alignment == alignmentBit)
30 {
31 break;
32 }
33 alignmentBit <<= 1;
34 }
35
36 if (i >= 31)
37 {
38 return 0;
39 }
40 else
41 {
42 return Alignment;
43 }
44 }
45
CalculateItemSize(int ItemSize,int Alignment)46 static int CalculateItemSize(int ItemSize, int Alignment)
47 {
48 /*********************************/
49 int alignmentCount;
50 /*********************************/
51
52 if (ItemSize <= Alignment)
53 {
54 /**
55 * The 2* accounts for the SList struct inside each memory block.
56 */
57 ItemSize = 2 * Alignment;
58 }
59 else
60 {
61 alignmentCount = ItemSize / Alignment;
62 if (ItemSize % Alignment != 0)
63 {
64 alignmentCount++;
65 }
66 /**
67 * The +1 accounts for the SList struct inside each memory block.
68 */
69 ItemSize = ((alignmentCount + 1) * Alignment);
70 }
71
72 return ItemSize;
73 }
74
OSA_MemoryPoolCreate(MemPool_t * MemPool,int ItemSize,void * PreallocatedMemory,int PreallocatedMemorySize,int Alignment)75 MemoryPool_t OSA_MemoryPoolCreate(
76 MemPool_t *MemPool, int ItemSize, void *PreallocatedMemory, int PreallocatedMemorySize, int Alignment)
77 {
78 /*********************************/
79 unsigned char *ptr;
80 SlNode_t *Node;
81 osa_status_t status;
82 /*********************************/
83
84 Alignment = CalculateAndVerifyAlignment(Alignment);
85
86 if (Alignment == 0)
87 {
88 return NULL;
89 }
90
91 ItemSize = CalculateItemSize(ItemSize, Alignment);
92
93 status = OSA_MutexCreate((osa_mutex_handle_t)MemPool->Lock);
94 if (status != KOSA_StatusSuccess)
95 {
96 return NULL;
97 }
98
99 InitStack(&MemPool->Stack);
100 MemPool->ItemSize = ItemSize;
101 MemPool->Alignment = Alignment;
102
103 ptr = (unsigned char *)PreallocatedMemory;
104
105 while (PreallocatedMemorySize >= ItemSize)
106 {
107 Node = (SlNode_t *)ptr;
108
109 PushOnStack(&MemPool->Stack, Node);
110 ptr += MemPool->ItemSize;
111 PreallocatedMemorySize -= MemPool->ItemSize;
112 }
113
114 return (MemoryPool_t)MemPool;
115 }
116
OSA_MemoryPoolAllocate(MemoryPool_t pool)117 void *OSA_MemoryPoolAllocate(MemoryPool_t pool)
118 {
119 /*********************************/
120 MemPool_t *MemPool;
121 SlNode_t *Node;
122 unsigned char *ptr;
123 /*********************************/
124
125 MemPool = (MemPool_t *)pool;
126
127 OSA_MutexLock((osa_mutex_handle_t)MemPool->Lock, osaWaitForever_c);
128
129 if (MemPool->Stack.Count == 0)
130 {
131 OSA_MutexUnlock((osa_mutex_handle_t)MemPool->Lock);
132 return NULL;
133 }
134
135 Node = PopOffStack(&MemPool->Stack);
136
137 OSA_MutexUnlock((osa_mutex_handle_t)MemPool->Lock);
138
139 ptr = ((unsigned char *)Node) + MemPool->Alignment;
140
141 return (void *)ptr;
142 }
143
OSA_MemoryPoolFree(MemoryPool_t pool,void * memory)144 void OSA_MemoryPoolFree(MemoryPool_t pool, void *memory)
145 {
146 /*********************************/
147 MemPool_t *MemPool;
148 SlNode_t *Node;
149 unsigned char *ptr;
150 /*********************************/
151
152 MemPool = (MemPool_t *)pool;
153
154 ptr = ((unsigned char *)memory) - MemPool->Alignment;
155
156 Node = (SlNode_t *)ptr;
157
158 OSA_MutexLock((osa_mutex_handle_t)MemPool->Lock, osaWaitForever_c);
159
160 PushOnStack(&MemPool->Stack, Node);
161
162 OSA_MutexUnlock((osa_mutex_handle_t)MemPool->Lock);
163 }
164
165 #endif
166