diff -Nur --exclude=.svn --exclude=aclocal.m4 --exclude='*x3*' --exclude=DEADJOE --exclude=configure --exclude='Makefile*' --exclude='*~' ../../dgcc/d/phobos/internal/gc/gcx.d ./internal/gc/gcx.d --- ../../dgcc/d/phobos/internal/gc/gcx.d 2008-01-30 11:53:18.000000000 +0100 +++ ./internal/gc/gcx.d 2008-01-30 12:24:25.000000000 +0100 @@ -10,6 +10,8 @@ Modified by David Friedman, July 2006 */ +private import std.gc, std.stack; + // D Garbage Collector implementation /************** Debugging ***************************/ @@ -1602,7 +1604,7 @@ debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n"); Thread.pauseAll(); - + p_cache = null; size_cache = 0; @@ -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 --exclude=aclocal.m4 --exclude='*x3*' --exclude=DEADJOE --exclude=configure --exclude='Makefile*' --exclude='*~' ../../dgcc/d/phobos/std/stack.d ./std/stack.d --- ../../dgcc/d/phobos/std/stack.d 1970-01-01 01:00:00.000000000 +0100 +++ ./std/stack.d 2008-01-30 12:23:36.000000000 +0100 @@ -0,0 +1,56 @@ +module std.stack; + +struct Stack { + void* Start, End; + void* lastESP; +} + +struct LinkedList(T) { + LinkedList* next; + T value; +} + +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("Value not found in linked list!"); +} + +LinkedList!(Stack*) *stacks; + +import std.stdio; +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; + } + writefln("ESP (", newESP, ") not in any known stack!"); + asm { int 3; } +} diff -Nur --exclude=.svn --exclude=aclocal.m4 --exclude='*x3*' --exclude=DEADJOE --exclude=configure --exclude='Makefile*' --exclude='*~' ../../dgcc/d/phobos/std/thread.d ./std/thread.d --- ../../dgcc/d/phobos/std/thread.d 2008-01-30 11:53:18.000000000 +0100 +++ ./std/thread.d 2008-01-29 18:25:23.000000000 +0100 @@ -39,6 +39,7 @@ */ module std.thread; +import std.stack; //debug=thread; @@ -88,6 +89,7 @@ this(size_t stacksize = 0) { this.stacksize = stacksize; + stack = addStack(null, null); } /** @@ -98,6 +100,7 @@ this.fp = fp; this.arg = arg; this.stacksize = stacksize; + stack = addStack(null, null); } /** @@ -107,6 +110,7 @@ { this.dg = dg; this.stacksize = stacksize; + stack = addStack(null, null); } /** @@ -115,7 +119,7 @@ */ thread_hdl hdl; - void* stackBottom; + Stack* stack; /** * Create a new thread and start it running. The new thread initializes @@ -406,7 +410,8 @@ int result; debug (thread) printf("Starting thread %d\n", t.idx); - t.stackBottom = os_query_stackBottom(); + t.stack.End = os_query_stackBottom(); + t.stack.Start = t.stack.End - t.stacksize; try { result = t.run(); @@ -440,7 +445,8 @@ t.state = TS.RUNNING; t.id = GetCurrentThreadId(); t.hdl = Thread.getCurrentThreadHandle(); - t.stackBottom = os_query_stackBottom(); + t.stack.End = os_query_stackBottom(); + t.stack.Start = t.stack.End - t.stacksize; assert(!allThreads[0]); allThreads[0] = t; @@ -571,8 +577,7 @@ } pthread_t id; - void* stackBottom; - void* stackTop; + Stack* stack; void start() { @@ -594,20 +599,23 @@ } } nthreads++; - - state = TS.RUNNING; - int result; - //printf("creating thread x%x\n", this); - //result = pthread_create(&id, null, &threadstart, this); - // Create with thread attributes to allow non-default stack size - Dave Fladebo - result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this); - if (result) - { state = TS.TERMINATED; + } + + state = TS.RUNNING; + int result; + //printf("creating thread x%x\n", this); + //result = pthread_create(&id, null, &threadstart, this); + // Create with thread attributes to allow non-default stack size - Dave Fladebo + result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this); + if (result) + synchronized(threadLock) + { + state = TS.TERMINATED; allThreads[idx] = null; idx = -1; error("failed to start"); // BUG: should report errno - } - } // %% changed end of sync region + } + // %% changed end of sync region //printf("t = x%x, id = %d\n", this, id); } @@ -790,12 +798,11 @@ } else { int result; - + result = pthread_kill(id, SIGUSR1); if (result) error("cannot pause"); - else - flagSuspend.wait(); // wait for acknowledgement + else flagSuspend.wait(); // wait for acknowledgement } } else @@ -813,7 +820,6 @@ } else { int result; - result = pthread_kill(id, SIGUSR2); if (result) error("cannot resume"); @@ -866,7 +872,7 @@ result = pthread_kill(t.id, SIGUSR1); if (result) getThis().error("cannot pause"); - else + else npause++; // count of paused threads } } @@ -960,6 +966,7 @@ if (pthread_cond_init(&waitCond, null)) error("cannot initialize wait condition"); + stack = addStack(null, null); } /************************************************ @@ -976,11 +983,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 +1028,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 +1105,7 @@ assert(result == 0); Thread t = getThis(); - t.stackTop = getESP(); + updateESP(getESP()); t.flags &= ~1; flagSuspend.signal(); while (1) @@ -1145,8 +1160,7 @@ private static Thread _instance; static uint nthreads = 1; - void* stackBottom; - void* stackTop; + Stack* stack; enum TS { INITIAL,