add a thp-based huge page alloc fallback
[pcsx_rearmed.git] / deps / libretro-common / memmap / memmap.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (memmap.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <memmap.h>
26
27 #ifndef PROT_READ
28 #define PROT_READ         0x1  /* Page can be read */
29 #endif
30
31 #ifndef PROT_WRITE
32 #define PROT_WRITE        0x2  /* Page can be written. */
33 #endif
34
35 #ifndef PROT_READWRITE
36 #define PROT_READWRITE    0x3  /* Page can be written to and read from. */
37 #endif
38
39 #ifndef PROT_EXEC
40 #define PROT_EXEC         0x4  /* Page can be executed. */
41 #endif
42
43 #ifndef PROT_NONE
44 #define PROT_NONE         0x0  /* Page can not be accessed. */
45 #endif
46
47 #ifndef MAP_FAILED
48 #define MAP_FAILED        ((void *) -1)
49 #endif
50
51 #ifdef _WIN32
52 void* mmap(void *addr, size_t len, int prot, int flags,
53       int fildes, size_t offset)
54 {
55    void     *map = (void*)NULL;
56    HANDLE handle = INVALID_HANDLE_VALUE;
57
58    switch (prot)
59    {
60       case PROT_READ:
61       default:
62          handle = CreateFileMapping((HANDLE)
63                _get_osfhandle(fildes), 0, PAGE_READONLY, 0,
64                len, 0);
65          if (!handle)
66             break;
67          map = (void*)MapViewOfFile(handle, FILE_MAP_READ, 0, 0, len);
68          CloseHandle(handle);
69          break;
70       case PROT_WRITE:
71          handle = CreateFileMapping((HANDLE)
72                _get_osfhandle(fildes),0,PAGE_READWRITE,0,
73                len, 0);
74          if (!handle)
75             break;
76          map = (void*)MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, len);
77          CloseHandle(handle);
78          break;
79       case PROT_READWRITE:
80          handle = CreateFileMapping((HANDLE)
81                _get_osfhandle(fildes),0,PAGE_READWRITE,0,
82                len, 0);
83          if (!handle)
84             break;
85          map = (void*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, len);
86          CloseHandle(handle);
87          break;
88    }
89
90    if (map == (void*)NULL)
91       return((void*)MAP_FAILED);
92    return((void*) ((int8_t*)map + offset));
93 }
94
95 int munmap(void *addr, size_t length)
96 {
97    if (!UnmapViewOfFile(addr))
98       return -1;
99    return 0;
100 }
101
102 int mprotect(void *addr, size_t len, int prot)
103 {
104    /* Incomplete, just assumes PAGE_EXECUTE_READWRITE right now
105     * instead of correctly handling prot */
106    prot = 0;
107    if (prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
108       prot = PAGE_EXECUTE_READWRITE;
109    return VirtualProtect(addr, len, prot, 0);
110 }
111
112 #elif !defined(HAVE_MMAN)
113 void* mmap(void *addr, size_t len, int prot, int flags,
114       int fildes, size_t offset)
115 {
116    return malloc(len);
117 }
118
119 int munmap(void *addr, size_t len)
120 {
121    free(addr);
122    return 0;
123 }
124
125 int mprotect(void *addr, size_t len, int prot)
126 {
127    /* stub - not really needed at this point
128     * since this codepath has no dynarecs. */
129    return 0;
130 }
131
132 #endif
133
134 #if defined(__MACH__) && defined(__arm__)
135 #include <libkern/OSCacheControl.h>
136 #endif
137
138 int memsync(void *start, void *end)
139 {
140    size_t len = (char*)end - (char*)start;
141 #if defined(__MACH__) && defined(__arm__)
142    sys_dcache_flush(start ,len);
143    sys_icache_invalidate(start, len);
144    return 0;
145 #elif defined(__arm__) && !defined(__QNX__)
146    (void)len;
147    __clear_cache(start, end);
148    return 0;
149 #elif defined(HAVE_MMAN)
150    return msync(start, len, MS_SYNC | MS_INVALIDATE
151 #ifdef __QNX__
152          MS_CACHE_ONLY
153 #endif
154          );
155 #else
156    (void)len;
157    return 0;
158 #endif
159 }
160
161 int memprotect(void *addr, size_t len)
162 {
163    return mprotect(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC);
164 }