cpython/Objects/mimalloc/options.c

/* ----------------------------------------------------------------------------
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   =; // stop outputting errors after this (use < 0 for no limit)
static long mi_max_warning_count =; // stop outputting warnings after this (use < 0 for no limit)

static void mi_add_stderr_output(void);

int mi_version(void) mi_attr_noexcept {}


// --------------------------------------------------------
// 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.
// --------------------------------------------------------
mi_init_t;

mi_option_desc_t;

#define MI_OPTION(opt)
#define MI_OPTION_LEGACY(opt,legacy)

static mi_option_desc_t options[_mi_option_last] =;

static void mi_option_init(mi_option_desc_t* desc);

void _mi_options_init(void) {}

mi_decl_nodiscard long mi_option_get(mi_option_t option) {}

mi_decl_nodiscard long mi_option_get_clamp(mi_option_t option, long min, long max) {}

mi_decl_nodiscard size_t mi_option_get_size(mi_option_t option) {}

void mi_option_set(mi_option_t option, long value) {}

void mi_option_set_default(mi_option_t option, long value) {}

mi_decl_nodiscard bool mi_option_is_enabled(mi_option_t option) {}

void mi_option_set_enabled(mi_option_t option, bool enable) {}

void mi_option_set_enabled_default(mi_option_t option, bool enable) {}

void mi_option_enable(mi_option_t option) {}

void mi_option_disable(mi_option_t option) {}

static void mi_cdecl mi_out_stderr(const char* msg, void* arg) {}

// 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
#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) {}

static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) {}


// 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) {}



// --------------------------------------------------------
// 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) {}

void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept {}

// add stderr to the delayed output after the module is loaded
static void mi_add_stderr_output(void) {}

// --------------------------------------------------------
// 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
// load before the `if` and we therefore split it out in a separate function.
static mi_decl_thread bool recurse =;

static mi_decl_noinline bool mi_recurse_enter_prim(void) {}

static mi_decl_noinline void mi_recurse_exit_prim(void) {}

static bool mi_recurse_enter(void) {}

static void mi_recurse_exit(void) {}

void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message) {}

// 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 ) {}

void _mi_fprintf( mi_output_fun* out, void* arg, const char* fmt, ... ) {}

static void mi_vfprintf_thread(mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args) {}

void _mi_trace_message(const char* fmt, ...) {}

void _mi_verbose_message(const char* fmt, ...) {}

static void mi_show_error_message(const char* fmt, va_list args) {}

void _mi_warning_message(const char* fmt, ...) {}


#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) {}

void mi_register_error(mi_error_fun* fun, void* arg) {}

void _mi_error_message(int err, const char* fmt, ...) {}

// --------------------------------------------------------
// Initialize options by checking the environment
// --------------------------------------------------------
char _mi_toupper(char c) {}

int _mi_strnicmp(const char* s, const char* t, size_t n) {}

void _mi_strlcpy(char* dest, const char* src, size_t dest_size) {}

void _mi_strlcat(char* dest, const char* src, size_t dest_size) {}

size_t _mi_strlen(const char* s) {}

size_t _mi_strnlen(const char* s, size_t max_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) {}
#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) {}