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