Mercurial > projects > ldc
comparison runtime/internal/memory.d @ 577:68be7408a0db
Merge Dynamic_Ranges and Data_Proc_Maps from GDC runtime.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Thu, 04 Sep 2008 18:57:03 +0200 |
parents | 5d6ef6e6805d |
children | 8caa9adce5ae |
comparison
equal
deleted
inserted
replaced
576:d159da5201f1 | 577:68be7408a0db |
---|---|
23 * distribution. | 23 * distribution. |
24 * Authors: Walter Bright, Sean Kelly | 24 * Authors: Walter Bright, Sean Kelly |
25 */ | 25 */ |
26 module memory; | 26 module memory; |
27 | 27 |
28 version = GC_Use_Dynamic_Ranges; | |
29 | |
30 // does Posix suffice? | |
31 version(Posix) | |
32 { | |
33 version = GC_Use_Data_Proc_Maps; | |
34 } | |
35 | |
36 version(GC_Use_Data_Proc_Maps) | |
37 { | |
38 version(Posix) {} else { | |
39 static assert(false, "Proc Maps only supported on Posix systems"); | |
40 } | |
41 private import tango.stdc.posix.unistd; | |
42 private import tango.stdc.posix.fcntl; | |
43 private import tango.stdc.string; | |
44 | |
45 version = GC_Use_Dynamic_Ranges; | |
46 } | |
28 | 47 |
29 private | 48 private |
30 { | 49 { |
31 version( linux ) | 50 version( linux ) |
32 { | 51 { |
150 } | 169 } |
151 | 170 |
152 alias __data_start Data_Start; | 171 alias __data_start Data_Start; |
153 alias _end Data_End; | 172 alias _end Data_End; |
154 } | 173 } |
155 else version( darwin ) | 174 |
156 { | 175 version( GC_Use_Dynamic_Ranges ) |
157 // TODO: How to access the darwin data segment? | 176 { |
177 private import tango.stdc.stdlib; | |
178 | |
179 struct DataSeg | |
180 { | |
181 void* beg; | |
182 void* end; | |
183 } | |
184 | |
185 DataSeg* allSegs = null; | |
186 size_t numSegs = 0; | |
187 | |
188 extern (C) void _d_gc_add_range( void* beg, void* end ) | |
189 { | |
190 void* ptr = realloc( allSegs, (numSegs + 1) * DataSeg.sizeof ); | |
191 | |
192 if( ptr ) // if realloc fails, we have problems | |
193 { | |
194 allSegs = cast(DataSeg*) ptr; | |
195 allSegs[numSegs].beg = beg; | |
196 allSegs[numSegs].end = end; | |
197 numSegs++; | |
198 } | |
199 } | |
200 | |
201 extern (C) void _d_gc_remove_range( void* beg ) | |
202 { | |
203 for( size_t pos = 0; pos < numSegs; ++pos ) | |
204 { | |
205 if( beg == allSegs[pos].beg ) | |
206 { | |
207 while( ++pos < numSegs ) | |
208 { | |
209 allSegs[pos-1] = allSegs[pos]; | |
210 } | |
211 numSegs--; | |
212 return; | |
213 } | |
214 } | |
215 } | |
158 } | 216 } |
159 | 217 |
160 alias void delegate( void*, void* ) scanFn; | 218 alias void delegate( void*, void* ) scanFn; |
219 | |
220 void* dataStart, dataEnd; | |
161 } | 221 } |
162 | 222 |
163 | 223 |
164 /** | 224 /** |
165 * | 225 * |
166 */ | 226 */ |
167 extern (C) void rt_scanStaticData( scanFn scan ) | 227 extern (C) void rt_scanStaticData( scanFn scan ) |
168 { | 228 { |
229 scan( dataStart, dataEnd ); | |
230 | |
231 version( GC_Use_Dynamic_Ranges ) | |
232 { | |
233 for( size_t pos = 0; pos < numSegs; ++pos ) | |
234 { | |
235 scan( allSegs[pos].beg, allSegs[pos].end ); | |
236 } | |
237 } | |
238 } | |
239 | |
240 void initStaticDataPtrs() | |
241 { | |
242 const int S = (void*).sizeof; | |
243 | |
244 // Can't assume the input addresses are word-aligned | |
245 static void* adjust_up( void* p ) | |
246 { | |
247 return p + ((S - (cast(size_t)p & (S-1))) & (S-1)); // cast ok even if 64-bit | |
248 } | |
249 | |
250 static void * adjust_down( void* p ) | |
251 { | |
252 return p - (cast(size_t) p & (S-1)); | |
253 } | |
254 | |
169 version( Win32 ) | 255 version( Win32 ) |
170 { | 256 { |
171 scan( &Data_Start, &Data_End ); | 257 dataStart = adjust_up( &Data_Start ); |
172 } | 258 dataEnd = adjust_down( &Data_End ); |
173 else version( linux ) | 259 } |
174 { | 260 else version( GC_Use_Data_Proc_Maps ) |
175 //printf("scanning static data from %p to %p\n", &Data_Start, &Data_End); | 261 { |
176 scan( &Data_Start, &Data_End ); | 262 // TODO: Exclude zero-mapped regions |
177 } | 263 |
178 else version( darwin ) | 264 int fd = open("/proc/self/maps", O_RDONLY); |
179 { | 265 int count; // %% need to configure ret for read.. |
180 static assert( false, "darwin not supported." ); | 266 char buf[2024]; |
267 char* p; | |
268 char* e; | |
269 char* s; | |
270 void* start; | |
271 void* end; | |
272 | |
273 p = buf.ptr; | |
274 if (fd != -1) | |
275 { | |
276 while ( (count = read(fd, p, buf.sizeof - (p - buf.ptr))) > 0 ) | |
277 { | |
278 e = p + count; | |
279 p = buf.ptr; | |
280 while (true) | |
281 { | |
282 s = p; | |
283 while (p < e && *p != '\n') | |
284 p++; | |
285 if (p < e) | |
286 { | |
287 // parse the entry in [s, p) | |
288 static if( S == 4 ) | |
289 { | |
290 enum Ofs | |
291 { | |
292 Write_Prot = 19, | |
293 Start_Addr = 0, | |
294 End_Addr = 9, | |
295 Addr_Len = 8, | |
296 } | |
297 } | |
298 else static if( S == 8 ) | |
299 { | |
300 enum Ofs | |
301 { | |
302 Write_Prot = 35, | |
303 Start_Addr = 0, | |
304 End_Addr = 9, | |
305 Addr_Len = 17, | |
306 } | |
307 } | |
308 else | |
309 { | |
310 static assert( false ); | |
311 } | |
312 | |
313 // %% this is wrong for 64-bit: | |
314 // uint strtoul(char *,char **,int); | |
315 | |
316 if( s[Ofs.Write_Prot] == 'w' ) | |
317 { | |
318 s[Ofs.Start_Addr + Ofs.Addr_Len] = '\0'; | |
319 s[Ofs.End_Addr + Ofs.Addr_Len] = '\0'; | |
320 start = cast(void*) strtoul(s + Ofs.Start_Addr, null, 16); | |
321 end = cast(void*) strtoul(s + Ofs.End_Addr, null, 16); | |
322 | |
323 // 1. Exclude anything overlapping [dataStart, dataEnd) | |
324 // 2. Exclude stack | |
325 if ( ( !dataEnd || | |
326 !( dataStart >= start && dataEnd <= end ) ) && | |
327 !( &buf[0] >= start && &buf[0] < end ) ) | |
328 { | |
329 // we already have static data from this region. anything else | |
330 // is heap (%% check) | |
331 debug (ProcMaps) printf("Adding map range %p 0%p\n", start, end); | |
332 _d_gc_add_range(start, end); | |
333 } | |
334 } | |
335 p++; | |
336 } | |
337 else | |
338 { | |
339 count = p - s; | |
340 memmove(buf.ptr, s, count); | |
341 p = buf.ptr + count; | |
342 break; | |
343 } | |
344 } | |
345 } | |
346 close(fd); | |
347 } | |
348 } | |
349 else version(linux) | |
350 { | |
351 dataStart = adjust_up( &Data_Start ); | |
352 dataEnd = adjust_down( &Data_End ); | |
181 } | 353 } |
182 else | 354 else |
183 { | 355 { |
184 static assert( false, "Operating system not supported." ); | 356 static assert( false, "Operating system not supported." ); |
185 } | 357 } |