2 * This module contains allocation functions for the garbage collector.
4 * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
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.
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
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
24 * Authors: Walter Bright, David Friedman, Sean Kelly, Leandro Lucarella
31 ////////////////////////////////////////////////////////////////////////
33 // Public interface/Documentation
36 * Possible results for the wait_pid() function.
40 DONE, /// The process has finished successfully
41 RUNNING, /// The process is still running
42 ERROR /// There was an error waiting for the process
48 * Indicates if an implementation support fork().
50 * The value shown here is just demostrative, the real value is defined based
51 * on the OS it's being compiled in.
53 const HAVE_FORK = true;
56 * Wait for a process with PID pid to finish.
58 * If block is false, this function will not block, and return WRes.RUNNING if
59 * the process is still running. Otherwise it will return always WRes.DONE
60 * (unless there is an error, in which case WRes.ERROR is returned).
62 WRes wait_pid(pid_t pid, bool block = true);
64 public import tango.stdc.posix.unistd: pid_t, fork;
69 else version (Posix) {
70 enum { HAVE_FORK = true }
71 public import tango.stdc.posix.unistd: pid_t, fork;
72 import tango.stdc.posix.sys.wait: waitpid, WNOHANG;
73 public WRes wait_pid(pid_t pid, bool block = true) {
75 pid_t waited_pid = waitpid(pid, &status, block ? 0 : WNOHANG);
78 assert (waited_pid == pid);
80 if (waited_pid != pid || status != 0)
87 enum { HAVE_FORK = false }
89 pid_t fork() { assert (false); return -1; }
90 WRes wait_pid(pid_t, bool = true) { assert (false); return false; }
95 ////////////////////////////////////////////////////////////////////////
98 import tango.sys.win32.UserGdi;
100 import tango.stdc.posix.sys.mman;
102 import tango.stdc.stdlib;
105 // Public interface/Documentation
108 * Visibility of the mapped memory.
112 PRIV, /// Private to this process
113 SHARED, /// Shared across fork()ed processes (only when HAVE_SHARED)
119 * Indicates if an implementation support mapping shared memory.
121 * The value shown here is just demostrative, the real value is defined based
122 * on the OS it's being compiled in.
124 const HAVE_SHARED = false;
129 void* alloc(size_t nbytes, Vis vis = Vis.PRIV);
132 * Unmap memory allocated with alloc().
137 bool dealloc(void* base, size_t nbytes, Vis vis = Vis.PRIV);
142 else static if (is(typeof(VirtualAlloc))) {
143 enum { HAVE_SHARED = false }
145 void* alloc(size_t nbytes, Vis vis = Vis.PRIV)
147 assert (vis == Vis.PRIV);
148 return VirtualAlloc(null, nbytes, MEM_RESERVE | MEM_COMMIT,
152 bool dealloc(void* base, size_t nbytes, Vis vis = Vis.PRIV)
154 assert (vis == Vis.PRIV);
155 return VirtualFree(base, 0, MEM_RELEASE) != 0;
160 else static if (is(typeof(mmap)) && is(typeof(MAP_ANON))) {
161 enum { HAVE_SHARED = true }
163 void* alloc(size_t nbytes, Vis vis = Vis.PRIV)
165 auto flags = MAP_ANON;
166 if (vis == Vis.SHARED)
169 flags |= MAP_PRIVATE;
170 void* p = mmap(null, nbytes, PROT_READ | PROT_WRITE, flags, -1, 0);
171 return (p == MAP_FAILED) ? null : p;
174 bool dealloc(void* base, size_t nbytes, Vis vis = Vis.PRIV)
176 // vis is not necessary to unmap
177 return munmap(base, nbytes) == 0;
181 else static if (is(typeof(malloc))) {
182 enum { HAVE_SHARED = false }
184 // NOTE: This assumes malloc granularity is at least (void*).sizeof. If
185 // (req_size + PAGESIZE) is allocated, and the pointer is rounded up
186 // to PAGESIZE alignment, there will be space for a void* at the end
187 // after PAGESIZE bytes used by the GC.
189 import rt.gc.cdgc.gc: PAGESIZE;
191 const size_t PAGE_MASK = PAGESIZE - 1;
193 void* alloc(size_t nbytes, Vis vis = Vis.PRIV)
195 assert (vis == Vis.PRIV);
197 p = cast(byte* ) malloc(nbytes + PAGESIZE);
198 q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK);
199 *cast(void**)(q + nbytes) = p;
203 bool dealloc(void* base, size_t nbytes, Vis vis = Vis.PRIV)
205 assert (vis == Vis.PRIV);
206 free(*cast(void**)(cast(byte*) base + nbytes));
211 else static assert(false, "No supported allocation methods available.");
214 // vim: set et sw=4 sts=4 :