microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billti/num2-sim

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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