Kernel/VTerm - "Fix" wrapping issue in VTerm (why was old behavior there?)
[tpg/acess2.git] / AcessNative / ld-acess_src / memory.c
1 /*
2  */
3 #define _GNU_SOURCE     // needed for MAP_ANONYMOUS to be avaliable
4 #include "common.h"
5 #include <stdio.h>
6 #include <stdlib.h>
7 #if __WIN32__
8 # include <windows.h>
9 #else
10 # include <sys/mman.h>
11 # include <errno.h>
12 #endif
13
14 // === PROTOTYPES ===
15  int    AllocateMemory(uintptr_t VirtAddr, size_t ByteCount);
16 uintptr_t       FindFreeRange(size_t ByteCount, int MaxBits);
17
18 // === CODE ===
19 int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount)
20 {
21         uintptr_t       base = (VirtAddr >> 12) << 12;
22         size_t  size = (VirtAddr & 0xFFF) + ByteCount;
23         void    *tmp;
24         #if __WIN32__
25         do
26         {
27                 MEMORY_BASIC_INFORMATION        info;
28                 VirtualQuery( (void*)base, &info, sizeof(info) );
29                 if( info.State != MEM_FREE ) {
30                         printf("ERROR: Unable to allocate memory %p+0x%x, already allocated\n",
31                                 (void*)base, size);
32                         base += 0x1000;
33                         if( size < 0x1000 )
34                                 return 0;
35                         size -= 0x1000;
36                 }
37                 else
38                         break;
39         } while( size >= 0x1000 );
40         tmp = VirtualAlloc((void*)base, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
41         if( tmp == NULL ) {
42                 printf("ERROR: Unable to allocate memory %p+%x (0x%x)\n",
43                         (void*)base, size,
44                         (int)GetLastError());
45                 return -1;
46         }
47         #else
48 //      printf("AllocateMemory: mmap(%p, 0x%lx, ...)\n", (void*)base, ByteCount);
49         tmp = mmap((void*)base, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
50         if( tmp == MAP_FAILED ) {
51                 printf("ERROR: Unable to allocate memory\n");
52                 perror("AllocateMemory");
53                 return -1;
54         }
55 //      printf("AllocateMemory: RETURN 0\n");
56         #endif
57         return 0;
58 }
59
60 uintptr_t FindFreeRange(size_t ByteCount, int MaxBits)
61 {
62         uintptr_t       base, ofs, size;
63         uintptr_t       end = -1;
64         static const int        PAGE_SIZE = 0x1000;
65         
66         size = (ByteCount + PAGE_SIZE - 1) / PAGE_SIZE;
67         size *= PAGE_SIZE;
68
69         end <<= (sizeof(intptr_t)*8-MaxBits);
70         end >>= (sizeof(intptr_t)*8-MaxBits);
71 //      printf("end = %p\n", (void*)end);
72         
73 //      for( base = 0; base < end - size; base -= PAGE_SIZE )
74         for( base = end - size + 1; base > 0; base -= PAGE_SIZE )
75         {
76                 for( ofs = 0; ofs < size; ofs += PAGE_SIZE ) {
77                         #if __WIN32__
78                         MEMORY_BASIC_INFORMATION        info;
79                         VirtualQuery( (void*)(base + ofs), &info, sizeof(info) );
80                         if( info.State != MEM_FREE )
81                                 break;
82                         #else
83                         if( msync( (void*)(base+ofs), 1, 0) == 0 )
84                                 break;
85                         if( errno != ENOMEM )
86                                 perror("FindFreeRange, msync");
87                         #endif
88                 }
89                 if( ofs >= size ) {
90                         return base;
91                 }
92         }
93         return 0;
94 }

UCC git Repository :: git.ucc.asn.au