1 | /* ---------------------------------------------------------------------------- |
2 | Copyright (c) 2018,2019, Microsoft Research, Daan Leijen |
3 | This is free software; you can redistribute it and/or modify it under the |
4 | terms of the MIT license. A copy of the license can be found in the file |
5 | "LICENSE" at the root of this distribution. |
6 | -----------------------------------------------------------------------------*/ |
7 | |
8 | // ------------------------------------------------------------------------ |
9 | // mi prefixed publi definitions of various Posix, Unix, and C++ functions |
10 | // for convenience and used when overriding these functions. |
11 | // ------------------------------------------------------------------------ |
12 | |
13 | #include "mimalloc.h" |
14 | #include "mimalloc-internal.h" |
15 | |
16 | // ------------------------------------------------------ |
17 | // Posix & Unix functions definitions |
18 | // ------------------------------------------------------ |
19 | |
20 | #include <errno.h> |
21 | #include <string.h> // memcpy |
22 | #include <stdlib.h> // getenv |
23 | |
24 | #ifndef EINVAL |
25 | #define EINVAL 22 |
26 | #endif |
27 | #ifndef ENOMEM |
28 | #define ENOMEM 12 |
29 | #endif |
30 | |
31 | |
32 | size_t mi_malloc_size(const void* p) mi_attr_noexcept { |
33 | return mi_usable_size(p); |
34 | } |
35 | |
36 | size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept { |
37 | return mi_usable_size(p); |
38 | } |
39 | |
40 | void mi_cfree(void* p) mi_attr_noexcept { |
41 | if (mi_is_in_heap_region(p)) { |
42 | mi_free(p); |
43 | } |
44 | } |
45 | |
46 | int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept { |
47 | // Note: The spec dictates we should not modify `*p` on an error. (issue#27) |
48 | // <http://man7.org/linux/man-pages/man3/posix_memalign.3.html> |
49 | if (p == NULL) return EINVAL; |
50 | if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment |
51 | if (!_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2 |
52 | void* q = mi_malloc_aligned(size, alignment); |
53 | if (q==NULL && size != 0) return ENOMEM; |
54 | *p = q; |
55 | return 0; |
56 | } |
57 | |
58 | void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept { |
59 | return mi_malloc_aligned(size, alignment); |
60 | } |
61 | |
62 | void* mi_valloc(size_t size) mi_attr_noexcept { |
63 | return mi_malloc_aligned(size, _mi_os_page_size()); |
64 | } |
65 | |
66 | void* mi_pvalloc(size_t size) mi_attr_noexcept { |
67 | size_t psize = _mi_os_page_size(); |
68 | if (size >= SIZE_MAX - psize) return NULL; // overflow |
69 | size_t asize = ((size + psize - 1) / psize) * psize; |
70 | return mi_malloc_aligned(asize, psize); |
71 | } |
72 | |
73 | void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept { |
74 | if (alignment==0 || !_mi_is_power_of_two(alignment)) return NULL; |
75 | if ((size&(alignment-1)) != 0) return NULL; // C11 requires integral multiple, see <https://en.cppreference.com/w/c/memory/aligned_alloc> |
76 | return mi_malloc_aligned(size, alignment); |
77 | } |
78 | |
79 | void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD |
80 | void* newp = mi_reallocn(p,count,size); |
81 | if (newp==NULL) errno = ENOMEM; |
82 | return newp; |
83 | } |
84 | |
85 | void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft |
86 | void* res = mi_expand(p, newsize); |
87 | if (res == NULL) errno = ENOMEM; |
88 | return res; |
89 | } |
90 | |
91 | unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept { |
92 | if (s==NULL) return NULL; |
93 | size_t len; |
94 | for(len = 0; s[len] != 0; len++) { } |
95 | size_t size = (len+1)*sizeof(unsigned short); |
96 | unsigned short* p = (unsigned short*)mi_malloc(size); |
97 | if (p != NULL) { |
98 | memcpy(p,s,size); |
99 | } |
100 | return p; |
101 | } |
102 | |
103 | unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept { |
104 | return (unsigned char*)mi_strdup((const char*)s); |
105 | } |
106 | |
107 | int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept { |
108 | if (buf==NULL || name==NULL) return EINVAL; |
109 | if (size != NULL) *size = 0; |
110 | #pragma warning(suppress:4996) |
111 | char* p = getenv(name); |
112 | if (p==NULL) { |
113 | *buf = NULL; |
114 | } |
115 | else { |
116 | *buf = mi_strdup(p); |
117 | if (*buf==NULL) return ENOMEM; |
118 | if (size != NULL) *size = strlen(p); |
119 | } |
120 | return 0; |
121 | } |
122 | |
123 | int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept { |
124 | if (buf==NULL || name==NULL) return EINVAL; |
125 | if (size != NULL) *size = 0; |
126 | #if !defined(_WIN32) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)) |
127 | // not supported |
128 | *buf = NULL; |
129 | return EINVAL; |
130 | #else |
131 | #pragma warning(suppress:4996) |
132 | unsigned short* p = (unsigned short*)_wgetenv((const wchar_t*)name); |
133 | if (p==NULL) { |
134 | *buf = NULL; |
135 | } |
136 | else { |
137 | *buf = mi_wcsdup(p); |
138 | if (*buf==NULL) return ENOMEM; |
139 | if (size != NULL) *size = wcslen((const wchar_t*)p); |
140 | } |
141 | return 0; |
142 | #endif |
143 | } |
144 | |
145 | void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { // Microsoft |
146 | return mi_recalloc_aligned_at(p, newcount, size, alignment, offset); |
147 | } |
148 | |
149 | void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { // Microsoft |
150 | return mi_recalloc_aligned(p, newcount, size, alignment); |
151 | } |
152 | |