]> git.llucax.com Git - software/dgc/cdgc.git/blob - rt/gc/cdgc/alloc.d
eeeab73528428a37d6cab5b61a36737165fd8dc2
[software/dgc/cdgc.git] / rt / gc / cdgc / 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 rt.gc.cdgc.alloc;
28
29 version (Win32)
30     import tango.sys.win32.UserGdi;
31 else version (Posix)
32     import tango.stdc.posix.sys.mman;
33 else
34     import tango.stdc.stdlib;
35
36
37 // Public interface/Documentation
38
39 /**
40  * Visibility of the mapped memory.
41  */
42 enum Vis
43 {
44     PRIV, /// Private to this process
45     SHARED, /// Shared across fork()ed processes (only when HAVE_SHARED)
46 }
47
48 version (D_Ddoc) {
49
50 /**
51  * Indicates if an implementation support mapping shared memory.
52  *
53  * The value shown here is just demostrative, the real value is defined based
54  * on the OS it's being compiled in.
55  */
56 const HAVE_SHARED = false;
57
58 /**
59  * Map memory.
60  */
61 void* os_mem_map(size_t nbytes, Vis vis = Vis.PRIV);
62
63 /**
64  * Unmap memory allocated with os_mem_map().
65  * Returns:
66  *      true  success
67  *      false failure
68  */
69 bool os_mem_unmap(void* base, size_t nbytes, Vis vis = Vis.PRIV);
70
71 }
72
73 // Implementations
74 else static if (is(typeof(VirtualAlloc))) {
75     enum { HAVE_SHARED = false }
76
77     void* os_mem_map(size_t nbytes, Vis vis = Vis.PRIV)
78     {
79         assert (vis == Vis.PRIV);
80         return VirtualAlloc(null, nbytes, MEM_RESERVE | MEM_COMMIT,
81                 PAGE_READWRITE);
82     }
83
84     bool os_mem_unmap(void* base, size_t nbytes, Vis vis = Vis.PRIV)
85     {
86         assert (vis == Vis.PRIV);
87         return VirtualFree(base, 0, MEM_RELEASE) != 0;
88     }
89
90 }
91
92 else static if (is(typeof(mmap)) && is(typeof(MAP_ANON))) {
93     enum { HAVE_SHARED = true }
94
95     void* os_mem_map(size_t nbytes, Vis vis = Vis.PRIV)
96     {
97         auto flags = MAP_ANON;
98         if (vis == Vis.SHARED)
99             flags |= MAP_SHARED;
100         else // PRIV
101             flags |= MAP_PRIVATE;
102         void* p = mmap(null, nbytes, PROT_READ | PROT_WRITE, flags, -1, 0);
103         return (p == MAP_FAILED) ? null : p;
104     }
105
106     bool os_mem_unmap(void* base, size_t nbytes, Vis vis = Vis.PRIV)
107     {
108         // vis is not necessary to unmap
109         return munmap(base, nbytes) == 0;
110     }
111 }
112
113 else static if (is(typeof(malloc))) {
114     enum { HAVE_SHARED = false }
115
116     // NOTE: This assumes malloc granularity is at least (void*).sizeof.  If
117     //       (req_size + PAGESIZE) is allocated, and the pointer is rounded up
118     //       to PAGESIZE alignment, there will be space for a void* at the end
119     //       after PAGESIZE bytes used by the GC.
120
121     import rt.gc.cdgc.gc: PAGESIZE;
122
123     const size_t PAGE_MASK = PAGESIZE - 1;
124
125     void* os_mem_map(size_t nbytes, Vis vis = Vis.PRIV)
126     {
127         assert (vis == Vis.PRIV);
128         byte* p, q;
129         p = cast(byte* ) malloc(nbytes + PAGESIZE);
130         q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK);
131         *cast(void**)(q + nbytes) = p;
132         return q;
133     }
134
135     bool os_mem_unmap(void* base, size_t nbytes, Vis vis = Vis.PRIV)
136     {
137         assert (vis == Vis.PRIV);
138         free(*cast(void**)(cast(byte*) base + nbytes));
139         return true;
140     }
141 }
142
143 else static assert(false, "No supported allocation methods available.");
144
145
146 // vim: set et sw=4 sts=4 :