2023-10-30 08:43:11 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/* ----------------------------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Copyright  ( c )  2018 - 2021 ,  Microsoft  Research ,  Daan  Leijen  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								This  is  free  software ;  you  can  redistribute  it  and / or  modify  it  under  the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								terms  of  the  MIT  license .  A  copy  of  the  license  can  be  found  in  the  file  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								" LICENSE "  at  the  root  of  this  distribution .  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "mimalloc.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "mimalloc/internal.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "mimalloc/atomic.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "mimalloc/prim.h"  // mi_prim_out_stderr 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdio.h>      // FILE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdlib.h>     // abort 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdarg.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  long  mi_max_error_count    =  16 ;  // stop outputting errors after this (use < 0 for no limit)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  long  mi_max_warning_count  =  16 ;  // stop outputting warnings after this (use < 0 for no limit)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_add_stderr_output ( void ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  mi_version ( void )  mi_attr_noexcept  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  MI_MALLOC_VERSION ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Options
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// These can be accessed by multiple threads and may be
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// concurrently initialized, but an initializing data race
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// is ok since they resolve to the same value.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  enum  mi_init_e  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  UNINIT ,        // not yet initialized
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DEFAULTED ,     // not found in the environment, use default value
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  INITIALIZED    // found in environment or set explicitly
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  mi_init_t ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  struct  mi_option_desc_s  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  long         value ;   // the value
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_init_t    init ;    // is it initialized yet? (from the environment)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_t  option ;  // for debugging: the option index should match the option
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  char *  name ;    // option name without `mimalloc_` prefix
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  char *  legacy_name ;  // potential legacy option name
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  mi_option_desc_t ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MI_OPTION(opt)                  mi_option_##opt, #opt, NULL 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MI_OPTION_LEGACY(opt,legacy)    mi_option_##opt, #opt, #legacy 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  mi_option_desc_t  options [ _mi_option_last ]  =  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // stable options
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # if MI_DEBUG || defined(MI_SHOW_ERRORS) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  1 ,  UNINIT ,  MI_OPTION ( show_errors )  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # else 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( show_errors )  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( show_stats )  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( verbose )  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // the following options are experimental and not all combinations make sense.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  1 ,  UNINIT ,  MI_OPTION ( eager_commit )  } ,                // commit per segment directly (4MiB)  (but see also `eager_commit_delay`)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  2 ,  UNINIT ,  MI_OPTION_LEGACY ( arena_eager_commit , eager_region_commit )  } ,  // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  1 ,  UNINIT ,  MI_OPTION_LEGACY ( purge_decommits , reset_decommits )  } ,         // purge decommits memory (instead of reset) (note: on linux this uses MADV_DONTNEED for decommit)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION_LEGACY ( allow_large_os_pages , large_os_pages )  } ,     // use large OS pages, use only with eager commit to prevent fragmentation of VMA's
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( reserve_huge_os_pages )  } ,       // per 1GiB huge pages
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  { - 1 ,  UNINIT ,  MI_OPTION ( reserve_huge_os_pages_at )  } ,    // reserve huge pages at node N
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( reserve_os_memory )      } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( deprecated_segment_cache )  } ,    // cache N segments per thread
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( deprecated_page_reset )  } ,       // reset page memory on free
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION_LEGACY ( abandoned_page_purge , abandoned_page_reset )  } ,        // reset free page memory when a thread terminates
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( deprecated_segment_reset )  } ,    // reset segment memory on free (needs eager commit)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__NetBSD__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,  UNINIT ,  MI_OPTION ( eager_commit_delay )  } ,          // the first N segments per thread are not eagerly committed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  1 ,  UNINIT ,  MI_OPTION ( eager_commit_delay )  } ,          // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  10 ,   UNINIT ,  MI_OPTION_LEGACY ( purge_delay , reset_delay )  } ,   // purge delay in milli-seconds
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,    UNINIT ,  MI_OPTION ( use_numa_nodes )  } ,            // 0 = use available numa nodes, otherwise use at most N nodes.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,    UNINIT ,  MI_OPTION ( limit_os_alloc )  } ,            // 1 = do not use OS memory for allocation (but only reserved arenas)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  100 ,  UNINIT ,  MI_OPTION ( os_tag )  } ,                    // only apple specific for now but might serve more or less related purpose
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  16 ,   UNINIT ,  MI_OPTION ( max_errors )  } ,                // maximum errors that are output
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  16 ,   UNINIT ,  MI_OPTION ( max_warnings )  } ,              // maximum warnings that are output
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  8 ,    UNINIT ,  MI_OPTION ( max_segment_reclaim ) } ,        // max. number of segment reclaims from the abandoned segments per try.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  0 ,    UNINIT ,  MI_OPTION ( destroy_on_exit ) } ,            // release all OS memory on process exit; careful with dangling pointer or after-exit frees!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # if (MI_INTPTR_SIZE>4) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  1024L  *  1024L ,  UNINIT ,  MI_OPTION ( arena_reserve )  } ,   // reserve memory N KiB at a time
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # else 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {   128L  *  1024L ,  UNINIT ,  MI_OPTION ( arena_reserve )  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  10 ,   UNINIT ,  MI_OPTION ( arena_purge_mult )  } ,         // purge delay multiplier for arena's
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {  1 ,    UNINIT ,  MI_OPTION_LEGACY ( purge_extend_delay ,  decommit_extend_delay )  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_option_init ( mi_option_desc_t *  desc ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_options_init ( void )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // called on process load; should not be called before the CRT is initialized!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // (e.g. do not call this from process_init as that may run before CRT initialization)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_add_stderr_output ( ) ;  // now it safe to use stderr for output
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for ( int  i  =  0 ;  i  <  _mi_option_last ;  i + +  )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_option_t  option  =  ( mi_option_t ) i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    long  l  =  mi_option_get ( option ) ;  MI_UNUSED ( l ) ;  // initialize
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // if (option != mi_option_verbose)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      mi_option_desc_t *  desc  =  & options [ option ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _mi_verbose_message ( " option '%s': %ld \n " ,  desc - > name ,  desc - > value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_max_error_count  =  mi_option_get ( mi_option_max_errors ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_max_warning_count  =  mi_option_get ( mi_option_max_warnings ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								mi_decl_nodiscard  long  mi_option_get ( mi_option_t  option )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_assert ( option  > =  0  & &  option  <  _mi_option_last ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( option  <  0  | |  option  > =  _mi_option_last )  return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_desc_t *  desc  =  & options [ option ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_assert ( desc - > option  = =  option ) ;   // index should match the option
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  mi_unlikely ( desc - > init  = =  UNINIT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_option_init ( desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  desc - > value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								mi_decl_nodiscard  long  mi_option_get_clamp ( mi_option_t  option ,  long  min ,  long  max )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  long  x  =  mi_option_get ( option ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ( x  <  min  ?  min  :  ( x  >  max  ?  max  :  x ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								mi_decl_nodiscard  size_t  mi_option_get_size ( mi_option_t  option )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_assert_internal ( option  = =  mi_option_reserve_os_memory  | |  option  = =  mi_option_arena_reserve ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  long  x  =  mi_option_get ( option ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ( x  <  0  ?  0  :  ( size_t ) x  *  MI_KiB ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_option_set ( mi_option_t  option ,  long  value )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_assert ( option  > =  0  & &  option  <  _mi_option_last ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( option  <  0  | |  option  > =  _mi_option_last )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_desc_t *  desc  =  & options [ option ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_assert ( desc - > option  = =  option ) ;   // index should match the option
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  desc - > value  =  value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  desc - > init  =  INITIALIZED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_option_set_default ( mi_option_t  option ,  long  value )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_assert ( option  > =  0  & &  option  <  _mi_option_last ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( option  <  0  | |  option  > =  _mi_option_last )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_desc_t *  desc  =  & options [ option ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( desc - > init  ! =  INITIALIZED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    desc - > value  =  value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								mi_decl_nodiscard  bool  mi_option_is_enabled ( mi_option_t  option )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ( mi_option_get ( option )  ! =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_option_set_enabled ( mi_option_t  option ,  bool  enable )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_set ( option ,  ( enable  ?  1  :  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_option_set_enabled_default ( mi_option_t  option ,  bool  enable )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_set_default ( option ,  ( enable  ?  1  :  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_option_enable ( mi_option_t  option )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_set_enabled ( option , true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_option_disable ( mi_option_t  option )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_option_set_enabled ( option , false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_cdecl  mi_out_stderr ( const  char *  msg ,  void *  arg )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  MI_UNUSED ( arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( msg  ! =  NULL  & &  msg [ 0 ]  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _mi_prim_out_stderr ( msg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Since an output function can be registered earliest in the `main`
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// function we also buffer output that happens earlier. When
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// an output function is registered it is called immediately with
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the output up to that point.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef MI_MAX_DELAY_OUTPUT 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MI_MAX_DELAY_OUTPUT ((size_t)(32*1024)) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  out_buf [ MI_MAX_DELAY_OUTPUT + 1 ] ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  _Atomic ( size_t )  out_len ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_cdecl  mi_out_buf ( const  char *  msg ,  void *  arg )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  MI_UNUSED ( arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( msg = = NULL )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( mi_atomic_load_relaxed ( & out_len ) > = MI_MAX_DELAY_OUTPUT )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  n  =  _mi_strlen ( msg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( n = = 0 )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // claim space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  start  =  mi_atomic_add_acq_rel ( & out_len ,  n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( start  > =  MI_MAX_DELAY_OUTPUT )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // check bound
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( start + n  > =  MI_MAX_DELAY_OUTPUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    n  =  MI_MAX_DELAY_OUTPUT - start - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  _mi_memcpy ( & out_buf [ start ] ,  msg ,  n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_out_buf_flush ( mi_output_fun *  out ,  bool  no_more_buf ,  void *  arg )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( out = = NULL )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // claim (if `no_more_buf == true`, no more output will be added after this point)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  count  =  mi_atomic_add_acq_rel ( & out_len ,  ( no_more_buf  ?  MI_MAX_DELAY_OUTPUT  :  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // and output the current contents
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( count > MI_MAX_DELAY_OUTPUT )  count  =  MI_MAX_DELAY_OUTPUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  out_buf [ count ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  out ( out_buf , arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! no_more_buf )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out_buf [ count ]  =  ' \n ' ;  // if continue with the buffer, insert a newline
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Once this module is loaded, switch to this routine
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// which outputs to stderr and the delayed output buffer.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_cdecl  mi_out_buf_stderr ( const  char *  msg ,  void *  arg )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_out_stderr ( msg , arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_out_buf ( msg , arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Default output handler
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Should be atomic but gives errors on many platforms as generally we cannot cast a function pointer to a uintptr_t.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// For now, don't register output from multiple threads.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  mi_output_fun *  volatile  mi_out_default ;  // = NULL
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  _Atomic ( void * )  mi_out_arg ;  // = NULL
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  mi_output_fun *  mi_out_get_default ( void * *  parg )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( parg  ! =  NULL )  {  * parg  =  mi_atomic_load_ptr_acquire ( void , & mi_out_arg ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_output_fun *  out  =  mi_out_default ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ( out  = =  NULL  ?  & mi_out_buf  :  out ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_register_output ( mi_output_fun *  out ,  void *  arg )  mi_attr_noexcept  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_out_default  =  ( out  = =  NULL  ?  & mi_out_stderr  :  out ) ;  // stop using the delayed output buffer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_atomic_store_ptr_release ( void , & mi_out_arg ,  arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( out ! = NULL )  mi_out_buf_flush ( out , true , arg ) ;          // output all the delayed output now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// add stderr to the delayed output after the module is loaded
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_add_stderr_output ( void )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_assert_internal ( mi_out_default  = =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_out_buf_flush ( & mi_out_stderr ,  false ,  NULL ) ;  // flush current contents to stderr
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_out_default  =  & mi_out_buf_stderr ;            // and add stderr to the delayed output
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Messages, all end up calling `_mi_fputs`.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  _Atomic ( size_t )  error_count ;    // = 0;  // when >= max_error_count stop emitting errors
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  _Atomic ( size_t )  warning_count ;  // = 0;  // when >= max_warning_count stop emitting warnings
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// When overriding malloc, we may recurse into mi_vfprintf if an allocation
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// inside the C runtime causes another message.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// In some cases (like on macOS) the loader already allocates which
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// calls into mimalloc; if we then access thread locals (like `recurse`)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this may crash as the access may call _tlv_bootstrap that tries to
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (recursively) invoke malloc again to allocate space for the thread local
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// variables on demand. This is why we use a _mi_preloading test on such
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// platforms. However, C code generator may move the initial thread local address
  
						 
					
						
							
								
									
										
										
										
											2024-08-28 19:41:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// load before the `if` and we therefore split it out in a separate function.
  
						 
					
						
							
								
									
										
										
										
											2023-10-30 08:43:11 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  mi_decl_thread  bool  recurse  =  false ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  mi_decl_noinline  bool  mi_recurse_enter_prim ( void )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( recurse )  return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  recurse  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  mi_decl_noinline  void  mi_recurse_exit_prim ( void )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  recurse  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  bool  mi_recurse_enter ( void )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( _mi_preloading ( ) )  return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  mi_recurse_enter_prim ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_recurse_exit ( void )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( _mi_preloading ( ) )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_recurse_exit_prim ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_fputs ( mi_output_fun *  out ,  void *  arg ,  const  char *  prefix ,  const  char *  message )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( out = = NULL  | |  ( void * ) out = = ( void * ) stdout  | |  ( void * ) out = = ( void * ) stderr )  {  // TODO: use mi_out_stderr for stderr?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! mi_recurse_enter ( ) )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out  =  mi_out_get_default ( & arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( prefix  ! =  NULL )  out ( prefix ,  arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out ( message ,  arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_recurse_exit ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( prefix  ! =  NULL )  out ( prefix ,  arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out ( message ,  arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Define our own limited `fprintf` that avoids memory allocation.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// We do this using `snprintf` with a limited buffer.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_vfprintf (  mi_output_fun *  out ,  void *  arg ,  const  char *  prefix ,  const  char *  fmt ,  va_list  args  )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  char  buf [ 512 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( fmt = = NULL )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! mi_recurse_enter ( ) )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  vsnprintf ( buf , sizeof ( buf ) - 1 , fmt , args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_recurse_exit ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  _mi_fputs ( out , arg , prefix , buf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_fprintf (  mi_output_fun *  out ,  void *  arg ,  const  char *  fmt ,  . . .  )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_list  args ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_start ( args , fmt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_vfprintf ( out , arg , NULL , fmt , args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_end ( args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_vfprintf_thread ( mi_output_fun *  out ,  void *  arg ,  const  char *  prefix ,  const  char *  fmt ,  va_list  args )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( prefix  ! =  NULL  & &  _mi_strnlen ( prefix , 33 )  < =  32  & &  ! _mi_is_main_thread ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  tprefix [ 64 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    snprintf ( tprefix ,  sizeof ( tprefix ) ,  " %sthread 0x%llx:  " ,  prefix ,  ( unsigned  long  long ) _mi_thread_id ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_vfprintf ( out ,  arg ,  tprefix ,  fmt ,  args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_vfprintf ( out ,  arg ,  prefix ,  fmt ,  args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_trace_message ( const  char *  fmt ,  . . . )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( mi_option_get ( mi_option_verbose )  < =  1 )  return ;   // only with verbose level 2 or higher
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_list  args ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_start ( args ,  fmt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_vfprintf_thread ( NULL ,  NULL ,  " mimalloc:  " ,  fmt ,  args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_end ( args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_verbose_message ( const  char *  fmt ,  . . . )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! mi_option_is_enabled ( mi_option_verbose ) )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_list  args ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_start ( args , fmt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_vfprintf ( NULL ,  NULL ,  " mimalloc:  " ,  fmt ,  args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_end ( args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_show_error_message ( const  char *  fmt ,  va_list  args )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! mi_option_is_enabled ( mi_option_verbose ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! mi_option_is_enabled ( mi_option_show_errors ) )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( mi_max_error_count  > =  0  & &  ( long ) mi_atomic_increment_acq_rel ( & error_count )  >  mi_max_error_count )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_vfprintf_thread ( NULL ,  NULL ,  " mimalloc: error:  " ,  fmt ,  args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_warning_message ( const  char *  fmt ,  . . . )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! mi_option_is_enabled ( mi_option_verbose ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! mi_option_is_enabled ( mi_option_show_errors ) )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( mi_max_warning_count  > =  0  & &  ( long ) mi_atomic_increment_acq_rel ( & warning_count )  >  mi_max_warning_count )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_list  args ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_start ( args , fmt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_vfprintf_thread ( NULL ,  NULL ,  " mimalloc: warning:  " ,  fmt ,  args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_end ( args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if MI_DEBUG 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_assert_fail ( const  char *  assertion ,  const  char *  fname ,  unsigned  line ,  const  char *  func  )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  _mi_fprintf ( NULL ,  NULL ,  " mimalloc: assertion failed: at  \" %s \" :%u, %s \n   assertion:  \" %s \" \n " ,  fname ,  line ,  ( func = = NULL ? " " : func ) ,  assertion ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Errors
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  mi_error_fun *  volatile   mi_error_handler ;  // = NULL
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  _Atomic ( void * )  mi_error_arg ;      // = NULL
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_error_default ( int  err )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  MI_UNUSED ( err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if (MI_DEBUG>0) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( err = = EFAULT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # ifdef _MSC_VER 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    __debugbreak ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if (MI_SECURE>0) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( err = = EFAULT )  {   // abort on serious errors in secure mode (corrupted meta-data)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(MI_XMALLOC) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( err = = ENOMEM  | |  err = = EOVERFLOW )  {  // abort on memory allocation fails in xmalloc mode
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  mi_register_error ( mi_error_fun *  fun ,  void *  arg )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_error_handler  =  fun ;   // can be NULL
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_atomic_store_ptr_release ( void , & mi_error_arg ,  arg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_error_message ( int  err ,  const  char *  fmt ,  . . . )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // show detailed error message
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_list  args ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_start ( args ,  fmt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mi_show_error_message ( fmt ,  args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  va_end ( args ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // and call the error handler which may abort (or return normally)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( mi_error_handler  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_error_handler ( err ,  mi_atomic_load_ptr_acquire ( void , & mi_error_arg ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_error_default ( err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Initialize options by checking the environment
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// --------------------------------------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								char  _mi_toupper ( char  c )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( c  > =  ' a '  & &  c  < =  ' z ' )  return  ( c  -  ' a '  +  ' A ' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       else  return  c ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  _mi_strnicmp ( const  char *  s ,  const  char *  t ,  size_t  n )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( n  = =  0 )  return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( ;  * s  ! =  0  & &  * t  ! =  0  & &  n  >  0 ;  s + + ,  t + + ,  n - - )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( _mi_toupper ( * s )  ! =  _mi_toupper ( * t ) )  break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ( n  = =  0  ?  0  :  * s  -  * t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_strlcpy ( char *  dest ,  const  char *  src ,  size_t  dest_size )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( dest = = NULL  | |  src = = NULL  | |  dest_size  = =  0 )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // copy until end of src, or when dest is (almost) full
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  ( * src  ! =  0  & &  dest_size  >  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    * dest + +  =  * src + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dest_size - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // always zero terminate
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  * dest  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  _mi_strlcat ( char *  dest ,  const  char *  src ,  size_t  dest_size )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( dest = = NULL  | |  src = = NULL  | |  dest_size  = =  0 )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // find end of string in the dest buffer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  ( * dest  ! =  0  & &  dest_size  >  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dest + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dest_size - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // and catenate
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  _mi_strlcpy ( dest ,  src ,  dest_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								size_t  _mi_strlen ( const  char *  s )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( s = = NULL )  return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while ( s [ len ]  ! =  0 )  {  len + + ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								size_t  _mi_strnlen ( const  char *  s ,  size_t  max_len )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( s = = NULL )  return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while ( s [ len ]  ! =  0  & &  len  <  max_len )  {  len + + ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef MI_NO_GETENV 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  bool  mi_getenv ( const  char *  name ,  char *  result ,  size_t  result_size )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  MI_UNUSED ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  MI_UNUSED ( result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  MI_UNUSED ( result_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  bool  mi_getenv ( const  char *  name ,  char *  result ,  size_t  result_size )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( name = = NULL  | |  result  = =  NULL  | |  result_size  <  64 )  return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  _mi_prim_getenv ( name , result , result_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// TODO: implement ourselves to reduce dependencies on the C runtime
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdlib.h> // strtol 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <string.h> // strstr 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mi_option_init ( mi_option_desc_t *  desc )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // Read option value from the environment
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  char  s [ 64  +  1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  char  buf [ 64 + 1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  _mi_strlcpy ( buf ,  " mimalloc_ " ,  sizeof ( buf ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  _mi_strlcat ( buf ,  desc - > name ,  sizeof ( buf ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  found  =  mi_getenv ( buf ,  s ,  sizeof ( s ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! found  & &  desc - > legacy_name  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _mi_strlcpy ( buf ,  " mimalloc_ " ,  sizeof ( buf ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _mi_strlcat ( buf ,  desc - > legacy_name ,  sizeof ( buf ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    found  =  mi_getenv ( buf ,  s ,  sizeof ( s ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _mi_warning_message ( " environment option  \" mimalloc_%s \"  is deprecated -- use  \" mimalloc_%s \"  instead. \n " ,  desc - > legacy_name ,  desc - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  len  =  _mi_strnlen ( s ,  sizeof ( buf )  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  len ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      buf [ i ]  =  _mi_toupper ( s [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    buf [ len ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( buf [ 0 ]  = =  0  | |  strstr ( " 1;TRUE;YES;ON " ,  buf )  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      desc - > value  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      desc - > init  =  INITIALIZED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  if  ( strstr ( " 0;FALSE;NO;OFF " ,  buf )  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      desc - > value  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      desc - > init  =  INITIALIZED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      char *  end  =  buf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      long  value  =  strtol ( buf ,  & end ,  10 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( desc - > option  = =  mi_option_reserve_os_memory  | |  desc - > option  = =  mi_option_arena_reserve )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // this option is interpreted in KiB to prevent overflow of `long`
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( * end  = =  ' K ' )  {  end + + ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( * end  = =  ' M ' )  {  value  * =  MI_KiB ;  end + + ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( * end  = =  ' G ' )  {  value  * =  MI_MiB ;  end + + ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  {  value  =  ( value  +  MI_KiB  -  1 )  /  MI_KiB ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( end [ 0 ]  = =  ' I '  & &  end [ 1 ]  = =  ' B ' )  {  end  + =  2 ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( * end  = =  ' B ' )  {  end + + ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( * end  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        desc - > value  =  value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        desc - > init  =  INITIALIZED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        desc - > init  =  DEFAULTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( desc - > option  = =  mi_option_verbose  & &  desc - > value  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // if the 'mimalloc_verbose' env var has a bogus value we'd never know
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // (since the value defaults to 'off') so in that case briefly enable verbose
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          desc - > value  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          _mi_warning_message ( " environment option mimalloc_%s has an invalid value. \n " ,  desc - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          desc - > value  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          _mi_warning_message ( " environment option mimalloc_%s has an invalid value. \n " ,  desc - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mi_assert_internal ( desc - > init  ! =  UNINIT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else  if  ( ! _mi_preloading ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    desc - > init  =  DEFAULTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}