11#include " malloc_from_scratch/memory_allocator.h"
22#include " malloc_from_scratch/memory_internal.h"
33
4+ #include < cstdlib>
45#include < unistd.h>
56
67namespace mem
@@ -15,28 +16,117 @@ void* malloc(size_t size)
1516
1617 internal::total_memory_allocated += size;
1718
18- size_t total_size = sizeof (internal::MemoryBlock) + size;
19+ internal::MemoryBlock* found_block =
20+ internal::findLargeEnoughFreeMemoryBlock (&internal::block_list_head, size);
1921
20- void * new_memory_allocation = internal::increaseHeap (total_size);
21- if (new_memory_allocation == NULL )
22+ if (found_block != nullptr )
23+ {
24+ void * return_address = internal::splitFreeMemoryBlockIfPossible (found_block, size);
25+ return return_address;
26+ }
27+
28+ bool is_frame_used = false ;
29+ size_t total_size = 0 ;
30+ if (size < internal::CHUNK_SIZE)
2231 {
23- return NULL ;
32+ total_size = internal::BLOCK_METADATA_SIZE + internal::CHUNK_SIZE;
33+ is_frame_used = true ;
34+ }
35+ else
36+ {
37+ total_size = internal::BLOCK_METADATA_SIZE + size;
38+ is_frame_used = false ;
2439 }
2540
26- internal::MemoryBlock* new_block =
27- reinterpret_cast <internal::MemoryBlock*> (new_memory_allocation);
28- new_block-> size_ = size;
29- new_block-> allocated_ = 1 ;
30- new_block-> next_ = nullptr ;
41+ void * new_memory_allocation = internal::increaseHeap (total_size);
42+ if (new_memory_allocation == nullptr )
43+ {
44+ return nullptr ;
45+ }
3146
32- internal::insertMemoryBlockAtEnd (&internal::block_list_head, new_block);
47+ internal::MemoryBlock* new_block = internal::getMemoryBlockFromAddress (new_memory_allocation);
48+ if (is_frame_used)
49+ {
50+ new_block->size_ = internal::CHUNK_SIZE;
51+ new_block->allocated_ = false ;
52+ new_block->next_ = nullptr ;
53+ internal::insertMemoryBlockAtEnd (&internal::block_list_head, new_block);
54+ void * return_address = internal::splitFreeMemoryBlockIfPossible (new_block, size);
55+ return return_address;
56+ }
57+ else
58+ {
59+ new_block->size_ = size;
60+ new_block->allocated_ = true ;
61+ new_block->next_ = nullptr ;
62+ internal::insertMemoryBlockAtEnd (&internal::block_list_head, new_block);
63+ }
3364
3465 return internal::getPayloadAddress (new_block);
3566}
3667
3768namespace internal
3869{
3970
71+ void * increaseHeap (size_t size)
72+ {
73+ void * result = sbrk (static_cast <intptr_t >(size));
74+ if (result == getErrorCodeInVoidPtr (-1 ) || result == getErrorCodeInVoidPtr (0 ))
75+ {
76+ exit (-1 );
77+ }
78+
79+ return result;
80+ }
81+
82+ MemoryBlock* findLargeEnoughFreeMemoryBlock (MemoryBlock** block_list_head, size_t size)
83+ {
84+ MemoryBlock* current = *block_list_head;
85+ while (current != nullptr )
86+ {
87+ if (current->allocated_ == false && current->size_ >= size)
88+ {
89+ return current;
90+ }
91+ current = current->next_ ;
92+ }
93+ return nullptr ;
94+ }
95+
96+ void * splitFreeMemoryBlockIfPossible (MemoryBlock* new_block, size_t size)
97+ {
98+ if (new_block == nullptr )
99+ {
100+ return nullptr ;
101+ }
102+
103+ size_t remaining_size = new_block->size_ - size;
104+ char one_byte_payload_size_requirement = 1 ;
105+ if (remaining_size >= BLOCK_METADATA_SIZE + one_byte_payload_size_requirement)
106+ {
107+ void * split_address = getMemoryBlockSplitAddress (new_block, size);
108+ MemoryBlock* new_temp_block = getMemoryBlockFromAddress (split_address);
109+ new_temp_block->size_ = remaining_size - BLOCK_METADATA_SIZE;
110+ new_temp_block->allocated_ = false ;
111+ new_temp_block->next_ = new_block->next_ ;
112+
113+ new_block->size_ = size;
114+ new_block->allocated_ = true ;
115+ new_block->next_ = new_temp_block;
116+ }
117+ else
118+ {
119+ new_block->allocated_ = true ;
120+ }
121+
122+ return getPayloadAddress (new_block);
123+ }
124+
125+ void * getMemoryBlockSplitAddress (MemoryBlock* new_block, size_t size)
126+ {
127+ return (reinterpret_cast <char *>(getPayloadAddress (new_block)) + size);
128+ }
129+
40130void insertMemoryBlockAtEnd (MemoryBlock** block_list_head, MemoryBlock* new_block)
41131{
42132 if (*block_list_head == nullptr )
@@ -54,6 +144,7 @@ void insertMemoryBlockAtEnd(MemoryBlock** block_list_head, MemoryBlock* new_bloc
54144 }
55145}
56146
147+ // helpers
57148void * getPayloadAddress (MemoryBlock* block)
58149{
59150 if (!block)
@@ -66,26 +157,21 @@ void* getPayloadAddress(MemoryBlock* block)
66157
67158MemoryBlock* getMetadata (void * payload_address)
68159{
69- if (!payload_address)
70- {
71- return nullptr ;
72- }
73-
74160 return reinterpret_cast <MemoryBlock*>(reinterpret_cast <char *>(payload_address) -
75161 BLOCK_METADATA_SIZE);
76162}
77163
78- void * increaseHeap ( size_t size )
164+ MemoryBlock* getMemoryBlockFromAddress ( void * address )
79165{
80- void * result = sbrk (static_cast <intptr_t >(size));
81- if (result == reinterpret_cast <void *>(-1 ))
82- {
83- return nullptr ;
84- }
166+ return reinterpret_cast <MemoryBlock*>(address);
167+ }
85168
86- return result;
169+ size_t getSizeOfAllocatedMemoryBlock (MemoryBlock* block)
170+ {
171+ return reinterpret_cast <size_t >(getPayloadAddress (block));
87172}
88173
89- void * decreaseHeap (MemoryBlock* block_heap_end, size_t size) { return nullptr ; }
174+ void * getErrorCodeInVoidPtr (size_t error_code) { return reinterpret_cast <void *>(error_code); }
175+
90176} // namespace internal
91177} // namespace mem
0 commit comments