]> git.llucax.com Git - software/dgc/cdgc.git/blob - gc/alloc.d
55d0497a7296e541008e7c09bd0ca97f5733f7b9
[software/dgc/cdgc.git] / gc / alloc.d
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
27 module gc.alloc;
28
29 // C OS-specific API
30 private extern (C) {
31     version (Win32) {
32         alias void* POINTER;
33         alias POINTER LPVOID;
34         alias uint DWORD;
35         alias int WINBOOL;
36         enum: DWORD {
37             PAGE_READWRITE = 4,
38             MEM_RESERVE = 8192,
39             MEM_COMMIT = 4096,
40             MEM_DECOMMIT = 16384,
41             MEM_RELEASE = 32768,
42         }
43         LPVOID VirtualAlloc(LPVOID, DWORD, DWORD, DWORD);
44         WINBOOL VirtualFree(LPVOID, DWORD, DWORD);
45     }
46     else version (Posix) {
47         version (linux) enum: bool { OPTIONAL_LARGEFILE_SUPPORT = true }
48         else version (solaris) enum: bool { OPTIONAL_LARGEFILE_SUPPORT = true }
49         else enum: bool { OPTIONAL_LARGEFILE_SUPPORT = false }
50         static if (OPTIONAL_LARGEFILE_SUPPORT)
51             enum: bool { USE_LARGEFILE64 = ((void*).sizeof == 4) }
52         else
53             enum: bool { USE_LARGEFILE64 = false }
54         static if (USE_LARGEFILE64 || (void*).sizeof > int.sizeof)
55             alias long off_t;
56         else
57             alias int off_t;
58         enum: int {
59             PROT_NONE = 0x0,
60             PROT_READ = 0x1,
61             PROT_WRITE = 0x2,
62             PROT_EXEC = 0x4,
63             MAP_SHARED = 0x01,
64             MAP_PRIVATE = 0x02,
65             MAP_FIXED = 0x10,
66         }
67         const MAP_FAILED = cast(void*) -1;
68         // Non-standard, but needed
69         version (linux) { enum: int { MAP_ANON = 0x20 } }
70         else version (darwin) { enum: int { MAP_ANON = 0x1000 } }
71         else version (freebsd) { enum: int { MAP_ANON = 0x1000 } }
72         else version (solaris) { enum: int { MAP_ANON = 0x100 } }
73         void* mmap(void*, size_t, int, int, int, off_t);
74         int munmap(void*, size_t);
75     }
76     else {
77         // Standard C library
78         import gc.libc;
79     }
80 }
81
82 /+
83 static if(is(typeof(VirtualAlloc)))
84     version = GC_Use_Alloc_Win32;
85 else static if (is(typeof(mmap)))
86     version = GC_Use_Alloc_MMap;
87 else static if (is(typeof(valloc)))
88     version = GC_Use_Alloc_Valloc;
89 else static if (is(typeof(malloc)))
90     version = GC_Use_Alloc_Malloc;
91 else static assert(false, "No supported allocation methods available.");
92 +/
93
94 static if (is(typeof(VirtualAlloc))) // version (GC_Use_Alloc_Win32)
95 {
96     /**
97      * Map memory.
98      */
99     void *os_mem_map(size_t nbytes)
100     {
101         return VirtualAlloc(null, nbytes, MEM_RESERVE, PAGE_READWRITE);
102     }
103
104
105     /**
106      * Commit memory.
107      * Returns:
108      *      0       success
109      *      !=0     failure
110      */
111     int os_mem_commit(void *base, size_t offset, size_t nbytes)
112     {   void *p;
113
114         p = VirtualAlloc(base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE);
115     return cast(int)(p is null);
116     }
117
118
119     /**
120      * Decommit memory.
121      * Returns:
122      *      0       success
123      *      !=0     failure
124      */
125     int os_mem_decommit(void *base, size_t offset, size_t nbytes)
126     {
127     return cast(int)(VirtualFree(base + offset, nbytes, MEM_DECOMMIT) == 0);
128     }
129
130
131     /**
132      * Unmap memory allocated with os_mem_map().
133      * Memory must have already been decommitted.
134      * Returns:
135      *      0       success
136      *      !=0     failure
137      */
138     int os_mem_unmap(void *base, size_t nbytes)
139     {
140         return cast(int)(VirtualFree(base, 0, MEM_RELEASE) == 0);
141     }
142 }
143 else static if (is(typeof(mmap)))  // else version (GC_Use_Alloc_MMap)
144 {
145     void *os_mem_map(size_t nbytes)
146     {   void *p;
147
148         p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
149         return (p == MAP_FAILED) ? null : p;
150     }
151
152
153     int os_mem_commit(void *base, size_t offset, size_t nbytes)
154     {
155         return 0;
156     }
157
158
159     int os_mem_decommit(void *base, size_t offset, size_t nbytes)
160     {
161         return 0;
162     }
163
164
165     int os_mem_unmap(void *base, size_t nbytes)
166     {
167         return munmap(base, nbytes);
168     }
169 }
170 else static if (is(typeof(valloc))) // else version (GC_Use_Alloc_Valloc)
171 {
172     void *os_mem_map(size_t nbytes)
173     {
174         return valloc(nbytes);
175     }
176
177
178     int os_mem_commit(void *base, size_t offset, size_t nbytes)
179     {
180         return 0;
181     }
182
183
184     int os_mem_decommit(void *base, size_t offset, size_t nbytes)
185     {
186         return 0;
187     }
188
189
190     int os_mem_unmap(void *base, size_t nbytes)
191     {
192         free(base);
193         return 0;
194     }
195 }
196 else static if (is(typeof(malloc))) // else version (GC_Use_Alloc_Malloc)
197 {
198     // NOTE: This assumes malloc granularity is at least (void*).sizeof.  If
199     //       (req_size + PAGESIZE) is allocated, and the pointer is rounded up
200     //       to PAGESIZE alignment, there will be space for a void* at the end
201     //       after PAGESIZE bytes used by the GC.
202
203
204     import gcx; // for PAGESIZE
205
206
207     const size_t PAGE_MASK = PAGESIZE - 1;
208
209
210     void *os_mem_map(size_t nbytes)
211     {   byte *p, q;
212         p = cast(byte *) malloc(nbytes + PAGESIZE);
213         q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK);
214         * cast(void**)(q + nbytes) = p;
215         return q;
216     }
217
218
219     int os_mem_commit(void *base, size_t offset, size_t nbytes)
220     {
221         return 0;
222     }
223
224
225     int os_mem_decommit(void *base, size_t offset, size_t nbytes)
226     {
227         return 0;
228     }
229
230
231     int os_mem_unmap(void *base, size_t nbytes)
232     {
233         free( *cast(void**)( cast(byte*) base + nbytes ) );
234         return 0;
235     }
236 }
237 else
238 {
239     static assert(false, "No supported allocation methods available.");
240 }