tstarting to work on Linux - 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 955a2ca78d7efc2787864e38a3d902df16fc2541
 (DIR) parent e127e40bb1327662a05f5b70dd1bbca5c69b042c
 (HTM) Author: rsc <devnull@localhost>
       Date:   Mon, 27 Dec 2004 18:21:58 +0000
       
       starting to work on Linux
       
       Diffstat:
         M src/libthread/Linux.c               |      39 +++++++++++++++++++++++++++++--
         M src/libthread/exec.c                |      44 +++++++++++++++++++------------
         A src/libthread/test/mkfile           |       8 ++++++++
         M src/libthread/thread.c              |       2 ++
         M src/libthread/threadimpl.h          |       6 ++++++
       
       5 files changed, 80 insertions(+), 19 deletions(-)
       ---
 (DIR) diff --git a/src/libthread/Linux.c b/src/libthread/Linux.c
       t@@ -87,6 +87,7 @@ _procsleep(_Procrendez *r)
                 * unlock the vouslock so our waker can wake us,
                 * and then suspend.
                 */
       +again:
                r->asleep = 1;
                r->pid = getpid();
        
       t@@ -101,9 +102,13 @@ _procsleep(_Procrendez *r)
                /*
                 * We're awake.  Make USR1 not interrupt system calls.
                 */
       -        ignusr1(1);
       -        assert(r->asleep == 0);
                lock(r->l);
       +        ignusr1(1);
       +        if(r->asleep && r->pid == getpid()){
       +print("resleep %d\n", getpid());
       +                /* Didn't really wake up - signal from something else */
       +                goto again;
       +        }
        }
        
        void
       t@@ -233,6 +238,7 @@ static char *threadexitsmsg;
        void
        sigusr2handler(int s)
        {
       +        print("%d usr2 %d\n", time(0), getpid());
                if(threadexitsmsg)
                        _exits(threadexitsmsg);
        }
       t@@ -260,6 +266,35 @@ threadexitsall(char *msg)
        }
        
        /*
       + * exec - need to arrange for wait proc to run
       + * the execs so it gets the wait messages
       + */
       +int
       +_runthreadspawn(int *fd, char *cmd, char **argv)
       +{
       +        Execjob e;
       +        int pid;
       +
       +        e.fd = fd;
       +        e.cmd = cmd;
       +        e.argv = argv;
       +        e.c = chancreate(sizeof(ulong), 0);        
       +print("%d run\n", time(0));
       +        qlock(&_threadexeclock);
       +        sendp(_threadexecchan, &e);
       +print("%d sent\n", time(0));
       +        while(_threadexecproc == nil)
       +                yield();
       +        kill(_threadexecproc->osprocid, SIGUSR2);
       +print("%d killed\n", time(0));
       +        pid = recvul(e.c);
       +        qunlock(&_threadexeclock);
       +print("%d ran\n", time(0));
       +        return pid;
       +}
       +
       +
       +/*
         * per-process data, indexed by pid
         *
         * could use modify_ldt and a segment register
 (DIR) diff --git a/src/libthread/exec.c b/src/libthread/exec.c
       t@@ -6,26 +6,36 @@
        
        static Lock thewaitlock;
        static Channel *thewaitchan;
       -static Channel *dowaitchan;
       -static Channel *execchan;
       +Channel        *_dowaitchan;
       +Channel        *_threadexecchan;
       +Proc        *_threadexecproc;
       +QLock        _threadexeclock;
       +
       +static void
       +execthread(void *v)
       +{
       +        Execjob *e;
       +
       +        USED(v);
       +        while((e = recvp(_threadexecchan)) != nil){
       +print("%d doexec pid %d\n", time(0), getpid());
       +                sendul(e->c, _threadspawn(e->fd, e->cmd, e->argv));
       +        }
       +}
        
        static void
        waitproc(void *v)
        {
                Channel *c;
                Waitmsg *w;
       -        Execjob *e;
        
                _threadsetsysproc();
       +        _threadexecproc = proc();
       +        threadcreate(execthread, nil, 65536);
                for(;;){
       -                for(;;){
       -                        while((e = nbrecvp(execchan)) != nil)
       -                                sendul(e->c, _threadspawn(e->fd, e->cmd, e->argv));
       -                        if((w = wait()) != nil)
       -                                break;
       +                while((w = wait()) == nil)
                                if(errno == ECHILD)
       -                                recvul(dowaitchan);
       -                }
       +                                recvul(_dowaitchan);
                        if((c = thewaitchan) != nil)
                                sendp(c, w);
                        else
       t@@ -94,20 +104,20 @@ _threadspawn(int fd[3], char *cmd, char *argv[])
                        close(fd[1]);
                if(fd[2] != fd[1] && fd[2] != fd[0])
                        close(fd[2]);
       -        channbsendul(dowaitchan, 1);
       +        channbsendul(_dowaitchan, 1);
                return pid;
        }
        
        int
        threadspawn(int fd[3], char *cmd, char *argv[])
        {
       -        if(dowaitchan == nil){
       +        if(_dowaitchan == nil){
                        lock(&thewaitlock);
       -                if(dowaitchan == nil){
       -                        dowaitchan = chancreate(sizeof(ulong), 1);
       -                        chansetname(dowaitchan, "dowaitchan");
       -                        execchan = chancreate(sizeof(void*), 0);
       -                        chansetname(execchan, "execchan");
       +                if(_dowaitchan == nil){
       +                        _dowaitchan = chancreate(sizeof(ulong), 1);
       +                        chansetname(_dowaitchan, "dowaitchan");
       +                        _threadexecchan = chancreate(sizeof(void*), 1);
       +                        chansetname(_threadexecchan, "execchan");
                                proccreate(waitproc, nil, STACK);
                        }
                        unlock(&thewaitlock);
 (DIR) diff --git a/src/libthread/test/mkfile b/src/libthread/test/mkfile
       t@@ -0,0 +1,8 @@
       +<$PLAN9/src/mkhdr
       +
       +SHORTLIB=thread 9
       +OFILES=
       +
       +TARG=tprimes tspawn tspawnloop
       +
       +<$PLAN9/src/mkmany
 (DIR) diff --git a/src/libthread/thread.c b/src/libthread/thread.c
       t@@ -184,7 +184,9 @@ scheduler(Proc *p)
                                if(p->nthread == 0)
                                        goto Out;
                                p->runrend.l = &p->lock;
       +print("sleep for jobs %d\n", getpid());
                                _procsleep(&p->runrend);
       +print("wake from jobs %d\n", getpid());
                        }
                        delthread(&p->runqueue, t);
                        unlock(&p->lock);
 (DIR) diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
       t@@ -5,6 +5,8 @@ typedef struct Execjob Execjob;
        typedef struct Proc Proc;
        typedef struct _Procrendez _Procrendez;
        
       +
       +
        typedef struct Jmp Jmp;
        struct Jmp
        {
       t@@ -88,6 +90,10 @@ struct Proc
        
        extern Proc *_threadprocs;
        extern Lock _threadprocslock;
       +extern Proc *_threadexecproc;
       +extern Channel *_threadexecchan;
       +extern QLock _threadexeclock;
       +extern Channel *_dowaitchan;
        
        extern void _procstart(Proc*, void (*fn)(Proc*));
        extern _Thread *_threadcreate(Proc*, void(*fn)(void*), void*, uint);