github.com/moontrade/nogc@v0.1.7/alloc/mimalloc/mimalloc.h (about)

     1  /* ----------------------------------------------------------------------------
     2  Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
     3  This is free software; you can redistribute it and/or modify it under the
     4  terms of the MIT license. A copy of the license can be found in the file
     5  "LICENSE" at the root of this distribution.
     6  -----------------------------------------------------------------------------*/
     7  #pragma once
     8  #ifndef MIMALLOC_H
     9  #define MIMALLOC_H
    10  
    11  #define MI_MALLOC_VERSION 171   // major + 2 digits minor
    12  
    13  // ------------------------------------------------------
    14  // Compiler specific attributes
    15  // ------------------------------------------------------
    16  
    17  #ifdef __cplusplus
    18    #if (__cplusplus >= 201103L) || (_MSC_VER > 1900)  // C++11
    19      #define mi_attr_noexcept   noexcept
    20    #else
    21      #define mi_attr_noexcept   throw()
    22    #endif
    23  #else
    24    #define mi_attr_noexcept
    25  #endif
    26  
    27  #if defined(__cplusplus) && (__cplusplus >= 201703)
    28    #define mi_decl_nodiscard    [[nodiscard]]
    29  #elif (__GNUC__ >= 4) || defined(__clang__)  // includes clang, icc, and clang-cl
    30    #define mi_decl_nodiscard    __attribute__((warn_unused_result))
    31  #elif (_MSC_VER >= 1700)
    32    #define mi_decl_nodiscard    _Check_return_
    33  #else
    34    #define mi_decl_nodiscard
    35  #endif
    36  
    37  #if defined(_MSC_VER) || defined(__MINGW32__)
    38    #if !defined(MI_SHARED_LIB)
    39      #define mi_decl_export
    40    #elif defined(MI_SHARED_LIB_EXPORT)
    41      #define mi_decl_export              __declspec(dllexport)
    42    #else
    43      #define mi_decl_export              __declspec(dllimport)
    44    #endif
    45    #if defined(__MINGW32__)
    46      #define mi_decl_restrict
    47      #define mi_attr_malloc              __attribute__((malloc))
    48    #else
    49      #if (_MSC_VER >= 1900) && !defined(__EDG__)
    50        #define mi_decl_restrict          __declspec(allocator) __declspec(restrict)
    51      #else
    52        #define mi_decl_restrict          __declspec(restrict)
    53      #endif
    54      #define mi_attr_malloc
    55    #endif
    56    #define mi_cdecl                      __cdecl
    57    #define mi_attr_alloc_size(s)
    58    #define mi_attr_alloc_size2(s1,s2)
    59    #define mi_attr_alloc_align(p)
    60  #elif defined(__GNUC__)                 // includes clang and icc
    61    #define mi_cdecl                      // leads to warnings... __attribute__((cdecl))
    62    #define mi_decl_export                __attribute__((visibility("default")))
    63    #define mi_decl_restrict
    64    #define mi_attr_malloc                __attribute__((malloc))
    65    #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5)
    66      #define mi_attr_alloc_size(s)
    67      #define mi_attr_alloc_size2(s1,s2)
    68      #define mi_attr_alloc_align(p)
    69    #elif defined(__INTEL_COMPILER)
    70      #define mi_attr_alloc_size(s)       __attribute__((alloc_size(s)))
    71      #define mi_attr_alloc_size2(s1,s2)  __attribute__((alloc_size(s1,s2)))
    72      #define mi_attr_alloc_align(p)
    73    #else
    74      #define mi_attr_alloc_size(s)       __attribute__((alloc_size(s)))
    75      #define mi_attr_alloc_size2(s1,s2)  __attribute__((alloc_size(s1,s2)))
    76      #define mi_attr_alloc_align(p)      __attribute__((alloc_align(p)))
    77    #endif
    78  #else
    79    #define mi_cdecl
    80    #define mi_decl_export
    81    #define mi_decl_restrict
    82    #define mi_attr_malloc
    83    #define mi_attr_alloc_size(s)
    84    #define mi_attr_alloc_size2(s1,s2)
    85    #define mi_attr_alloc_align(p)
    86  #endif
    87  
    88  // ------------------------------------------------------
    89  // Includes
    90  // ------------------------------------------------------
    91  
    92  #include <stddef.h>     // size_t
    93  #include <stdbool.h>    // bool
    94  
    95  #ifdef __cplusplus
    96  extern "C" {
    97  #endif
    98  
    99  // ------------------------------------------------------
   100  // Standard malloc interface
   101  // ------------------------------------------------------
   102  
   103  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc(size_t size)  mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   104  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc(size_t count, size_t size)  mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
   105  mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize)      mi_attr_noexcept mi_attr_alloc_size(2);
   106  mi_decl_export void* mi_expand(void* p, size_t newsize)                         mi_attr_noexcept mi_attr_alloc_size(2);
   107  
   108  mi_decl_export void mi_free(void* p) mi_attr_noexcept;
   109  mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc;
   110  mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
   111  mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
   112  
   113  // ------------------------------------------------------
   114  // Extended functionality
   115  // ------------------------------------------------------
   116  #define MI_SMALL_WSIZE_MAX  (128)
   117  #define MI_SMALL_SIZE_MAX   (MI_SMALL_WSIZE_MAX*sizeof(void*))
   118  
   119  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   120  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   121  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc(size_t size)       mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   122  
   123  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
   124  mi_decl_nodiscard mi_decl_export void* mi_reallocn(void* p, size_t count, size_t size)        mi_attr_noexcept mi_attr_alloc_size2(2,3);
   125  mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize)                   mi_attr_noexcept mi_attr_alloc_size(2);
   126  
   127  mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
   128  mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size)     mi_attr_noexcept;
   129  
   130  
   131  // ------------------------------------------------------
   132  // Internals
   133  // ------------------------------------------------------
   134  
   135  typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg);
   136  mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept;
   137  
   138  typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg);
   139  mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept;
   140  
   141  typedef void (mi_cdecl mi_error_fun)(int err, void* arg);
   142  mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg);
   143  
   144  mi_decl_export void mi_collect(bool force)    mi_attr_noexcept;
   145  mi_decl_export int  mi_version(void)          mi_attr_noexcept;
   146  mi_decl_export void mi_stats_reset(void)      mi_attr_noexcept;
   147  mi_decl_export void mi_stats_merge(void)      mi_attr_noexcept;
   148  mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept;  // backward compatibility: `out` is ignored and should be NULL
   149  mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
   150  
   151  mi_decl_export void mi_process_init(void)     mi_attr_noexcept;
   152  mi_decl_export void mi_thread_init(void)      mi_attr_noexcept;
   153  mi_decl_export void mi_thread_done(void)      mi_attr_noexcept;
   154  mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
   155  
   156  mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, 
   157                                      size_t* current_rss, size_t* peak_rss, 
   158                                      size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept;
   159  
   160  // -------------------------------------------------------------------------------------
   161  // Aligned allocation
   162  // Note that `alignment` always follows `size` for consistency with unaligned
   163  // allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
   164  // -------------------------------------------------------------------------------------
   165  
   166  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
   167  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   168  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
   169  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   170  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2) mi_attr_alloc_align(3);
   171  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
   172  mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3);
   173  mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2);
   174  
   175  
   176  // -------------------------------------------------------------------------------------
   177  // Heaps: first-class, but can only allocate from the same thread that created it.
   178  // -------------------------------------------------------------------------------------
   179  
   180  struct mi_heap_s;
   181  typedef struct mi_heap_s mi_heap_t;
   182  
   183  mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void);
   184  mi_decl_export void       mi_heap_delete(mi_heap_t* heap);
   185  mi_decl_export void       mi_heap_destroy(mi_heap_t* heap);
   186  mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap);
   187  mi_decl_export mi_heap_t* mi_heap_get_default(void);
   188  mi_decl_export mi_heap_t* mi_heap_get_backing(void);
   189  mi_decl_export void       mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept;
   190  
   191  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
   192  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
   193  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
   194  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
   195  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
   196  
   197  mi_decl_nodiscard mi_decl_export void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize)              mi_attr_noexcept mi_attr_alloc_size(3);
   198  mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size)  mi_attr_noexcept mi_attr_alloc_size2(3,4);
   199  mi_decl_nodiscard mi_decl_export void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize)             mi_attr_noexcept mi_attr_alloc_size(3);
   200  
   201  mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s)            mi_attr_noexcept mi_attr_malloc;
   202  mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
   203  mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
   204  
   205  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3);
   206  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
   207  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3);
   208  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
   209  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3) mi_attr_alloc_align(4);
   210  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
   211  mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4);
   212  mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3);
   213  
   214  
   215  // --------------------------------------------------------------------------------
   216  // Zero initialized re-allocation.
   217  // Only valid on memory that was originally allocated with zero initialization too.
   218  // e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
   219  // see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
   220  // --------------------------------------------------------------------------------
   221  
   222  mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize)                mi_attr_noexcept mi_attr_alloc_size(2);
   223  mi_decl_nodiscard mi_decl_export void* mi_recalloc(void* p, size_t newcount, size_t size)  mi_attr_noexcept mi_attr_alloc_size2(2,3);
   224  
   225  mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3);
   226  mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2);
   227  mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(2,3) mi_attr_alloc_align(4);
   228  mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(2,3);
   229  
   230  mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize)                mi_attr_noexcept mi_attr_alloc_size(3);
   231  mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size)  mi_attr_noexcept mi_attr_alloc_size2(3,4);
   232  
   233  mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4);
   234  mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3);
   235  mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(3,4) mi_attr_alloc_align(5);
   236  mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(3,4);
   237  
   238  
   239  // ------------------------------------------------------
   240  // Analysis
   241  // ------------------------------------------------------
   242  
   243  mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p);
   244  mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p);
   245  mi_decl_export bool mi_check_owned(const void* p);
   246  
   247  // An area of heap space contains blocks of a single size.
   248  typedef struct mi_heap_area_s {
   249    void*  blocks;      // start of the area containing heap blocks
   250    size_t reserved;    // bytes reserved for this area (virtual)
   251    size_t committed;   // current available bytes for this area
   252    size_t used;        // bytes in use by allocated blocks
   253    size_t block_size;  // size in bytes of each block
   254  } mi_heap_area_t;
   255  
   256  typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg);
   257  
   258  mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
   259  
   260  // Experimental
   261  mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
   262  mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept;
   263  
   264  mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept;
   265  mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept;
   266  
   267  mi_decl_export int  mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
   268  mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept;
   269  
   270  
   271  // deprecated
   272  mi_decl_export int  mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
   273  
   274  
   275  // ------------------------------------------------------
   276  // Convenience
   277  // ------------------------------------------------------
   278  
   279  #define mi_malloc_tp(tp)                ((tp*)mi_malloc(sizeof(tp)))
   280  #define mi_zalloc_tp(tp)                ((tp*)mi_zalloc(sizeof(tp)))
   281  #define mi_calloc_tp(tp,n)              ((tp*)mi_calloc(n,sizeof(tp)))
   282  #define mi_mallocn_tp(tp,n)             ((tp*)mi_mallocn(n,sizeof(tp)))
   283  #define mi_reallocn_tp(p,tp,n)          ((tp*)mi_reallocn(p,n,sizeof(tp)))
   284  #define mi_recalloc_tp(p,tp,n)          ((tp*)mi_recalloc(p,n,sizeof(tp)))
   285  
   286  #define mi_heap_malloc_tp(hp,tp)        ((tp*)mi_heap_malloc(hp,sizeof(tp)))
   287  #define mi_heap_zalloc_tp(hp,tp)        ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
   288  #define mi_heap_calloc_tp(hp,tp,n)      ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
   289  #define mi_heap_mallocn_tp(hp,tp,n)     ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
   290  #define mi_heap_reallocn_tp(hp,p,tp,n)  ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp)))
   291  #define mi_heap_recalloc_tp(hp,p,tp,n)  ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp)))
   292  
   293  
   294  // ------------------------------------------------------
   295  // Options, all `false` by default
   296  // ------------------------------------------------------
   297  
   298  typedef enum mi_option_e {
   299    // stable options
   300    mi_option_show_errors,
   301    mi_option_show_stats,
   302    mi_option_verbose,
   303    // the following options are experimental
   304    mi_option_eager_commit,
   305    mi_option_eager_region_commit,
   306    mi_option_reset_decommits,
   307    mi_option_large_os_pages,         // implies eager commit
   308    mi_option_reserve_huge_os_pages,
   309    mi_option_reserve_os_memory,
   310    mi_option_segment_cache,
   311    mi_option_page_reset,
   312    mi_option_abandoned_page_reset,
   313    mi_option_segment_reset,
   314    mi_option_eager_commit_delay,
   315    mi_option_reset_delay,
   316    mi_option_use_numa_nodes,
   317    mi_option_limit_os_alloc,
   318    mi_option_os_tag,
   319    mi_option_max_errors,
   320    mi_option_max_warnings,
   321    _mi_option_last
   322  } mi_option_t;
   323  
   324  
   325  mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option);
   326  mi_decl_export void mi_option_enable(mi_option_t option);
   327  mi_decl_export void mi_option_disable(mi_option_t option);
   328  mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable);
   329  mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable);
   330  
   331  mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option);
   332  mi_decl_export void mi_option_set(mi_option_t option, long value);
   333  mi_decl_export void mi_option_set_default(mi_option_t option, long value);
   334  
   335  
   336  // -------------------------------------------------------------------------------------------------------
   337  // "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions.
   338  // (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.)
   339  // note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing.
   340  // -------------------------------------------------------------------------------------------------------
   341  
   342  mi_decl_export void  mi_cfree(void* p) mi_attr_noexcept;
   343  mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
   344  mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p)        mi_attr_noexcept;
   345  mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
   346  
   347  mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size)   mi_attr_noexcept;
   348  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1);
   349  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_valloc(size_t size)  mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   350  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   351  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1);
   352  
   353  mi_decl_nodiscard mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
   354  mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
   355  mi_decl_nodiscard mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept;
   356  
   357  mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc;
   358  mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char*  mi_mbsdup(const unsigned char* s)  mi_attr_noexcept mi_attr_malloc;
   359  mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name)                      mi_attr_noexcept;
   360  mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept;
   361  
   362  mi_decl_export void mi_free_size(void* p, size_t size)                           mi_attr_noexcept;
   363  mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept;
   364  mi_decl_export void mi_free_aligned(void* p, size_t alignment)                   mi_attr_noexcept;
   365  
   366  // The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`.
   367  // (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception).
   368  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size)                   mi_attr_malloc mi_attr_alloc_size(1);
   369  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
   370  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_nothrow(size_t size)           mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
   371  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
   372  mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_n(size_t count, size_t size)   mi_attr_malloc mi_attr_alloc_size2(1, 2);
   373  mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize)                mi_attr_alloc_size(2);
   374  mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3);
   375  
   376  #ifdef __cplusplus
   377  }
   378  #endif
   379  
   380  // ---------------------------------------------------------------------------------------------
   381  // Implement the C++ std::allocator interface for use in STL containers.
   382  // (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally)
   383  // ---------------------------------------------------------------------------------------------
   384  #ifdef __cplusplus
   385  
   386  #include <cstdint>     // PTRDIFF_MAX
   387  #if (__cplusplus >= 201103L) || (_MSC_VER > 1900)  // C++11
   388  #include <type_traits> // std::true_type
   389  #include <utility>     // std::forward
   390  #endif
   391  
   392  template<class T> struct mi_stl_allocator {
   393    typedef T                 value_type;
   394    typedef std::size_t       size_type;
   395    typedef std::ptrdiff_t    difference_type;
   396    typedef value_type&       reference;
   397    typedef value_type const& const_reference;
   398    typedef value_type*       pointer;
   399    typedef value_type const* const_pointer;
   400    template <class U> struct rebind { typedef mi_stl_allocator<U> other; };
   401  
   402    mi_stl_allocator()                                             mi_attr_noexcept = default;
   403    mi_stl_allocator(const mi_stl_allocator&)                      mi_attr_noexcept = default;
   404    template<class U> mi_stl_allocator(const mi_stl_allocator<U>&) mi_attr_noexcept { }
   405    mi_stl_allocator  select_on_container_copy_construction() const { return *this; }
   406    void              deallocate(T* p, size_type) { mi_free(p); }
   407  
   408    #if (__cplusplus >= 201703L)  // C++17
   409    mi_decl_nodiscard T* allocate(size_type count) { return static_cast<T*>(mi_new_n(count, sizeof(T))); }
   410    mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); }
   411    #else
   412    mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast<pointer>(mi_new_n(count, sizeof(value_type))); }
   413    #endif
   414  
   415    #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900))  // C++11
   416    using propagate_on_container_copy_assignment = std::true_type;
   417    using propagate_on_container_move_assignment = std::true_type;
   418    using propagate_on_container_swap            = std::true_type;
   419    using is_always_equal                        = std::true_type;
   420    template <class U, class ...Args> void construct(U* p, Args&& ...args) { ::new(p) U(std::forward<Args>(args)...); }
   421    template <class U> void destroy(U* p) mi_attr_noexcept { p->~U(); }
   422    #else
   423    void construct(pointer p, value_type const& val) { ::new(p) value_type(val); }
   424    void destroy(pointer p) { p->~value_type(); }
   425    #endif
   426  
   427    size_type     max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); }
   428    pointer       address(reference x) const        { return &x; }
   429    const_pointer address(const_reference x) const  { return &x; }
   430  };
   431  
   432  template<class T1,class T2> bool operator==(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return true; }
   433  template<class T1,class T2> bool operator!=(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return false; }
   434  #endif // __cplusplus
   435  
   436  #endif