1 /** 2 * This module contains allocation functions for the garbage collector. 3 * 4 * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com. 5 * All rights reserved. 6 * License: 7 * This software is provided 'as-is', without any express or implied 8 * warranty. In no event will the authors be held liable for any damages 9 * arising from the use of this software. 10 * 11 * Permission is granted to anyone to use this software for any purpose, 12 * including commercial applications, and to alter it and redistribute it 13 * freely, in both source and binary form, subject to the following 14 * restrictions: 15 * 16 * o The origin of this software must not be misrepresented; you must not 17 * claim that you wrote the original software. If you use this software 18 * in a product, an acknowledgment in the product documentation would be 19 * appreciated but is not required. 20 * o Altered source versions must be plainly marked as such, and must not 21 * be misrepresented as being the original software. 22 * o This notice may not be removed or altered from any source 23 * distribution. 24 * Authors: Walter Bright, David Friedman, Sean Kelly 25 */ 26 module rt.gc.basic.gcalloc; 27 28 version (Win32) 29 { 30 private import tango.sys.win32.UserGdi; 31 32 alias int pthread_t; 33 34 pthread_t pthread_self() 35 { 36 return cast(pthread_t) GetCurrentThreadId(); 37 } 38 39 //version = GC_Use_Alloc_Win32; 40 } 41 else version (Posix) 42 { 43 private import tango.stdc.posix.sys.mman; 44 private import tango.stdc.stdlib; 45 46 //version = GC_Use_Alloc_MMap; 47 } 48 else 49 { 50 private import tango.stdc.stdlib; 51 52 //version = GC_Use_Alloc_Malloc; 53 } 54 55 /+ 56 static if(is(typeof(VirtualAlloc))) 57 version = GC_Use_Alloc_Win32; 58 else static if (is(typeof(mmap))) 59 version = GC_Use_Alloc_MMap; 60 else static if (is(typeof(valloc))) 61 version = GC_Use_Alloc_Valloc; 62 else static if (is(typeof(malloc))) 63 version = GC_Use_Alloc_Malloc; 64 else static assert(false, "No supported allocation methods available."); 65 +/ 66 67 static if (is(typeof(VirtualAlloc))) // version (GC_Use_Alloc_Win32) 68 { 69 /** 70 * Map memory. 71 */ 72 void *os_mem_map(size_t nbytes) 73 { 74 return VirtualAlloc(null, nbytes, MEM_RESERVE, PAGE_READWRITE); 75 } 76 77 78 /** 79 * Commit memory. 80 * Returns: 81 * 0 success 82 * !=0 failure 83 */ 84 int os_mem_commit(void *base, size_t offset, size_t nbytes) 85 { void *p; 86 87 p = VirtualAlloc(base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE); 88 return cast(int)(p is null); 89 } 90 91 92 /** 93 * Decommit memory. 94 * Returns: 95 * 0 success 96 * !=0 failure 97 */ 98 int os_mem_decommit(void *base, size_t offset, size_t nbytes) 99 { 100 return cast(int)(VirtualFree(base + offset, nbytes, MEM_DECOMMIT) == 0); 101 } 102 103 104 /** 105 * Unmap memory allocated with os_mem_map(). 106 * Memory must have already been decommitted. 107 * Returns: 108 * 0 success 109 * !=0 failure 110 */ 111 int os_mem_unmap(void *base, size_t nbytes) 112 { 113 return cast(int)(VirtualFree(base, 0, MEM_RELEASE) == 0); 114 } 115 } 116 else static if (is(typeof(mmap))) // else version (GC_Use_Alloc_MMap) 117 { 118 debug(PRINTF) import tango.stdc.stdio: printf; 119 120 121 void *os_mem_map(size_t nbytes) 122 { void *p; 123 124 debug(PRINTF) printf("mmap alloc of %p bytes\n", nbytes); 125 p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 126 return (p == MAP_FAILED) ? null : p; 127 } 128 129 130 int os_mem_commit(void *base, size_t offset, size_t nbytes) 131 { 132 return 0; 133 } 134 135 136 int os_mem_decommit(void *base, size_t offset, size_t nbytes) 137 { 138 return 0; 139 } 140 141 142 int os_mem_unmap(void *base, size_t nbytes) 143 { 144 return munmap(base, nbytes); 145 } 146 } 147 else static if (is(typeof(valloc))) // else version (GC_Use_Alloc_Valloc) 148 { 149 void *os_mem_map(size_t nbytes) 150 { 151 return valloc(nbytes); 152 } 153 154 155 int os_mem_commit(void *base, size_t offset, size_t nbytes) 156 { 157 return 0; 158 } 159 160 161 int os_mem_decommit(void *base, size_t offset, size_t nbytes) 162 { 163 return 0; 164 } 165 166 167 int os_mem_unmap(void *base, size_t nbytes) 168 { 169 free(base); 170 return 0; 171 } 172 } 173 else static if (is(typeof(malloc))) // else version (GC_Use_Alloc_Malloc) 174 { 175 // NOTE: This assumes malloc granularity is at least (void*).sizeof. If 176 // (req_size + PAGESIZE) is allocated, and the pointer is rounded up 177 // to PAGESIZE alignment, there will be space for a void* at the end 178 // after PAGESIZE bytes used by the GC. 179 180 181 private import rt.gc.basic.gcx; // for PAGESIZE 182 183 184 const size_t PAGE_MASK = PAGESIZE - 1; 185 186 187 void *os_mem_map(size_t nbytes) 188 { byte *p, q; 189 p = cast(byte *) malloc(nbytes + PAGESIZE); 190 q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK); 191 * cast(void**)(q + nbytes) = p; 192 return q; 193 } 194 195 196 int os_mem_commit(void *base, size_t offset, size_t nbytes) 197 { 198 return 0; 199 } 200 201 202 int os_mem_decommit(void *base, size_t offset, size_t nbytes) 203 { 204 return 0; 205 } 206 207 208 int os_mem_unmap(void *base, size_t nbytes) 209 { 210 free( *cast(void**)( cast(byte*) base + nbytes ) ); 211 return 0; 212 } 213 } 214 else 215 { 216 static assert(false, "No supported allocation methods available."); 217 }