]> git.llucax.com Git - software/dgc/cdgc.git/blob - gc/alloc.d
f7970da269ccc28dcc1585789d9663af7a08d2ad
[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 static if (is(typeof(VirtualAlloc)))
83 {
84     /**
85      * Map memory.
86      */
87     void *os_mem_map(size_t nbytes)
88     {
89         return VirtualAlloc(null, nbytes, MEM_RESERVE, PAGE_READWRITE);
90     }
91
92
93     /**
94      * Commit memory.
95      * Returns:
96      *      0       success
97      *      !=0     failure
98      */
99     int os_mem_commit(void *base, size_t offset, size_t nbytes)
100     {   void *p;
101
102         p = VirtualAlloc(base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE);
103     return cast(int)(p is null);
104     }
105
106
107     /**
108      * Decommit memory.
109      * Returns:
110      *      0       success
111      *      !=0     failure
112      */
113     int os_mem_decommit(void *base, size_t offset, size_t nbytes)
114     {
115     return cast(int)(VirtualFree(base + offset, nbytes, MEM_DECOMMIT) == 0);
116     }
117
118
119     /**
120      * Unmap memory allocated with os_mem_map().
121      * Memory must have already been decommitted.
122      * Returns:
123      *      0       success
124      *      !=0     failure
125      */
126     int os_mem_unmap(void *base, size_t nbytes)
127     {
128         return cast(int)(VirtualFree(base, 0, MEM_RELEASE) == 0);
129     }
130 }
131 else static if (is(typeof(mmap)) && is(typeof(MAP_ANON)))
132 {
133     void *os_mem_map(size_t nbytes)
134     {   void *p;
135
136         p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
137         return (p == MAP_FAILED) ? null : p;
138     }
139
140
141     int os_mem_commit(void *base, size_t offset, size_t nbytes)
142     {
143         return 0;
144     }
145
146
147     int os_mem_decommit(void *base, size_t offset, size_t nbytes)
148     {
149         return 0;
150     }
151
152
153     int os_mem_unmap(void *base, size_t nbytes)
154     {
155         return munmap(base, nbytes);
156     }
157 }
158 else static if (is(typeof(malloc)))
159 {
160     // NOTE: This assumes malloc granularity is at least (void*).sizeof.  If
161     //       (req_size + PAGESIZE) is allocated, and the pointer is rounded up
162     //       to PAGESIZE alignment, there will be space for a void* at the end
163     //       after PAGESIZE bytes used by the GC.
164
165
166     import gcx; // for PAGESIZE
167
168
169     const size_t PAGE_MASK = PAGESIZE - 1;
170
171
172     void *os_mem_map(size_t nbytes)
173     {   byte *p, q;
174         p = cast(byte *) malloc(nbytes + PAGESIZE);
175         q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK);
176         * cast(void**)(q + nbytes) = p;
177         return q;
178     }
179
180
181     int os_mem_commit(void *base, size_t offset, size_t nbytes)
182     {
183         return 0;
184     }
185
186
187     int os_mem_decommit(void *base, size_t offset, size_t nbytes)
188     {
189         return 0;
190     }
191
192
193     int os_mem_unmap(void *base, size_t nbytes)
194     {
195         free( *cast(void**)( cast(byte*) base + nbytes ) );
196         return 0;
197     }
198 }
199 else
200 {
201     static assert(false, "No supported allocation methods available.");
202 }