Revert some changes which don't have proper dependencies.
[mono-project.git] / mono / utils / mono-mmap-windows.c
blob1b3a1399693ec93323d2e988b11153985a6b9205
1 /**
2 * \file
3 * Windows support for mapping code into the process address space
5 * Author:
6 * Mono Team (mono-list@lists.ximian.com)
8 * Copyright 2001-2008 Novell, Inc.
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include <config.h>
13 #include <glib.h>
15 #if defined(HOST_WIN32)
16 #include <windows.h>
17 #include "mono/utils/mono-mmap-windows-internals.h"
18 #include <mono/utils/mono-counters.h>
19 #include <io.h>
21 static void *malloced_shared_area;
23 int
24 mono_pagesize (void)
26 SYSTEM_INFO info;
27 static int saved_pagesize = 0;
28 if (saved_pagesize)
29 return saved_pagesize;
30 GetSystemInfo (&info);
31 saved_pagesize = info.dwPageSize;
32 return saved_pagesize;
35 int
36 mono_valloc_granule (void)
38 SYSTEM_INFO info;
39 static int saved_valloc_granule = 0;
40 if (saved_valloc_granule)
41 return saved_valloc_granule;
42 GetSystemInfo (&info);
43 saved_valloc_granule = info.dwAllocationGranularity;
44 return saved_valloc_granule;
47 int
48 mono_mmap_win_prot_from_flags (int flags)
50 int prot = flags & (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC);
51 switch (prot) {
52 case 0: prot = PAGE_NOACCESS; break;
53 case MONO_MMAP_READ: prot = PAGE_READONLY; break;
54 case MONO_MMAP_READ|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READ; break;
55 case MONO_MMAP_READ|MONO_MMAP_WRITE: prot = PAGE_READWRITE; break;
56 case MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break;
57 case MONO_MMAP_WRITE: prot = PAGE_READWRITE; break;
58 case MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break;
59 case MONO_MMAP_EXEC: prot = PAGE_EXECUTE; break;
60 default:
61 g_assert_not_reached ();
63 return prot;
66 /**
67 * mono_setmmapjit:
68 * \param flag indicating whether to enable or disable the use of MAP_JIT in mmap
70 * Call this method to enable or disable the use of MAP_JIT to create the pages
71 * for the JIT to use. This is only needed for scenarios where Mono is bundled
72 * as an App in MacOS
74 void
75 mono_setmmapjit (int flag)
77 /* Ignored on HOST_WIN32 */
80 void*
81 mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
83 if (!mono_valloc_can_alloc (length))
84 return NULL;
86 void *ptr;
87 int mflags = MEM_RESERVE|MEM_COMMIT;
88 int prot = mono_mmap_win_prot_from_flags (flags);
89 /* translate the flags */
91 ptr = VirtualAlloc (addr, length, mflags, prot);
93 mono_account_mem (type, (ssize_t)length);
95 return ptr;
98 void*
99 mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountType type)
101 int prot = mono_mmap_win_prot_from_flags (flags);
102 char *mem = (char*)VirtualAlloc (NULL, length + alignment, MEM_RESERVE, prot);
103 char *aligned;
105 if (!mem)
106 return NULL;
108 if (!mono_valloc_can_alloc (length))
109 return NULL;
111 aligned = mono_aligned_address (mem, length, alignment);
113 aligned = (char*)VirtualAlloc (aligned, length, MEM_COMMIT, prot);
114 g_assert (aligned);
116 mono_account_mem (type, (ssize_t)length);
118 return aligned;
122 mono_vfree (void *addr, size_t length, MonoMemAccountType type)
124 MEMORY_BASIC_INFORMATION mbi;
125 SIZE_T query_result = VirtualQuery (addr, &mbi, sizeof (mbi));
126 BOOL res;
128 g_assert (query_result);
130 res = VirtualFree (mbi.AllocationBase, 0, MEM_RELEASE);
132 g_assert (res);
134 mono_account_mem (type, -(ssize_t)length);
136 return 0;
139 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) || G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
141 static void
142 remove_trailing_whitespace_utf16 (wchar_t *s)
144 gsize length = wcslen (s);
145 gsize const original_length = length;
146 while (length > 0 && iswspace (s [length - 1]))
147 --length;
148 if (length != original_length)
149 s [length] = 0;
152 void*
153 mono_file_map_error (size_t length, int flags, int fd, guint64 offset, void **ret_handle,
154 const char *filepath, char **error_message)
156 void *ptr = NULL;
157 HANDLE mapping = NULL;
158 int const prot = mono_mmap_win_prot_from_flags (flags);
159 /* translate the flags */
160 /*if (flags & MONO_MMAP_PRIVATE)
161 mflags |= MAP_PRIVATE;
162 if (flags & MONO_MMAP_SHARED)
163 mflags |= MAP_SHARED;
164 if (flags & MONO_MMAP_ANON)
165 mflags |= MAP_ANONYMOUS;
166 if (flags & MONO_MMAP_FIXED)
167 mflags |= MAP_FIXED;
168 if (flags & MONO_MMAP_32BIT)
169 mflags |= MAP_32BIT;*/
170 int const mflags = (flags & MONO_MMAP_WRITE) ? FILE_MAP_COPY : FILE_MAP_READ;
171 HANDLE const file = (HANDLE)_get_osfhandle (fd);
172 const char *failed_function = NULL;
174 // The size of the mapping is the maximum file offset to map.
176 // It is not, as you might expect, the maximum view size to be mapped from it.
178 // If it were the maximum view size, the size parameter would have just
179 // been one DWORD in 32bit Windows, expanded to SIZE_T in 64bit Windows.
180 // It is 64bits even on 32bit Windows to allow large files.
182 // See https://docs.microsoft.com/en-us/windows/desktop/Memory/creating-a-file-mapping-object.
183 const guint64 mapping_length = offset + length;
185 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
187 failed_function = "CreateFileMapping";
188 mapping = CreateFileMappingW (file, NULL, prot, (DWORD)(mapping_length >> 32), (DWORD)mapping_length, NULL);
189 if (mapping == NULL)
190 goto exit;
192 failed_function = "MapViewOfFile";
193 ptr = MapViewOfFile (mapping, mflags, (DWORD)(offset >> 32), (DWORD)offset, length);
194 if (ptr == NULL)
195 goto exit;
197 #elif G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
199 failed_function = "CreateFileMappingFromApp";
200 mapping = CreateFileMappingFromApp (file, NULL, prot, mapping_length, NULL);
201 if (mapping == NULL)
202 goto exit;
204 failed_function = "MapViewOfFileFromApp";
205 ptr = MapViewOfFileFromApp (mapping, mflags, offset, length);
206 if (ptr == NULL)
207 goto exit;
209 #else
210 #error unknown Windows variant
211 #endif
213 exit:
214 if (!ptr && (mapping || error_message)) {
215 int const win32_error = GetLastError ();
216 if (mapping)
217 CloseHandle (mapping);
218 if (error_message) {
219 WCHAR win32_error_string [100] = { 0 }; // FIXME LocalFree not initially in UWP but it is now.
220 FormatMessageW (FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
221 0, win32_error, 0, win32_error_string, 99, NULL);
222 // Win32 error messages end with an unsightly newline.
223 remove_trailing_whitespace_utf16 (win32_error_string);
224 *error_message = g_strdup_printf ("%s failed file:%s length:0x%IX offset:0x%I64X function:%s error:%ls(0x%X)\n",
225 __func__, filepath ? filepath : "", length, offset, failed_function, win32_error_string, win32_error);
227 SetLastError (win32_error);
229 *ret_handle = mapping;
230 return ptr;
233 void*
234 mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle)
236 return mono_file_map_error (length, flags, fd, offset, ret_handle, NULL, NULL);
240 mono_file_unmap (void *addr, void *handle)
242 UnmapViewOfFile (addr);
243 CloseHandle (handle);
244 return 0;
247 #endif // G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) || G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
250 mono_mprotect (void *addr, size_t length, int flags)
252 DWORD oldprot;
253 int prot = mono_mmap_win_prot_from_flags (flags);
255 if (flags & MONO_MMAP_DISCARD) {
256 VirtualFree (addr, length, MEM_DECOMMIT);
257 VirtualAlloc (addr, length, MEM_COMMIT, prot);
258 return 0;
260 return VirtualProtect (addr, length, prot, &oldprot) == 0;
263 void*
264 mono_shared_area (void)
266 if (!malloced_shared_area)
267 malloced_shared_area = mono_malloc_shared_area (0);
268 /* get the pid here */
269 return malloced_shared_area;
272 void
273 mono_shared_area_remove (void)
275 if (malloced_shared_area)
276 g_free (malloced_shared_area);
277 malloced_shared_area = NULL;
280 void*
281 mono_shared_area_for_pid (void *pid)
283 return NULL;
286 void
287 mono_shared_area_unload (void *area)
292 mono_shared_area_instances (void **array, int count)
294 return 0;
297 #endif // HOST_WIN32