3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
31 #define INCLUDE_FROM_DYNALLOC_C
36 char Mem_Heap
[NUM_BLOCKS
* BLOCK_SIZE
];
37 void* Mem_Handles
[NUM_HANDLES
];
38 uint8_t Mem_Block_Flags
[(NUM_BLOCKS
/ 4) + ((NUM_BLOCKS
% 4) ?
1 : 0)];
39 uint8_t FlagMaskLookupMask
[4];
40 uint8_t FlagMaskLookupNum
[4];
41 } Mem_MemData
= {.FlagMaskLookupMask
= {(3 << 0), (3 << 2), (3 << 4), (3 << 6)},
42 .FlagMaskLookupNum
= { 0, 2, 4, 6}};
44 static uint8_t Mem_GetBlockFlags(const Block_Number_t BlockNum
)
46 const Block_Number_t BlockIndex
= (BlockNum
>> 2);
47 const uint8_t FlagMask
= Mem_MemData
.FlagMaskLookupMask
[BlockNum
& 0x03];
48 const uint8_t FlagMaskShift
= Mem_MemData
.FlagMaskLookupNum
[BlockNum
& 0x03];
50 return ((Mem_MemData
.Mem_Block_Flags
[BlockIndex
] & FlagMask
) >> FlagMaskShift
);
53 static void Mem_SetBlockFlags(const Block_Number_t BlockNum
, const uint8_t Flags
)
55 const Block_Number_t BlockIndex
= (BlockNum
>> 2);
56 const uint8_t FlagMask
= Mem_MemData
.FlagMaskLookupMask
[BlockNum
& 0x03];
57 const uint8_t FlagMaskShift
= Mem_MemData
.FlagMaskLookupNum
[BlockNum
& 0x03];
59 Mem_MemData
.Mem_Block_Flags
[BlockIndex
] &= ~FlagMask
;
60 Mem_MemData
.Mem_Block_Flags
[BlockIndex
] |= (Flags
<< FlagMaskShift
);
63 static inline void Mem_Defrag(void)
65 Block_Number_t FreeStartBlock
= 0;
66 char* FreeStartPtr
= NULL
;
67 char* UsedStartPtr
= NULL
;
68 Block_Number_t CurrBlock
;
70 for (CurrBlock
= 0; CurrBlock
< NUM_BLOCKS
; CurrBlock
++)
72 if (!(Mem_GetBlockFlags(CurrBlock
) & BLOCK_USED_MASK
))
74 FreeStartPtr
= &Mem_MemData
.Mem_Heap
[CurrBlock
* BLOCK_SIZE
];
75 FreeStartBlock
= CurrBlock
;
80 if (FreeStartPtr
== NULL
)
83 while (++CurrBlock
< NUM_BLOCKS
)
85 uint8_t CurrBlockFlags
= Mem_GetBlockFlags(CurrBlock
);
87 if (CurrBlockFlags
& BLOCK_USED_MASK
)
89 UsedStartPtr
= &Mem_MemData
.Mem_Heap
[CurrBlock
* BLOCK_SIZE
];
91 for (Handle_Number_t HandleNum
= 0; HandleNum
< NUM_HANDLES
; HandleNum
++)
93 if (Mem_MemData
.Mem_Handles
[HandleNum
] == UsedStartPtr
)
95 Mem_MemData
.Mem_Handles
[HandleNum
] = FreeStartPtr
;
100 memcpy(FreeStartPtr
, UsedStartPtr
, BLOCK_SIZE
);
101 FreeStartPtr
+= BLOCK_SIZE
;
103 Mem_SetBlockFlags(FreeStartBlock
++, CurrBlockFlags
);
104 Mem_SetBlockFlags(CurrBlock
, 0);
109 static inline bool Mem_FindFreeBlocks(Block_Number_t
* const RetStartPtr
, const Block_Number_t Blocks
)
111 Block_Number_t FreeInCurrSec
= 0;
113 for (Block_Number_t CurrBlock
= 0; CurrBlock
< NUM_BLOCKS
; CurrBlock
++)
115 if (Mem_GetBlockFlags(CurrBlock
) & BLOCK_USED_MASK
)
120 if (FreeInCurrSec
>= Blocks
)
122 *RetStartPtr
= CurrBlock
;
130 Mem_Handle_t
Mem_Alloc(const Alloc_Size_t Bytes
)
132 Block_Number_t ReqBlocks
= (Bytes
/ BLOCK_SIZE
);
133 Block_Number_t StartBlock
;
135 if (Bytes
% BLOCK_SIZE
)
138 if (!(Mem_FindFreeBlocks(&StartBlock
, ReqBlocks
)))
142 if (!(Mem_FindFreeBlocks(&StartBlock
, ReqBlocks
)))
146 for (Block_Number_t UsedBlock
= 0; UsedBlock
< (ReqBlocks
- 1); UsedBlock
++)
147 Mem_SetBlockFlags((StartBlock
+ UsedBlock
), (BLOCK_USED_MASK
| BLOCK_LINKED_MASK
));
149 Mem_SetBlockFlags((StartBlock
+ (ReqBlocks
- 1)), BLOCK_USED_MASK
);
151 for (Handle_Number_t AllocEntry
= 0; AllocEntry
< NUM_HANDLES
; AllocEntry
++)
153 Mem_Handle_t CurrHdl
= (Mem_Handle_t
)&Mem_MemData
.Mem_Handles
[AllocEntry
];
155 if (DEREF(CurrHdl
, void*) == NULL
)
157 DEREF(CurrHdl
, void*) = &Mem_MemData
.Mem_Heap
[StartBlock
* BLOCK_SIZE
];
165 Mem_Handle_t
Mem_Realloc(Mem_Handle_t CurrAllocHdl
, const Alloc_Size_t Bytes
)
167 Mem_Free(CurrAllocHdl
);
168 return Mem_Alloc(Bytes
);
171 Mem_Handle_t
Mem_Calloc(const Alloc_Size_t Bytes
)
173 Mem_Handle_t AllocHdl
= Mem_Alloc(Bytes
);
175 if (AllocHdl
!= NULL
)
176 memset(DEREF(AllocHdl
, void*), 0x00, Bytes
);
181 void Mem_Free(Mem_Handle_t CurrAllocHdl
)
183 char* MemBlockPtr
= DEREF(CurrAllocHdl
, char*);
184 Block_Number_t CurrBlock
= ((uint16_t)(MemBlockPtr
- Mem_MemData
.Mem_Heap
) / BLOCK_SIZE
);
185 uint8_t CurrBlockFlags
;
187 if ((CurrAllocHdl
== NULL
) || (MemBlockPtr
== NULL
))
192 CurrBlockFlags
= Mem_GetBlockFlags(CurrBlock
);
193 Mem_SetBlockFlags(CurrBlock
, 0);
197 while (CurrBlockFlags
& BLOCK_LINKED_MASK
);
199 DEREF(CurrAllocHdl
, void*) = NULL
;
202 Block_Number_t
Mem_TotalFreeBlocks(void)
204 Block_Number_t FreeBlocks
= 0;
206 for (Block_Number_t CurrBlock
= 0; CurrBlock
< NUM_BLOCKS
; CurrBlock
++)
208 if (!(Mem_GetBlockFlags(CurrBlock
) & BLOCK_USED_MASK
))
215 Handle_Number_t
Mem_TotalFreeHandles(void)
217 Handle_Number_t FreeHandles
= 0;
219 for (Handle_Number_t CurrHandle
= 0; CurrHandle
< NUM_HANDLES
; CurrHandle
++)
221 if (Mem_MemData
.Mem_Handles
[CurrHandle
] == NULL
)