1
0
mirror of https://github.com/adtools/clib2.git synced 2025-12-08 14:59:05 +00:00

Slab allocator update

Added more consistency checking to the slab allocator, which is built if DEBUG is defined in "stdlib_slab.c".

Memory allocations are no longer guaranteed to be aligned to 64 bit word boundaries. In fact, this has not even worked reliably in the past 10 years.

Memory allocation request sizes are now rounded to multiples of 32 bit words (the size of an address pointer) instead to the size of a 64 bit word.

Reduced the memory footprint of the memory allocation management data structures by reusing the most significant bit of the memory allocation size. This allows many more allocations to fit into the 32 byte chunk slabs, but limits the maximum memory allocation size to a little less than 2 GBytes.

Added integer overflow checks to the memory management code.

Reduced the memory management overhead further. This cuts an additional 8 bytes per allocation, unless neither the slab allocator nor memory pools are available. With this reduction the slab allocator is able to use 16 byte chunks, which cover memory allocation requests of 1..8 bytes.

Fixed a bug caused by returning an allocation back to a slab which passed the wrong pointer.
This commit is contained in:
Olaf Barthel
2016-11-23 16:37:46 +01:00
parent f8cf752e6a
commit d2acae7cd7
19 changed files with 375 additions and 155 deletions

View File

@ -31,6 +31,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
/*#define DEBUG*/
#ifndef _STDLIB_HEADERS_H
#include "stdlib_headers.h"
#endif /* _STDLIB_HEADERS_H */
@ -72,25 +74,6 @@ struct MinList NOCOMMON __memory_list;
/****************************************************************************/
size_t
__get_allocation_size(size_t size)
{
#ifndef __MEM_DEBUG
{
size_t total_allocation_size;
total_allocation_size = sizeof(struct MemoryNode) + size;
/* Round up the allocation size to the physical allocation granularity. */
size += ((total_allocation_size + MEM_BLOCKMASK) & ~((ULONG)MEM_BLOCKMASK)) - total_allocation_size;
}
#endif /* __MEM_DEBUG */
return(size);
}
/****************************************************************************/
void *
__allocate_memory(size_t size,BOOL never_free,const char * UNUSED debug_file_name,int UNUSED debug_line_number)
{
@ -135,13 +118,32 @@ __allocate_memory(size_t size,BOOL never_free,const char * UNUSED debug_file_nam
}
#else
{
/* Round up the allocation size to the physical allocation granularity. */
size = __get_allocation_size(size);
/* Round up allocation to a multiple of 32 bits. */
if((size & 3) != 0)
size += 4 - (size & 3);
allocation_size = sizeof(*mn) + size;
}
#endif /* __MEM_DEBUG */
/* Integer overflow has occured? */
if(size == 0 || allocation_size < size)
{
__set_errno(ENOMEM);
goto out;
}
/* We reuse the MemoryNode.mn_Size field to mark
* allocations are not suitable for use with
* free() and realloc(). This limits allocation
* sizes to a little less than 2 GBytes.
*/
if(allocation_size & MN_SIZE_NEVERFREE)
{
__set_errno(ENOMEM);
goto out;
}
#if defined(__USE_SLAB_ALLOCATOR)
{
/* Are we using the slab allocator? */
@ -155,15 +157,27 @@ __allocate_memory(size_t size,BOOL never_free,const char * UNUSED debug_file_nam
}
else
{
#if defined(__amigaos4__)
{
mn = AllocMem(allocation_size,MEMF_PRIVATE);
}
#else
#ifdef __MEM_DEBUG
{
mn = AllocMem(allocation_size,MEMF_ANY);
}
#endif /* __amigaos4__ */
#else
{
struct MinNode * mln;
mln = AllocMem(sizeof(*mln) + allocation_size,MEMF_ANY);
if(mln != NULL)
{
AddTail((struct List *)&__memory_list,(struct Node *)mln);
mn = (struct MemoryNode *)&mln[1];
}
else
{
mn = NULL;
}
}
#endif /* __MEM_DEBUG */
}
}
#else
@ -174,15 +188,27 @@ __allocate_memory(size_t size,BOOL never_free,const char * UNUSED debug_file_nam
}
else
{
#if defined(__amigaos4__)
{
mn = AllocMem(allocation_size,MEMF_PRIVATE);
}
#else
#ifdef __MEM_DEBUG
{
mn = AllocMem(allocation_size,MEMF_ANY);
}
#endif /* __amigaos4__ */
#else
{
struct MinNode * mln;
mln = AllocMem(sizeof(*mln) + allocation_size,MEMF_ANY);
if(mln != NULL)
{
AddTail((struct List *)&__memory_list,(struct Node *)mln);
mn = (struct MemoryNode *)&mln[1];
}
else
{
mn = NULL;
}
}
#endif /* __MEM_DEBUG */
}
}
#endif /* __USE_SLAB_ALLOCATOR */
@ -193,10 +219,10 @@ __allocate_memory(size_t size,BOOL never_free,const char * UNUSED debug_file_nam
goto out;
}
mn->mn_Size = size;
mn->mn_NeverFree = never_free;
mn->mn_Size = size;
AddTail((struct List *)&__memory_list,(struct Node *)mn);
if(never_free)
SET_FLAG(mn->mn_Size, MN_SIZE_NEVERFREE);
__current_memory_allocated += allocation_size;
if(__maximum_memory_allocated < __current_memory_allocated)
@ -212,6 +238,8 @@ __allocate_memory(size_t size,BOOL never_free,const char * UNUSED debug_file_nam
char * body = head + MALLOC_HEAD_SIZE;
char * tail = body + size;
AddTail((struct List *)&__memory_list,(struct Node *)mn);
mn->mn_AlreadyFree = FALSE;
mn->mn_Allocation = body;
mn->mn_AllocationSize = allocation_size;