mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-05 23:19:31 +03:00
add c primitives, move getenv into primitives
This commit is contained in:
parent
69cb30a874
commit
10f62eb5a1
7 changed files with 209 additions and 126 deletions
|
@ -166,6 +166,15 @@ bool _mi_free_delayed_block(mi_block_t* block);
|
||||||
void _mi_free_generic(const mi_segment_t* segment, mi_page_t* page, bool is_local, void* p) mi_attr_noexcept; // for runtime integration
|
void _mi_free_generic(const mi_segment_t* segment, mi_page_t* page, bool is_local, void* p) mi_attr_noexcept; // for runtime integration
|
||||||
void _mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size);
|
void _mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size);
|
||||||
|
|
||||||
|
// option.c, c primitives
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
#if MI_DEBUG>1
|
#if MI_DEBUG>1
|
||||||
bool _mi_page_is_valid(mi_page_t* page);
|
bool _mi_page_is_valid(mi_page_t* page);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -149,7 +149,7 @@ int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept {
|
||||||
else {
|
else {
|
||||||
*buf = mi_strdup(p);
|
*buf = mi_strdup(p);
|
||||||
if (*buf==NULL) return ENOMEM;
|
if (*buf==NULL) return ENOMEM;
|
||||||
if (size != NULL) *size = strlen(p);
|
if (size != NULL) *size = _mi_strlen(p);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
166
src/options.c
166
src/options.c
|
@ -7,17 +7,11 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#include "mimalloc.h"
|
#include "mimalloc.h"
|
||||||
#include "mimalloc-internal.h"
|
#include "mimalloc-internal.h"
|
||||||
#include "mimalloc-atomic.h"
|
#include "mimalloc-atomic.h"
|
||||||
|
#include "prim/prim.h" // mi_prim_out_stderr
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h> // strtol
|
|
||||||
#include <string.h> // strncpy, strncat, strlen, strstr
|
|
||||||
#include <ctype.h> // toupper
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable:4996) // strncpy, strncat
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static long mi_max_error_count = 16; // stop outputting errors after this (use < 0 for no limit)
|
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 long mi_max_warning_count = 16; // stop outputting warnings after this (use < 0 for no limit)
|
||||||
|
@ -170,41 +164,11 @@ void mi_option_disable(mi_option_t option) {
|
||||||
mi_option_set_enabled(option,false);
|
mi_option_set_enabled(option,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mi_cdecl mi_out_stderr(const char* msg, void* arg) {
|
static void mi_cdecl mi_out_stderr(const char* msg, void* arg) {
|
||||||
MI_UNUSED(arg);
|
MI_UNUSED(arg);
|
||||||
if (msg == NULL) return;
|
if (msg != NULL && msg[0] != 0) {
|
||||||
#ifdef _WIN32
|
_mi_prim_out_stderr(msg);
|
||||||
// on windows with redirection, the C runtime cannot handle locale dependent output
|
|
||||||
// after the main thread closes so we use direct console output.
|
|
||||||
if (!_mi_preloading()) {
|
|
||||||
// _cputs(msg); // _cputs cannot be used at is aborts if it fails to lock the console
|
|
||||||
static HANDLE hcon = INVALID_HANDLE_VALUE;
|
|
||||||
static bool hconIsConsole;
|
|
||||||
if (hcon == INVALID_HANDLE_VALUE) {
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
|
||||||
hcon = GetStdHandle(STD_ERROR_HANDLE);
|
|
||||||
hconIsConsole = ((hcon != INVALID_HANDLE_VALUE) && GetConsoleScreenBufferInfo(hcon, &sbi));
|
|
||||||
}
|
|
||||||
const size_t len = strlen(msg);
|
|
||||||
if (len > 0 && len < UINT32_MAX) {
|
|
||||||
DWORD written = 0;
|
|
||||||
if (hconIsConsole) {
|
|
||||||
WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL);
|
|
||||||
}
|
|
||||||
else if (hcon != INVALID_HANDLE_VALUE) {
|
|
||||||
// use direct write if stderr was redirected
|
|
||||||
WriteFile(hcon, msg, (DWORD)len, &written, NULL);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// finally fall back to fputs after all
|
|
||||||
fputs(msg, stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
fputs(msg, stderr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since an output function can be registered earliest in the `main`
|
// Since an output function can be registered earliest in the `main`
|
||||||
|
@ -221,7 +185,7 @@ static void mi_cdecl mi_out_buf(const char* msg, void* arg) {
|
||||||
MI_UNUSED(arg);
|
MI_UNUSED(arg);
|
||||||
if (msg==NULL) return;
|
if (msg==NULL) return;
|
||||||
if (mi_atomic_load_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return;
|
if (mi_atomic_load_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return;
|
||||||
size_t n = strlen(msg);
|
size_t n = _mi_strlen(msg);
|
||||||
if (n==0) return;
|
if (n==0) return;
|
||||||
// claim space
|
// claim space
|
||||||
size_t start = mi_atomic_add_acq_rel(&out_len, n);
|
size_t start = mi_atomic_add_acq_rel(&out_len, n);
|
||||||
|
@ -358,7 +322,7 @@ 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) {
|
static void mi_vfprintf_thread(mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args) {
|
||||||
if (prefix != NULL && strlen(prefix) <= 32 && !_mi_is_main_thread()) {
|
if (prefix != NULL && _mi_strnlen(prefix,33) <= 32 && !_mi_is_main_thread()) {
|
||||||
char tprefix[64];
|
char tprefix[64];
|
||||||
snprintf(tprefix, sizeof(tprefix), "%sthread 0x%llx: ", prefix, (unsigned long long)_mi_thread_id());
|
snprintf(tprefix, sizeof(tprefix), "%sthread 0x%llx: ", prefix, (unsigned long long)_mi_thread_id());
|
||||||
mi_vfprintf(out, arg, tprefix, fmt, args);
|
mi_vfprintf(out, arg, tprefix, fmt, args);
|
||||||
|
@ -463,8 +427,20 @@ void _mi_error_message(int err, const char* fmt, ...) {
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// Initialize options by checking the environment
|
// Initialize options by checking the environment
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
char _mi_toupper(char c) {
|
||||||
|
if (c >= 'a' && c <= 'z') return (c - 'a' + 'A');
|
||||||
|
else return c;
|
||||||
|
}
|
||||||
|
|
||||||
static void mi_strlcpy(char* dest, const char* src, size_t dest_size) {
|
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;
|
if (dest==NULL || src==NULL || dest_size == 0) return;
|
||||||
// copy until end of src, or when dest is (almost) full
|
// copy until end of src, or when dest is (almost) full
|
||||||
while (*src != 0 && dest_size > 1) {
|
while (*src != 0 && dest_size > 1) {
|
||||||
|
@ -475,7 +451,7 @@ static void mi_strlcpy(char* dest, const char* src, size_t dest_size) {
|
||||||
*dest = 0;
|
*dest = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_strlcat(char* dest, const char* src, size_t dest_size) {
|
void _mi_strlcat(char* dest, const char* src, size_t dest_size) {
|
||||||
if (dest==NULL || src==NULL || dest_size == 0) return;
|
if (dest==NULL || src==NULL || dest_size == 0) return;
|
||||||
// find end of string in the dest buffer
|
// find end of string in the dest buffer
|
||||||
while (*dest != 0 && dest_size > 1) {
|
while (*dest != 0 && dest_size > 1) {
|
||||||
|
@ -483,7 +459,21 @@ static void mi_strlcat(char* dest, const char* src, size_t dest_size) {
|
||||||
dest_size--;
|
dest_size--;
|
||||||
}
|
}
|
||||||
// and catenate
|
// and catenate
|
||||||
mi_strlcpy(dest, src, dest_size);
|
_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
|
#ifdef MI_NO_GETENV
|
||||||
|
@ -494,94 +484,28 @@ static bool mi_getenv(const char* name, char* result, size_t result_size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#if defined _WIN32
|
|
||||||
// On Windows use GetEnvironmentVariable instead of getenv to work
|
|
||||||
// reliably even when this is invoked before the C runtime is initialized.
|
|
||||||
// i.e. when `_mi_preloading() == true`.
|
|
||||||
// Note: on windows, environment names are not case sensitive.
|
|
||||||
#include <windows.h>
|
|
||||||
static bool mi_getenv(const char* name, char* result, size_t result_size) {
|
static bool mi_getenv(const char* name, char* result, size_t result_size) {
|
||||||
result[0] = 0;
|
if (name==NULL || result == NULL || result_size < 64) return false;
|
||||||
size_t len = GetEnvironmentVariableA(name, result, (DWORD)result_size);
|
return _mi_prim_getenv(name,result,result_size);
|
||||||
return (len > 0 && len < result_size);
|
|
||||||
}
|
|
||||||
#elif !defined(MI_USE_ENVIRON) || (MI_USE_ENVIRON!=0)
|
|
||||||
// On Posix systemsr use `environ` to acces environment variables
|
|
||||||
// even before the C runtime is initialized.
|
|
||||||
#if defined(__APPLE__) && defined(__has_include) && __has_include(<crt_externs.h>)
|
|
||||||
#include <crt_externs.h>
|
|
||||||
static char** mi_get_environ(void) {
|
|
||||||
return (*_NSGetEnviron());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
extern char** environ;
|
|
||||||
static char** mi_get_environ(void) {
|
|
||||||
return environ;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
static int mi_strnicmp(const char* s, const char* t, size_t n) {
|
|
||||||
if (n == 0) return 0;
|
// TODO: implement ourselves to reduce dependencies on the C runtime
|
||||||
for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) {
|
#include <stdlib.h> // strtol
|
||||||
if (toupper(*s) != toupper(*t)) break;
|
#include <string.h> // strstr
|
||||||
}
|
|
||||||
return (n == 0 ? 0 : *s - *t);
|
|
||||||
}
|
|
||||||
static bool mi_getenv(const char* name, char* result, size_t result_size) {
|
|
||||||
if (name==NULL) return false;
|
|
||||||
const size_t len = strlen(name);
|
|
||||||
if (len == 0) return false;
|
|
||||||
char** env = mi_get_environ();
|
|
||||||
if (env == NULL) return false;
|
|
||||||
// compare up to 256 entries
|
|
||||||
for (int i = 0; i < 256 && env[i] != NULL; i++) {
|
|
||||||
const char* s = env[i];
|
|
||||||
if (mi_strnicmp(name, s, len) == 0 && s[len] == '=') { // case insensitive
|
|
||||||
// found it
|
|
||||||
mi_strlcpy(result, s + len + 1, result_size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// fallback: use standard C `getenv` but this cannot be used while initializing the C runtime
|
|
||||||
static bool mi_getenv(const char* name, char* result, size_t result_size) {
|
|
||||||
// cannot call getenv() when still initializing the C runtime.
|
|
||||||
if (_mi_preloading()) return false;
|
|
||||||
const char* s = getenv(name);
|
|
||||||
if (s == NULL) {
|
|
||||||
// we check the upper case name too.
|
|
||||||
char buf[64+1];
|
|
||||||
size_t len = strlen(name);
|
|
||||||
if (len >= sizeof(buf)) len = sizeof(buf) - 1;
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
buf[i] = toupper(name[i]);
|
|
||||||
}
|
|
||||||
buf[len] = 0;
|
|
||||||
s = getenv(buf);
|
|
||||||
}
|
|
||||||
if (s != NULL && strlen(s) < result_size) {
|
|
||||||
mi_strlcpy(result, s, result_size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // !MI_USE_ENVIRON
|
|
||||||
#endif // !MI_NO_GETENV
|
|
||||||
|
|
||||||
static void mi_option_init(mi_option_desc_t* desc) {
|
static void mi_option_init(mi_option_desc_t* desc) {
|
||||||
// Read option value from the environment
|
// Read option value from the environment
|
||||||
char buf[64+1];
|
char buf[64+1];
|
||||||
mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
_mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
||||||
mi_strlcat(buf, desc->name, sizeof(buf));
|
_mi_strlcat(buf, desc->name, sizeof(buf));
|
||||||
char s[64+1];
|
char s[64+1];
|
||||||
if (mi_getenv(buf, s, sizeof(s))) {
|
if (mi_getenv(buf, s, sizeof(s))) {
|
||||||
size_t len = strlen(s);
|
size_t len = _mi_strnlen(s,64);
|
||||||
if (len >= sizeof(buf)) len = sizeof(buf) - 1;
|
if (len >= sizeof(buf)) len = sizeof(buf) - 1;
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
buf[i] = (char)toupper(s[i]);
|
buf[i] = _mi_toupper(s[i]);
|
||||||
}
|
}
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
if (buf[0]==0 || strstr("1;TRUE;YES;ON", buf) != NULL) {
|
if (buf[0]==0 || strstr("1;TRUE;YES;ON", buf) != NULL) {
|
||||||
|
|
|
@ -589,3 +589,69 @@ void _mi_prim_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* current
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Output
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
void _mi_prim_out_stderr( const char* msg ) {
|
||||||
|
fputs(msg,stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Environment
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#if !defined(MI_USE_ENVIRON) || (MI_USE_ENVIRON!=0)
|
||||||
|
// On Posix systemsr use `environ` to acces environment variables
|
||||||
|
// even before the C runtime is initialized.
|
||||||
|
#if defined(__APPLE__) && defined(__has_include) && __has_include(<crt_externs.h>)
|
||||||
|
#include <crt_externs.h>
|
||||||
|
static char** mi_get_environ(void) {
|
||||||
|
return (*_NSGetEnviron());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
extern char** environ;
|
||||||
|
static char** mi_get_environ(void) {
|
||||||
|
return environ;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
|
||||||
|
if (name==NULL) return false;
|
||||||
|
const size_t len = _mi_strlen(name);
|
||||||
|
if (len == 0) return false;
|
||||||
|
char** env = mi_get_environ();
|
||||||
|
if (env == NULL) return false;
|
||||||
|
// compare up to 256 entries
|
||||||
|
for (int i = 0; i < 256 && env[i] != NULL; i++) {
|
||||||
|
const char* s = env[i];
|
||||||
|
if (_mi_strnicmp(name, s, len) == 0 && s[len] == '=') { // case insensitive
|
||||||
|
// found it
|
||||||
|
_mi_strlcpy(result, s + len + 1, result_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// fallback: use standard C `getenv` but this cannot be used while initializing the C runtime
|
||||||
|
bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
|
||||||
|
// cannot call getenv() when still initializing the C runtime.
|
||||||
|
if (_mi_preloading()) return false;
|
||||||
|
const char* s = getenv(name);
|
||||||
|
if (s == NULL) {
|
||||||
|
// we check the upper case name too.
|
||||||
|
char buf[64+1];
|
||||||
|
size_t len = _mi_strnlen(name,sizeof(buf)-1);
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
buf[i] = _mi_toupper(name[i]);
|
||||||
|
}
|
||||||
|
buf[len] = 0;
|
||||||
|
s = getenv(buf);
|
||||||
|
}
|
||||||
|
if (s == NULL || _mi_strnlen(s,result_size) >= result_size) return false;
|
||||||
|
_mi_strlcpy(result, s, result_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // !MI_USE_ENVIRON
|
||||||
|
|
|
@ -197,4 +197,34 @@ void _mi_prim_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* current
|
||||||
*stime = 0;
|
*stime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Output
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
void _mi_prim_out_stderr( const char* msg ) {
|
||||||
|
fputs(msg,stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Environment
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
|
||||||
|
// cannot call getenv() when still initializing the C runtime.
|
||||||
|
if (_mi_preloading()) return false;
|
||||||
|
const char* s = getenv(name);
|
||||||
|
if (s == NULL) {
|
||||||
|
// we check the upper case name too.
|
||||||
|
char buf[64+1];
|
||||||
|
size_t len = _mi_strnlen(name,sizeof(buf)-1);
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
buf[i] = _mi_toupper(name[i]);
|
||||||
|
}
|
||||||
|
buf[len] = 0;
|
||||||
|
s = getenv(buf);
|
||||||
|
}
|
||||||
|
if (s == NULL || _mi_strnlen(s,result_size) >= result_size) return false;
|
||||||
|
_mi_strlcpy(result, s, result_size);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#include "mimalloc-atomic.h"
|
#include "mimalloc-atomic.h"
|
||||||
#include "prim.h"
|
#include "prim.h"
|
||||||
#include <string.h> // strerror
|
#include <string.h> // strerror
|
||||||
|
#include <stdio.h> // fputs, stderr
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable:4996) // strerror
|
#pragma warning(disable:4996) // strerror
|
||||||
|
@ -407,10 +408,6 @@ mi_msecs_t _mi_prim_clock_now(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
|
||||||
// Process info
|
|
||||||
//----------------------------------------------------------------
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
|
|
||||||
|
@ -455,3 +452,53 @@ void _mi_prim_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* current
|
||||||
*peak_commit = (size_t)info.PeakPagefileUsage;
|
*peak_commit = (size_t)info.PeakPagefileUsage;
|
||||||
*page_faults = (size_t)info.PageFaultCount;
|
*page_faults = (size_t)info.PageFaultCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Output
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
void _mi_prim_out_stderr( const char* msg )
|
||||||
|
{
|
||||||
|
// on windows with redirection, the C runtime cannot handle locale dependent output
|
||||||
|
// after the main thread closes so we use direct console output.
|
||||||
|
if (!_mi_preloading()) {
|
||||||
|
// _cputs(msg); // _cputs cannot be used at is aborts if it fails to lock the console
|
||||||
|
static HANDLE hcon = INVALID_HANDLE_VALUE;
|
||||||
|
static bool hconIsConsole;
|
||||||
|
if (hcon == INVALID_HANDLE_VALUE) {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||||
|
hcon = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
hconIsConsole = ((hcon != INVALID_HANDLE_VALUE) && GetConsoleScreenBufferInfo(hcon, &sbi));
|
||||||
|
}
|
||||||
|
const size_t len = strlen(msg);
|
||||||
|
if (len > 0 && len < UINT32_MAX) {
|
||||||
|
DWORD written = 0;
|
||||||
|
if (hconIsConsole) {
|
||||||
|
WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL);
|
||||||
|
}
|
||||||
|
else if (hcon != INVALID_HANDLE_VALUE) {
|
||||||
|
// use direct write if stderr was redirected
|
||||||
|
WriteFile(hcon, msg, (DWORD)len, &written, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// finally fall back to fputs after all
|
||||||
|
fputs(msg, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Environment
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
// On Windows use GetEnvironmentVariable instead of getenv to work
|
||||||
|
// reliably even when this is invoked before the C runtime is initialized.
|
||||||
|
// i.e. when `_mi_preloading() == true`.
|
||||||
|
// Note: on windows, environment names are not case sensitive.
|
||||||
|
bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
|
||||||
|
result[0] = 0;
|
||||||
|
size_t len = GetEnvironmentVariableA(name, result, (DWORD)result_size);
|
||||||
|
return (len > 0 && len < result_size);
|
||||||
|
}
|
|
@ -66,6 +66,13 @@ void _mi_prim_process_info(mi_msecs_t* utime, mi_msecs_t* stime,
|
||||||
size_t* current_rss, size_t* peak_rss,
|
size_t* current_rss, size_t* peak_rss,
|
||||||
size_t* current_commit, size_t* peak_commit, size_t* page_faults);
|
size_t* current_commit, size_t* peak_commit, size_t* page_faults);
|
||||||
|
|
||||||
|
// Default stderr output.
|
||||||
|
// msg != NULL && strlen(msg) > 0
|
||||||
|
void _mi_prim_out_stderr( const char* msg );
|
||||||
|
|
||||||
|
// Get an environment variable.
|
||||||
|
// name != NULL, result != NULL, result_size >= 64
|
||||||
|
bool _mi_prim_getenv(const char* name, char* result, size_t result_size);
|
||||||
|
|
||||||
|
|
||||||
#endif // MIMALLOC_PRIM_H
|
#endif // MIMALLOC_PRIM_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue