microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
alex/katas-update

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

allocator/mimalloc-sys/mimalloc/src/prim/wasi/prim.c

275lines · modecode

1/* ----------------------------------------------------------------------------
2Copyright (c) 2018-2023, Microsoft Research, Daan Leijen
3This is free software; you can redistribute it and/or modify it under the
4terms 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// This file is included in `src/prim/prim.c`
9
10#include "mimalloc.h"
11#include "mimalloc/internal.h"
12#include "mimalloc/atomic.h"
13#include "mimalloc/prim.h"
14
15//---------------------------------------------
16// Initialize
17//---------------------------------------------
18
19void _mi_prim_mem_init( mi_os_mem_config_t* config ) {
20 config->page_size = 64*MI_KiB; // WebAssembly has a fixed page size: 64KiB
21 config->alloc_granularity = 16;
22 config->has_overcommit = false;
23 config->must_free_whole = true;
24 config->has_virtual_reserve = false;
25}
26
27//---------------------------------------------
28// Free
29//---------------------------------------------
30
31int _mi_prim_free(void* addr, size_t size ) {
32 MI_UNUSED(addr); MI_UNUSED(size);
33 // wasi heap cannot be shrunk
34 return 0;
35}
36
37
38//---------------------------------------------
39// Allocation: sbrk or memory_grow
40//---------------------------------------------
41
42#if defined(MI_USE_SBRK)
43 static void* mi_memory_grow( size_t size ) {
44 void* p = sbrk(size);
45 if (p == (void*)(-1)) return NULL;
46 #if !defined(__wasi__) // on wasi this is always zero initialized already (?)
47 memset(p,0,size);
48 #endif
49 return p;
50 }
51#elif defined(__wasi__)
52 static void* mi_memory_grow( size_t size ) {
53 size_t base = (size > 0 ? __builtin_wasm_memory_grow(0,_mi_divide_up(size, _mi_os_page_size()))
54 : __builtin_wasm_memory_size(0));
55 if (base == SIZE_MAX) return NULL;
56 return (void*)(base * _mi_os_page_size());
57 }
58#endif
59
60#if defined(MI_USE_PTHREADS)
61static pthread_mutex_t mi_heap_grow_mutex = PTHREAD_MUTEX_INITIALIZER;
62#endif
63
64static void* mi_prim_mem_grow(size_t size, size_t try_alignment) {
65 void* p = NULL;
66 if (try_alignment <= 1) {
67 // `sbrk` is not thread safe in general so try to protect it (we could skip this on WASM but leave it in for now)
68 #if defined(MI_USE_PTHREADS)
69 pthread_mutex_lock(&mi_heap_grow_mutex);
70 #endif
71 p = mi_memory_grow(size);
72 #if defined(MI_USE_PTHREADS)
73 pthread_mutex_unlock(&mi_heap_grow_mutex);
74 #endif
75 }
76 else {
77 void* base = NULL;
78 size_t alloc_size = 0;
79 // to allocate aligned use a lock to try to avoid thread interaction
80 // between getting the current size and actual allocation
81 // (also, `sbrk` is not thread safe in general)
82 #if defined(MI_USE_PTHREADS)
83 pthread_mutex_lock(&mi_heap_grow_mutex);
84 #endif
85 {
86 void* current = mi_memory_grow(0); // get current size
87 if (current != NULL) {
88 void* aligned_current = mi_align_up_ptr(current, try_alignment); // and align from there to minimize wasted space
89 alloc_size = _mi_align_up( ((uint8_t*)aligned_current - (uint8_t*)current) + size, _mi_os_page_size());
90 base = mi_memory_grow(alloc_size);
91 }
92 }
93 #if defined(MI_USE_PTHREADS)
94 pthread_mutex_unlock(&mi_heap_grow_mutex);
95 #endif
96 if (base != NULL) {
97 p = mi_align_up_ptr(base, try_alignment);
98 if ((uint8_t*)p + size > (uint8_t*)base + alloc_size) {
99 // another thread used wasm_memory_grow/sbrk in-between and we do not have enough
100 // space after alignment. Give up (and waste the space as we cannot shrink :-( )
101 // (in `mi_os_mem_alloc_aligned` this will fall back to overallocation to align)
102 p = NULL;
103 }
104 }
105 }
106 /*
107 if (p == NULL) {
108 _mi_warning_message("unable to allocate sbrk/wasm_memory_grow OS memory (%zu bytes, %zu alignment)\n", size, try_alignment);
109 errno = ENOMEM;
110 return NULL;
111 }
112 */
113 mi_assert_internal( p == NULL || try_alignment == 0 || (uintptr_t)p % try_alignment == 0 );
114 return p;
115}
116
117// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
118int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
119 MI_UNUSED(allow_large); MI_UNUSED(commit);
120 *is_large = false;
121 *is_zero = false;
122 *addr = mi_prim_mem_grow(size, try_alignment);
123 return (*addr != NULL ? 0 : ENOMEM);
124}
125
126
127//---------------------------------------------
128// Commit/Reset/Protect
129//---------------------------------------------
130
131int _mi_prim_commit(void* addr, size_t size, bool* is_zero) {
132 MI_UNUSED(addr); MI_UNUSED(size);
133 *is_zero = false;
134 return 0;
135}
136
137int _mi_prim_decommit(void* addr, size_t size, bool* needs_recommit) {
138 MI_UNUSED(addr); MI_UNUSED(size);
139 *needs_recommit = false;
140 return 0;
141}
142
143int _mi_prim_reset(void* addr, size_t size) {
144 MI_UNUSED(addr); MI_UNUSED(size);
145 return 0;
146}
147
148int _mi_prim_protect(void* addr, size_t size, bool protect) {
149 MI_UNUSED(addr); MI_UNUSED(size); MI_UNUSED(protect);
150 return 0;
151}
152
153
154//---------------------------------------------
155// Huge pages and NUMA nodes
156//---------------------------------------------
157
158int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr) {
159 MI_UNUSED(hint_addr); MI_UNUSED(size); MI_UNUSED(numa_node);
160 *is_zero = true;
161 *addr = NULL;
162 return ENOSYS;
163}
164
165size_t _mi_prim_numa_node(void) {
166 return 0;
167}
168
169size_t _mi_prim_numa_node_count(void) {
170 return 1;
171}
172
173
174//----------------------------------------------------------------
175// Clock
176//----------------------------------------------------------------
177
178#include <time.h>
179
180#if defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC)
181
182mi_msecs_t _mi_prim_clock_now(void) {
183 struct timespec t;
184 #ifdef CLOCK_MONOTONIC
185 clock_gettime(CLOCK_MONOTONIC, &t);
186 #else
187 clock_gettime(CLOCK_REALTIME, &t);
188 #endif
189 return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000);
190}
191
192#else
193
194// low resolution timer
195mi_msecs_t _mi_prim_clock_now(void) {
196 #if !defined(CLOCKS_PER_SEC) || (CLOCKS_PER_SEC == 1000) || (CLOCKS_PER_SEC == 0)
197 return (mi_msecs_t)clock();
198 #elif (CLOCKS_PER_SEC < 1000)
199 return (mi_msecs_t)clock() * (1000 / (mi_msecs_t)CLOCKS_PER_SEC);
200 #else
201 return (mi_msecs_t)clock() / ((mi_msecs_t)CLOCKS_PER_SEC / 1000);
202 #endif
203}
204
205#endif
206
207
208//----------------------------------------------------------------
209// Process info
210//----------------------------------------------------------------
211
212void _mi_prim_process_info(mi_process_info_t* pinfo)
213{
214 // use defaults
215 MI_UNUSED(pinfo);
216}
217
218
219//----------------------------------------------------------------
220// Output
221//----------------------------------------------------------------
222
223void _mi_prim_out_stderr( const char* msg ) {
224 fputs(msg,stderr);
225}
226
227
228//----------------------------------------------------------------
229// Environment
230//----------------------------------------------------------------
231
232bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
233 // cannot call getenv() when still initializing the C runtime.
234 if (_mi_preloading()) return false;
235 const char* s = getenv(name);
236 if (s == NULL) {
237 // we check the upper case name too.
238 char buf[64+1];
239 size_t len = _mi_strnlen(name,sizeof(buf)-1);
240 for (size_t i = 0; i < len; i++) {
241 buf[i] = _mi_toupper(name[i]);
242 }
243 buf[len] = 0;
244 s = getenv(buf);
245 }
246 if (s == NULL || _mi_strnlen(s,result_size) >= result_size) return false;
247 _mi_strlcpy(result, s, result_size);
248 return true;
249}
250
251
252//----------------------------------------------------------------
253// Random
254//----------------------------------------------------------------
255
256bool _mi_prim_random_buf(void* buf, size_t buf_len) {
257 return false;
258}
259
260
261//----------------------------------------------------------------
262// Thread init/done
263//----------------------------------------------------------------
264
265void _mi_prim_thread_init_auto_done(void) {
266 // nothing
267}
268
269void _mi_prim_thread_done_auto_done(void) {
270 // nothing
271}
272
273void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) {
274 MI_UNUSED(heap);
275}
276