tTweaks to make libthread tell Valgrind about its stack limits, so that Valgrind can detect stack overflow for me. - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit a3785ca2cc1c8693d89ebe44216acf781a634718
 (DIR) parent cdd61ab0aee825e93688ae5d2cfb86f14baad858
 (HTM) Author: rsc <devnull@localhost>
       Date:   Wed, 21 Apr 2004 19:29:04 +0000
       
       Tweaks to make libthread tell Valgrind about its stack limits,
       so that Valgrind can detect stack overflow for me.
       
       Diffstat:
         M src/libthread/386.c                 |      36 +++++++++++++++++++++++++++++++
         M src/libthread/asm-FreeBSD-386.s     |       8 +++++++-
         M src/libthread/channel.c             |       2 +-
         M src/libthread/mkfile                |       3 +++
         M src/libthread/sched.c               |       5 +++--
         M src/libthread/threadimpl.h          |       2 +-
         M src/libthread/tprimes.c             |      12 +++++++++---
       
       7 files changed, 60 insertions(+), 8 deletions(-)
       ---
 (DIR) diff --git a/src/libthread/386.c b/src/libthread/386.c
       t@@ -1,8 +1,23 @@
        #include "threadimpl.h"
       +/*
       + * To use this you need some patches to Valgrind that
       + * let it help out with detecting stack overflow. 
       + */
       +#define USEVALGRIND 0
       +#ifdef USEVALGRIND
       +#include <valgrind/memcheck.h>
       +#endif
        
        static void
        launcher386(void (*f)(void *arg), void *arg)
        {
       +        Proc *p;
       +        Thread *t;
       +
       +        p = _threadgetproc();
       +        t = p->thread;
       +        _threadstacklimit(t->stk);
       +
                (*f)(arg);
                threadexits(nil);
        }
       t@@ -19,3 +34,24 @@ _threadinitstack(Thread *t, void (*f)(void*), void *arg)
                t->sched.sp = (ulong)tos - 8;                /* old PC and new PC */
        }
        
       +void
       +_threadinswitch(int enter)
       +{
       +        USED(enter);
       +#ifdef USEVALGRIND
       +        if(enter)
       +                VALGRIND_SET_STACK_LIMIT(0, 0, 1);
       +        else
       +                VALGRIND_SET_STACK_LIMIT(0, 0, 0);
       +#endif
       +}
       +
       +void
       +_threadstacklimit(void *addr)
       +{
       +        USED(addr);
       +
       +#ifdef USEVALGRIND
       +        VALGRIND_SET_STACK_LIMIT(1, addr, 0);
       +#endif
       +}
 (DIR) diff --git a/src/libthread/asm-FreeBSD-386.s b/src/libthread/asm-FreeBSD-386.s
       t@@ -17,6 +17,9 @@ _setlabel:
        .type        _gotolabel,@function
        
        _gotolabel:
       +        pushl $1
       +        call _threadinswitch
       +        popl %eax
                movl        4(%esp), %edx
                movl        0(%edx), %ecx
                movl        4(%edx), %ebx
       t@@ -24,9 +27,12 @@ _gotolabel:
                movl        12(%edx), %ebp
                movl        16(%edx), %esi
                movl        20(%edx), %edi
       +        movl        %ecx, 0(%esp)
       +        pushl $0
       +        call _threadinswitch
       +        popl %eax
                xorl        %eax, %eax
                incl        %eax
       -        movl        %ecx, 0(%esp)
                ret
        
        
 (DIR) diff --git a/src/libthread/channel.c b/src/libthread/channel.c
       t@@ -277,7 +277,7 @@ static void
        channelsize(Channel *c, int sz)
        {
                if(c->e != sz){
       -                fprint(2, "expected channel with elements of size %d, got size %d",
       +                fprint(2, "expected channel with elements of size %d, got size %d\n",
                                sz, c->e);
                        abort();
                }
 (DIR) diff --git a/src/libthread/mkfile b/src/libthread/mkfile
       t@@ -53,3 +53,6 @@ trend: trend.$O $PLAN9/lib/$LIB
        
        CLEANFILES=$CLEANFILES tprimes texec
        
       +asm-Linux-386.$O: asm-FreeBSD-386.s
       +asm-NetBSD-386.$O: asm-FreeBSD-386.s
       +asm-OpenBSD-386.$O: asm-FreeBSD-386.s
 (DIR) diff --git a/src/libthread/sched.c b/src/libthread/sched.c
       t@@ -166,14 +166,15 @@ Resched:
                p = _threadgetproc();
        //fprint(2, "p %p\n", p);
                if((t = p->thread) != nil){
       -                if((ulong)&p < (ulong)t->stk){        /* stack overflow */
       -                        fprint(2, "stack overflow %lux %lux\n", (ulong)&p, (ulong)t->stk);
       +                if((ulong)&p < (ulong)t->stk+512){        /* stack overflow waiting to happen */
       +                        fprint(2, "stack overflow: stack at %lux, limit at %lux\n", (ulong)&p, (ulong)t->stk);
                                abort();
                        }
                //        _threaddebug(DBGSCHED, "pausing, state=%s set %p goto %p",
                //                psstate(t->state), &t->sched, &p->sched);
                        if(_setlabel(&t->sched)==0)
                                _gotolabel(&p->sched);
       +                _threadstacklimit(t->stk);
                        return;
                }else{
                        t = runthread(p);
 (DIR) diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
       t@@ -219,4 +219,4 @@ extern int _threadgetpid(void);
        extern void _threadmemset(void*, int, int);
        extern void _threaddebugmemset(void*, int, int);
        extern int _threadprocs;
       -
       +extern void _threadstacklimit(void*);
 (DIR) diff --git a/src/libthread/tprimes.c b/src/libthread/tprimes.c
       t@@ -1,6 +1,12 @@
       -#include <lib9.h>
       +#include <u.h>
       +#include <libc.h>
        #include <thread.h>
        
       +enum
       +{
       +        STACK = 8192
       +};
       +
        int quiet;
        int goal;
        int buffer;
       t@@ -19,7 +25,7 @@ primethread(void *arg)
                if(!quiet)
                        print("%d\n", p);
                nc = chancreate(sizeof(ulong), buffer);
       -        (*fn)(primethread, nc, 8192);
       +        (*fn)(primethread, nc, STACK);
                for(;;){
                        i = recvul(c);
                        if(i%p)
       t@@ -56,7 +62,7 @@ threadmain(int argc, char **argv)
                        goal = 100;
        
                c = chancreate(sizeof(ulong), buffer);
       -        (*fn)(primethread, c, 8192);
       +        (*fn)(primethread, c, STACK);
                for(i=2;; i++)
                        sendul(c, i);
        }