diff -Nur --exclude='*svn*' ../dgcc/d/phobos/internal/gc/gcx.d libphobos/internal/gc/gcx.d --- ../dgcc/d/phobos/internal/gc/gcx.d 2008-01-30 11:53:18.000000000 +0100 +++ libphobos/internal/gc/gcx.d 2008-01-30 21:32:28.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()) updateESP(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='*svn*' ../dgcc/d/phobos/std/stack.d libphobos/std/stack.d --- ../dgcc/d/phobos/std/stack.d 1970-01-01 01:00:00.000000000 +0100 +++ libphobos/std/stack.d 2008-01-30 20:57:42.000000000 +0100 @@ -0,0 +1,74 @@ +module std.stack; +import std.string, std.stdio; + +struct Stack { + void* Start, End; + void* lastESP; + string toString() { + return format("[", Start, " -> ", End, " @", lastESP, "]"); + } +} + +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='*svn*' ../dgcc/d/phobos/std/thread.d libphobos/std/thread.d --- ../dgcc/d/phobos/std/thread.d 2008-01-30 11:53:18.000000000 +0100 +++ libphobos/std/thread.d 2008-01-30 21:36:37.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; /** * 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,7 @@ assert(result == 0); Thread t = getThis(); - t.stackTop = getESP(); + updateESP(getESP()); t.flags &= ~1; flagSuspend.signal(); while (1) @@ -1145,8 +1166,7 @@ private static Thread _instance; static uint nthreads = 1; - void* stackBottom; - void* stackTop; + Stack* stack; enum TS { INITIAL,