diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/internal/gc/gc.d patched_phobos/internal/gc/gc.d --- unpatched_phobos/internal/gc/gc.d 2008-02-06 03:35:44.000000000 +0100 +++ patched_phobos/internal/gc/gc.d 2008-02-06 15:20:57.000000000 +0100 @@ -309,7 +309,9 @@ debug(PRINTF) printf(" p = %p\n", p); if (!(ti.next.flags() & 1)) _gc.hasNoPointers(p); - if (isize == 1) + if (isize == 0) + memset(p, 0, size); + else if (isize == 1) memset(p, *cast(ubyte*)q, size); else if (isize == int.sizeof) { @@ -629,9 +631,12 @@ size_t initsize = initializer.length; assert(sizeelem); - assert(initsize); + // assert(initsize); + // there's a bug that accidentally calls this function with + // types with zero initializers. Deal with it for now. + // \todo: find underlying cause assert(initsize <= sizeelem); - assert((sizeelem / initsize) * initsize == sizeelem); + assert(!initsize || (sizeelem / initsize) * initsize == sizeelem); debug(PRINTF) { @@ -703,8 +708,12 @@ } auto q = initializer.ptr; // pointer to initializer - - if (newsize > size) + + if (initsize == 0) + { + memset(newdata + size, 0, newsize - size); + } + else if (newsize > size) { if (initsize == 1) { diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/internal/gc/gcx.d patched_phobos/internal/gc/gcx.d --- unpatched_phobos/internal/gc/gcx.d 2008-02-06 03:35:44.000000000 +0100 +++ patched_phobos/internal/gc/gcx.d 2008-02-06 03:28:17.000000000 +0100 @@ -10,6 +10,8 @@ Modified by David Friedman, July 2006 */ +private import std.gc, std.stack; + // D Garbage Collector implementation /************** Debugging ***************************/ @@ -1642,6 +1644,7 @@ if (t && t.getState() == Thread.TS.RUNNING) { + if (t.isSelf()) t.stack.lastESP = Thread.getESP(); if (noStack && threads.length == 1) break; @@ -1655,32 +1658,9 @@ assert(0); } debug (PRINTF) printf("mt scan stack bot = %x, top = %x\n", context.Esp, t.stackBottom); - mark(cast(void *)context.Esp, t.stackBottom); + //mark(cast(void *)context.Esp, t.stackBottom); mark(&context.Edi, &context.Eip); } - else version (GNU) - { - if (t.isSelf()) - t.stackTop = Thread.getESP(); - - //%%fry printf("top=%08x bot=%08x ext=%08x\n", t.stackTop, t.stackBottom, Thread.getESP());//%%try - version (STACKGROWSDOWN) - mark(t.stackTop, t.stackBottom); - else - mark(t.stackBottom, t.stackTop); - } - else version (linux) - { - // The registers are already stored in the stack - //printf("Thread: ESP = x%x, stackBottom = x%x, isSelf = %d\n", Thread.getESP(), t.stackBottom, t.isSelf()); - if (t.isSelf()) - t.stackTop = Thread.getESP(); - - version (STACKGROWSDOWN) - mark(t.stackTop, t.stackBottom); - else - mark(t.stackBottom, t.stackTop); - } } } } @@ -1710,6 +1690,15 @@ mark(ranges[n].pbot, ranges[n].ptop); } //log--; + // Scan stacks LL + auto cur = stacks; + while (cur) { + version(STACKGROWSDOWN) + mark(cur.value.lastESP, cur.value.End); + else + mark(cur.value.Start, cur.value.lastESP); + cur = cur.next; + } debug(COLLECT_PRINTF) printf("\tscan heap\n"); while (anychanges) diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/std/mmfile.d patched_phobos/std/mmfile.d --- unpatched_phobos/std/mmfile.d 2008-02-06 03:35:40.000000000 +0100 +++ patched_phobos/std/mmfile.d 2008-02-06 03:02:31.000000000 +0100 @@ -193,31 +193,35 @@ default: assert(0); } - - if (useWfuncs) + if (filename) { - wchar* namez = std.utf.toUTF16z(filename); - hFile = CreateFileW(namez, - dwDesiredAccess2, - dwShareMode, - null, - dwCreationDisposition, - FILE_ATTRIBUTE_NORMAL, - cast(HANDLE)null); + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(filename); + hFile = CreateFileW(namez, + dwDesiredAccess2, + dwShareMode, + null, + dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, + cast(HANDLE)null); + } + else + { + char* namez = std.file.toMBSz(filename); + hFile = CreateFileA(namez, + dwDesiredAccess2, + dwShareMode, + null, + dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, + cast(HANDLE)null); + } + if (hFile == INVALID_HANDLE_VALUE) + goto err1; } else - { - char* namez = std.file.toMBSz(filename); - hFile = CreateFileA(namez, - dwDesiredAccess2, - dwShareMode, - null, - dwCreationDisposition, - FILE_ATTRIBUTE_NORMAL, - cast(HANDLE)null); - } - if (hFile == INVALID_HANDLE_VALUE) - goto err1; + hFile = null; int hi = cast(int)(size>>32); hFileMap = CreateFileMappingA(hFile, null, flProtect, hi, cast(uint)size, null); @@ -360,7 +364,7 @@ errNo(); hFileMap = null; - if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE) + if (hFile && hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE) errNo(); hFile = INVALID_HANDLE_VALUE; } diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/std/stack.d patched_phobos/std/stack.d --- unpatched_phobos/std/stack.d 1970-01-01 01:00:00.000000000 +0100 +++ patched_phobos/std/stack.d 2008-02-06 05:27:35.000000000 +0100 @@ -0,0 +1,75 @@ +module std.stack; +import std.string, std.stdio; + +struct Stack { + void* Start, End; + void* lastESP; + string toString() { + return format("[", Start, " -> ", End, " @", lastESP, "]"); + } + bool contains(void* ptr) { return ptr >= Start && ptr <= End; } +} + +struct LinkedList(T) { + LinkedList* next; + T value; + string toString() { + auto cur = this; + string res; + while (cur) { + res ~= format(value, " -> "); + cur = cur.next; + } + return res ~ "null"; + } +} + +void ll_push(T, U)(ref T list, U what) { + static assert(is(T==LinkedList!(U)*)); + auto nlist = new LinkedList!(U); + nlist.next = list; + nlist.value = what; + list = nlist; +} + +void ll_delete(T, U)(ref T list, U value) { + if (list && list.value == value) { list = list.next; return; } + auto cur = list; + if (cur) while (cur.next) { + if (cur.next.value == value) { cur.next = cur.next.next; return; } + cur = cur.next; + } + throw new Exception(format("Value not found in linked list (", list, ")")); +} + +LinkedList!(Stack*) *stacks; + +Stack* addStack(void* from, void* to) { + auto st = new Stack; + st.Start=from; st.End=to; + ll_push(stacks, st); + return st; +} + +void delStack(Stack* which) { + ll_delete(stacks, which); +} + +void updateESP(void* newESP) { + auto cur = stacks; + while (cur) { + if (newESP >= cur.value.Start && newESP <= cur.value.End) { + cur.value.lastESP = newESP; + return; + } + cur = cur.next; + } + Stack[] meep; + cur = stacks; + while (cur) { + meep ~= *cur.value; + cur = cur.next; + } + writefln("ESP (", newESP, ") not in any known stack (", meep, ")"); + asm { int 3; } +} diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/std/thread.d patched_phobos/std/thread.d --- unpatched_phobos/std/thread.d 2008-02-06 03:35:42.000000000 +0100 +++ patched_phobos/std/thread.d 2008-02-06 05:27:17.000000000 +0100 @@ -39,6 +39,7 @@ */ module std.thread; +import std.stack; //debug=thread; @@ -80,6 +81,12 @@ */ class Thread { + public static void* getESP() + { + void* res; + asm { mov res, ESP; } + return res; + } /** * Constructor used by classes derived from Thread that override main(). * The optional stacksize parameter default value of 0 will cause threads @@ -88,6 +95,7 @@ this(size_t stacksize = 0) { this.stacksize = stacksize; + stack = addStack(null, null); } /** @@ -98,6 +106,7 @@ this.fp = fp; this.arg = arg; this.stacksize = stacksize; + stack = addStack(null, null); } /** @@ -107,6 +116,7 @@ { this.dg = dg; this.stacksize = stacksize; + stack = addStack(null, null); } /** @@ -115,7 +125,7 @@ */ thread_hdl hdl; - void* stackBottom; + Stack* stack; // the stack this thread is currently executing. NOT the main stack. /** * Create a new thread and start it running. The new thread initializes @@ -406,7 +416,10 @@ int result; debug (thread) printf("Starting thread %d\n", t.idx); - t.stackBottom = os_query_stackBottom(); + t.stack.End = os_query_stackBottom(); + auto size = t.stacksize; + if (!size) size = 1024*1024; + t.stack.Start = t.stack.End - size; try { result = t.run(); @@ -440,7 +453,10 @@ t.state = TS.RUNNING; t.id = GetCurrentThreadId(); t.hdl = Thread.getCurrentThreadHandle(); - t.stackBottom = os_query_stackBottom(); + t.stack.End = os_query_stackBottom(); + auto size = t.stacksize; + if (!size) size = 1024*1024; // default + t.stack.Start = t.stack.End - size; assert(!allThreads[0]); allThreads[0] = t; @@ -571,8 +587,7 @@ } pthread_t id; - void* stackBottom; - void* stackTop; + Stack* stack; void start() { @@ -594,7 +609,7 @@ } } nthreads++; - + state = TS.RUNNING; int result; //printf("creating thread x%x\n", this); @@ -813,7 +828,6 @@ } else { int result; - result = pthread_kill(id, SIGUSR2); if (result) error("cannot resume"); @@ -866,7 +880,7 @@ result = pthread_kill(t.id, SIGUSR1); if (result) getThis().error("cannot pause"); - else + else npause++; // count of paused threads } } @@ -960,6 +974,7 @@ if (pthread_cond_init(&waitCond, null)) error("cannot initialize wait condition"); + stack = addStack(null, null); } /************************************************ @@ -976,11 +991,14 @@ // Need to set t.id here, because thread is off and running // before pthread_create() sets it. t.id = pthread_self(); + t.stack.End = getESP(); + size_t stacksize; + pthread_attr_getstacksize(&t.threadAttrs, &stacksize); + t.stack.Start = t.stack.End - stacksize; // accurate enough version(skyos) installSignalHandlers(); - t.stackBottom = getESP(); try { if(t.state == TS.RUNNING) @@ -1018,7 +1036,10 @@ t.state = TS.RUNNING; t.id = pthread_self(); - t.stackBottom = cast(void*) _d_gcc_query_stack_origin(); + t.stack.End = cast(void*) _d_gcc_query_stack_origin(); + size_t stacksize; + pthread_attr_getstacksize(&t.threadAttrs, &stacksize); + t.stack.Start = t.stack.End - stacksize; assert(!allThreads[0]); allThreads[0] = t; @@ -1092,7 +1113,8 @@ assert(result == 0); Thread t = getThis(); - t.stackTop = getESP(); + auto esp = getESP(); + if (t.stack.contains(esp)) t.stack.lastESP = esp; t.flags &= ~1; flagSuspend.signal(); while (1) @@ -1145,8 +1167,7 @@ private static Thread _instance; static uint nthreads = 1; - void* stackBottom; - void* stackTop; + Stack* stack; enum TS { INITIAL,