Add memory sizing/alignment helpers to util.cc/h

This functionality previously lived in the CompHash class, with one difference:
this removes a discrepancy between the offset aligner and the memory pointer
aligner/padder. The size aligner used to align the provided offset and then add an
additional alignment size (for example, 1 aligned to 4 wouldn't yield 4 but 8).
Like the memory aligners it now only rounds up as needed.

Includes unit tests.
This commit is contained in:
Christian Kreibich 2021-09-16 17:15:30 -07:00
parent 5fc8d89897
commit c5cceaf5ad
2 changed files with 69 additions and 0 deletions

View file

@ -2187,6 +2187,57 @@ void safe_close(int fd)
}
}
const void* memory_align(const void* ptr, size_t size)
{
if ( ! size )
return ptr;
ASSERT(is_power_of_2(size));
const char* buf = reinterpret_cast<const char*>(ptr);
size_t mask = size - 1; // Assume size is a power of 2.
unsigned long l_ptr = reinterpret_cast<unsigned long>(ptr);
unsigned long offset = l_ptr & mask;
if ( offset > 0 )
return reinterpret_cast<const void*>(buf - offset + size);
else
return reinterpret_cast<const void*>(buf);
}
void* memory_align_and_pad(void* ptr, size_t size)
{
if ( ! size )
return ptr;
ASSERT(is_power_of_2(size));
char* buf = reinterpret_cast<char*>(ptr);
size_t mask = size - 1;
while ( (reinterpret_cast<unsigned long>(buf) & mask) != 0 )
// Not aligned - zero pad.
*buf++ = '\0';
return reinterpret_cast<void*>(buf);
}
int memory_size_align(size_t offset, size_t size)
{
if ( ! size || ! offset )
return offset;
ASSERT(is_power_of_2(size));
size_t mask = size - 1; // Assume size is a power of 2.
if ( offset & mask )
{
offset &= ~mask; // Round down.
offset += size; // Round up.
}
return offset;
}
void get_memory_usage(uint64_t* total, uint64_t* malloced)
{
uint64_t ret_total;

View file

@ -493,6 +493,24 @@ inline char* safe_strncpy(char* dest, const char* src, size_t n)
return result;
}
// Memory alignment helpers.
inline bool is_power_of_2(bro_uint_t x)
{
return ((x - 1) & x) == 0;
}
// Rounds the given pointer up to the nearest multiple of the
// given size, if not already a multiple.
const void* memory_align(const void* ptr, size_t size);
// Rounds the given pointer up to the nearest multiple of the
// given size, padding the skipped region with 0 bytes.
void* memory_align_and_pad(void* ptr, size_t size);
// Returns offset rounded up so it can correctly align data of the given size.
int memory_size_align(size_t offset, size_t size);
// Returns total memory allocations and (if available) amount actually
// handed out by malloc.
extern void get_memory_usage(uint64_t* total, uint64_t* malloced);