diff --git a/include/tlsf.h b/include/tlsf.h index e860963b3..94bd67a36 100644 --- a/include/tlsf.h +++ b/include/tlsf.h @@ -7,14 +7,19 @@ #ifndef INCLUDED_tlsf #define INCLUDED_tlsf +#include #include #include -#include "tlsf_common.h" #if defined(__cplusplus) extern "C" { #endif +/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */ +/* pool_t: a block of memory that TLSF can manage. */ +typedef void* tlsf_t; +typedef void* pool_t; + /* Create/destroy a memory pool. */ tlsf_t tlsf_create(void* mem, size_t max_bytes); tlsf_t tlsf_create_with_pool(void* mem, size_t pool_bytes, size_t max_bytes); diff --git a/include/tlsf_common.h b/include/tlsf_common.h deleted file mode 100644 index 183494c29..000000000 --- a/include/tlsf_common.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2006-2016 Matthew Conte - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#pragma once -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/* -** Constants definition for poisoning. -** These defines are used as 3rd argument of tlsf_poison_fill_region() for readability purposes. -*/ -#define POISONING_AFTER_FREE true -#define POISONING_AFTER_MALLOC !POISONING_AFTER_FREE - -/* -** Cast and min/max macros. -*/ -#define tlsf_cast(t, exp) ((t) (exp)) -#define tlsf_min(a, b) ((a) < (b) ? (a) : (b)) -#define tlsf_max(a, b) ((a) > (b) ? (a) : (b)) - -/* -** Set assert macro, if it has not been provided by the user. -*/ -#if !defined (tlsf_assert) -#define tlsf_assert assert -#endif - -enum tlsf_config -{ - /* All allocation sizes and addresses are aligned to 4 bytes. */ - ALIGN_SIZE_LOG2 = 2, - ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2), -}; - -/* -** Data structures and associated constants. -*/ - -/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */ -/* pool_t: a block of memory that TLSF can manage. */ -typedef void* tlsf_t; -typedef void* pool_t; - -/* A type used for casting when doing pointer arithmetic. */ -typedef ptrdiff_t tlsfptr_t; - -typedef struct block_header_t -{ - /* Points to the previous physical block. */ - struct block_header_t* prev_phys_block; - - /* The size of this block, excluding the block header. */ - size_t size; - - /* Next and previous free blocks. */ - struct block_header_t* next_free; - struct block_header_t* prev_free; -} block_header_t; - -/* -** Since block sizes are always at least a multiple of 4, the two least -** significant bits of the size field are used to store the block status: -** - bit 0: whether block is busy or free -** - bit 1: whether previous block is busy or free -*/ -static const size_t block_header_free_bit = 1 << 0; -static const size_t block_header_prev_free_bit = 1 << 1; - -/* -** The size of the block header exposed to used blocks is the size field. -** The prev_phys_block field is stored *inside* the previous free block. -*/ -static const size_t block_header_overhead = sizeof(size_t); - -/* User data starts directly after the size field in a used block. */ -static const size_t block_start_offset = - offsetof(block_header_t, size) + sizeof(size_t); - -/* -** A free block must be large enough to store its header minus the size of -** the prev_phys_block field, and no larger than the number of addressable -** bits for FL_INDEX. -*/ -static const size_t block_size_min = - sizeof(block_header_t) - sizeof(block_header_t*); - -/* The TLSF control structure. */ -typedef struct control_t -{ - /* Empty lists point at this block to indicate they are free. */ - block_header_t block_null; - - /* Local parameter for the pool. Given the maximum - * value of each field, all the following parameters - * can fit on 4 bytes when using bitfields - */ - unsigned int fl_index_count : 5; // 5 cumulated bits - unsigned int fl_index_shift : 3; // 8 cumulated bits - unsigned int fl_index_max : 6; // 14 cumulated bits - unsigned int sl_index_count : 6; // 20 cumulated bits - - /* log2 of number of linear subdivisions of block sizes. Larger - ** values require more memory in the control structure. Values of - ** 4 or 5 are typical. - */ - unsigned int sl_index_count_log2 : 3; // 23 cumulated bits - unsigned int small_block_size : 8; // 31 cumulated bits - - /* size of the metadata ( size of control block, - * sl_bitmap and blocks ) - */ - size_t size; - - /* Bitmaps for free lists. */ - unsigned int fl_bitmap; - unsigned int *sl_bitmap; - - /* Head of free lists. */ - block_header_t** blocks; -} control_t; - -#if defined(__cplusplus) -}; -#endif diff --git a/tlsf.c b/tlsf.c index 19c65861a..23c5aa32a 100644 --- a/tlsf.c +++ b/tlsf.c @@ -8,7 +8,6 @@ #include #include #include "tlsf.h" -#include "tlsf_common.h" #include "tlsf_block_functions.h" #include "tlsf_control_functions.h" diff --git a/include/tlsf_block_functions.h b/tlsf_block_functions.h similarity index 64% rename from include/tlsf_block_functions.h rename to tlsf_block_functions.h index e2cb06b60..d801442d7 100644 --- a/include/tlsf_block_functions.h +++ b/tlsf_block_functions.h @@ -5,12 +5,79 @@ */ #pragma once -#include "tlsf_common.h" #if defined(__cplusplus) extern "C" { #endif +/* +** Constants definition for poisoning. +** These defines are used as 3rd argument of tlsf_poison_fill_region() for readability purposes. +*/ +#define POISONING_AFTER_FREE true +#define POISONING_AFTER_MALLOC !POISONING_AFTER_FREE + +/* A type used for casting when doing pointer arithmetic. */ +typedef ptrdiff_t tlsfptr_t; + +/* +** Cast and min/max macros. +*/ +#if !defined (tlsf_cast) +#define tlsf_cast(t, exp) ((t) (exp)) +#endif +#if !defined (tlsf_min) +#define tlsf_min(a, b) ((a) < (b) ? (a) : (b)) +#endif +#if !defined (tlsf_max) +#define tlsf_max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/* +** Set assert macro, if it has not been provided by the user. +*/ +#if !defined (tlsf_assert) +#define tlsf_assert assert +#endif + +typedef struct block_header_t +{ + /* Points to the previous physical block. */ + struct block_header_t* prev_phys_block; + + /* The size of this block, excluding the block header. */ + size_t size; + + /* Next and previous free blocks. */ + struct block_header_t* next_free; + struct block_header_t* prev_free; +} block_header_t; + +/* User data starts directly after the size field in a used block. */ +#define block_start_offset (offsetof(block_header_t, size) + sizeof(size_t)) + +/* +** A free block must be large enough to store its header minus the size of +** the prev_phys_block field, and no larger than the number of addressable +** bits for FL_INDEX. +*/ +#define block_size_min (sizeof(block_header_t) - sizeof(block_header_t*)) + +/* +** Since block sizes are always at least a multiple of 4, the two least +** significant bits of the size field are used to store the block status: +** - bit 0: whether block is busy or free +** - bit 1: whether previous block is busy or free +*/ +#define block_header_free_bit (1UL << 0) +#define block_header_prev_free_bit (1UL << 1) + +/* +** The size of the block header exposed to used blocks is the size field. +** The prev_phys_block field is stored *inside* the previous free block. +*/ +#define block_header_overhead (sizeof(size_t)) + /* ** block_header_t member functions. */ diff --git a/include/tlsf_control_functions.h b/tlsf_control_functions.h similarity index 92% rename from include/tlsf_control_functions.h rename to tlsf_control_functions.h index 9a57f8849..1ed344359 100644 --- a/include/tlsf_control_functions.h +++ b/tlsf_control_functions.h @@ -5,7 +5,6 @@ */ #pragma once -#include "tlsf_common.h" #include "tlsf_block_functions.h" #if defined(__cplusplus) @@ -15,6 +14,48 @@ extern "C" { #define tlsf_decl static inline __attribute__((always_inline)) #endif +enum tlsf_config +{ + /* All allocation sizes and addresses are aligned to 4 bytes. */ + ALIGN_SIZE_LOG2 = 2, + ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2), +}; + +/* The TLSF control structure. */ +typedef struct control_t +{ + /* Empty lists point at this block to indicate they are free. */ + block_header_t block_null; + + /* Local parameter for the pool. Given the maximum + * value of each field, all the following parameters + * can fit on 4 bytes when using bitfields + */ + unsigned int fl_index_count : 5; // 5 cumulated bits + unsigned int fl_index_shift : 3; // 8 cumulated bits + unsigned int fl_index_max : 6; // 14 cumulated bits + unsigned int sl_index_count : 6; // 20 cumulated bits + + /* log2 of number of linear subdivisions of block sizes. Larger + ** values require more memory in the control structure. Values of + ** 4 or 5 are typical. + */ + unsigned int sl_index_count_log2 : 3; // 23 cumulated bits + unsigned int small_block_size : 8; // 31 cumulated bits + + /* size of the metadata ( size of control block, + * sl_bitmap and blocks ) + */ + size_t size; + + /* Bitmaps for free lists. */ + unsigned int fl_bitmap; + unsigned int *sl_bitmap; + + /* Head of free lists. */ + block_header_t** blocks; +} control_t; + /* ** Architecture-specific bit manipulation routines. ** @@ -227,13 +268,12 @@ tlsf_decl size_t tlsf_block_size_min(void) return block_size_min; } -tlsf_decl size_t tlsf_block_size_max(tlsf_t tlsf) +tlsf_decl size_t tlsf_block_size_max(control_t *control) { - if (tlsf == NULL) + if (control == NULL) { return 0; } - control_t* control = tlsf_cast(control_t*, tlsf); return tlsf_cast(size_t, 1) << control->fl_index_max; } @@ -241,7 +281,7 @@ tlsf_decl size_t tlsf_block_size_max(tlsf_t tlsf) ** Adjust an allocation size to be aligned to word size, and no smaller ** than internal minimum. */ -tlsf_decl size_t adjust_request_size(tlsf_t tlsf, size_t size, size_t align) +tlsf_decl size_t adjust_request_size(control_t *control, size_t size, size_t align) { size_t adjust = 0; if (size) @@ -249,7 +289,7 @@ tlsf_decl size_t adjust_request_size(tlsf_t tlsf, size_t size, size_t align) const size_t aligned = align_up(size, align); /* aligned sized must not exceed block_size_max or we'll go out of bounds on sl_bitmap */ - if (aligned < tlsf_block_size_max(tlsf)) + if (aligned < tlsf_block_size_max(control)) { adjust = tlsf_max(aligned, block_size_min); }