ttry to implement the daemonize hack. - 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 5093c3fa40717e78b0a63955640a8ac9071b5c07
 (DIR) parent 048610b7ea50507c6987d5b0cc0c4810cda87d53
 (HTM) Author: rsc <devnull@localhost>
       Date:   Fri, 22 Oct 2004 18:45:08 +0000
       
       ttry to implement the daemonize hack.
       
       Diffstat:
         M src/libthread/386.c                 |       4 ++--
         M src/libthread/create.c              |      48 ++++++++++++++++++++++++-------
         M src/libthread/exec-unix.c           |       8 ++++----
         M src/libthread/fdwait.c              |       2 +-
         M src/libthread/main.c                |      44 ++++++++++++++++++++++++++++++-
         M src/libthread/mkfile                |       6 ++++--
         M src/libthread/note.c                |       1 +
         M src/libthread/pthread.c             |      48 ++++++++++++++++++-------------
         M src/libthread/sched.c               |      35 ++++++++++++++++++++++---------
         M src/libthread/texec.c               |       7 ++++++-
         M src/libthread/threadimpl.h          |      13 +++++++++++++
       
       11 files changed, 165 insertions(+), 51 deletions(-)
       ---
 (DIR) diff --git a/src/libthread/386.c b/src/libthread/386.c
       t@@ -1,6 +1,6 @@
       +#if defined(__linux__)
        #include "ucontext.c"
       -
       -#ifdef OLD
       +#else
        
        #include "threadimpl.h"
        /*
 (DIR) diff --git a/src/libthread/create.c b/src/libthread/create.c
       t@@ -18,6 +18,9 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize,
        
                t = _threadmalloc(sizeof(Thread), 1);
                t->proc = p;
       +        t->nextproc = p;
       +        t->homeproc = p;
       +
                t->grp = grp;
                t->id = id = newthreadid();
                if(name)
       t@@ -42,15 +45,7 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize,
                 * Add thread to proc.
                 */
                lock(&p->lock);
       -        p->nthreads++;
       -        if(p->threads.head == nil)
       -                p->threads.head = t;
       -        else{
       -                t->prevt = p->threads.tail;
       -                t->prevt->nextt = t;
       -        }
       -        p->threads.tail = t;
       -        t->next = (Thread*)~0;
       +        _procaddthread(p, t);
        
                /*
                 * Mark thread as ready to run.
       t@@ -123,7 +118,7 @@ threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize)
        {
                int id;
        
       -        assert(_threadnprocs == 1);
       +        assert(_threadpq.head->next == nil);        /* only 1 */
        
                id = threadcreate(f, arg, stacksize);
                _threaddebug(DBGSCHED, "idle is %d", id);
       t@@ -181,3 +176,36 @@ newprocid(void)
                return i;
        }
        
       +/*
       + * Add thread to proc's list.
       + */
       +void
       +_procaddthread(Proc *p, Thread *t)
       +{
       +        p->nthreads++;
       +        if(p->threads.head == nil)
       +                p->threads.head = t;
       +        else{
       +                t->prevt = p->threads.tail;
       +                t->prevt->nextt = t;
       +        }
       +        p->threads.tail = t;
       +        t->next = (Thread*)~0;
       +}
       +
       +/*
       + * Remove thread from proc's list.
       + */
       +void
       +_procdelthread(Proc *p, Thread *t)
       +{
       +        if(t->prevt)
       +                t->prevt->nextt = t->nextt;
       +        else
       +                p->threads.head = t->nextt;
       +        if(t->nextt)
       +                t->nextt->prevt = t->prevt;
       +        else
       +                p->threads.tail = t->prevt;
       +        p->nthreads--;
       +}
 (DIR) diff --git a/src/libthread/exec-unix.c b/src/libthread/exec-unix.c
       t@@ -4,7 +4,7 @@
        #include "threadimpl.h"
        
        static void efork(int[3], int[2], char*, char**);
       -static int
       +int
        _threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs)
        {
                int pfd[2];
       t@@ -88,14 +88,14 @@ Bad:
        void
        threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
        {
       -        if(_threadexec(pidc, fd, prog, args, 0) >= 0)
       +        if(_callthreadexec(pidc, fd, prog, args, 0) >= 0)
                        threadexits(nil);
        }
        
        int
        threadspawn(int fd[3], char *prog, char *args[])
        {
       -        return _threadexec(nil, fd, prog, args, 0);
       +        return _callthreadexec(nil, fd, prog, args, 0);
        }
        
        /*
       t@@ -128,7 +128,7 @@ threadexecl(Channel *pidc, int fd[3], char *f, ...)
                args[n] = 0;
                va_end(arg);
        
       -        if(_threadexec(pidc, fd, f, args, 1) >= 0)
       +        if(_callthreadexec(pidc, fd, f, args, 1) >= 0)
                        threadexits(nil);
        }
        
 (DIR) diff --git a/src/libthread/fdwait.c b/src/libthread/fdwait.c
       t@@ -163,7 +163,7 @@ threadfdwaitsetup(void)
        
                if(!setup){
                        setup = 1;
       -                threadcreateidle(pollidle, nil, 16384);
       +                proccreate(pollidle, nil, 16384);
                }
        }
        
 (DIR) diff --git a/src/libthread/main.c b/src/libthread/main.c
       t@@ -11,7 +11,11 @@ struct Mainarg
                char **argv;
        };
        
       +int _threadmainpid;
        int mainstacksize;
       +int _callsthreaddaemonize;
       +static int passtomainpid;
       +
        extern void (*_sysfatal)(char*, va_list);
        
        static void
       t@@ -25,15 +29,53 @@ mainlauncher(void *arg)
                threadexits("threadmain");
        }
        
       +static void
       +passer(void *x, char *msg)
       +{
       +        USED(x);
       +        Waitmsg *w;
       +
       +        if(strcmp(msg, "sys: usr2") == 0)
       +                _exit(0);        /* daemonize */
       +        else if(strcmp(msg, "sys: child") == 0){
       +                w = wait();
       +                if(w == nil)
       +                        _exit(1);
       +                _exit(atoi(w->msg));
       +        }else
       +                postnote(PNPROC, passtomainpid, msg);
       +}
       +
        int
        main(int argc, char **argv)
        {
       +        int pid;
                Mainarg a;
                Proc *p;
       +        sigset_t mask;
        
                /*
       -         * XXX Do daemonize hack here.
       +         * Do daemonize hack here.
                 */
       +        if(_callsthreaddaemonize){
       +                passtomainpid = getpid();
       +                switch(pid = fork()){
       +                case -1:
       +                        sysfatal("fork: %r");
       +
       +                case 0:
       +                        /* continue executing */
       +                        _threadmainpid = getppid();
       +                        break;
       +
       +                default:
       +                        /* wait for signal USR2 */
       +                        notify(passer);
       +                        for(;;)
       +                                pause();
       +                        _exit(0);
       +                }
       +        }
        
                /*
                 * Instruct QLock et al. to use our scheduling functions
 (DIR) diff --git a/src/libthread/mkfile b/src/libthread/mkfile
       t@@ -1,13 +1,15 @@
        <$PLAN9/src/mkhdr
        
        LIB=libthread.a
       -
       +THREAD=`sh ./thread.sh`
        OFILES=\
                $OBJTYPE.$O\
       +        $THREAD.$O\
                asm-$SYSNAME-$OBJTYPE.$O\
                channel.$O\
                chanprint.$O\
                create.$O\
       +        daemon.$O\
                debug.$O\
                exec-unix.$O\
                exit.$O\
       t@@ -28,7 +30,6 @@ OFILES=\
                memset.$O\
                memsetd.$O\
                note.$O\
       -        pthread.$O\
                read9pmsg.$O\
                ref.$O\
                sched.$O\
       t@@ -69,3 +70,4 @@ VG=`test -d /home/rsc/pub/valgrind-debian && echo -DUSEVALGRIND`
        
        CFLAGS=$CFLAGS $VG
        
       +Linux-clone.$O: execproc.ch exit-getpid.ch proctab.ch procstack.ch
 (DIR) diff --git a/src/libthread/note.c b/src/libthread/note.c
       t@@ -1,5 +1,6 @@
        #include "threadimpl.h"
        
       +
        int        _threadnopasser;
        
        #define        NFN                33
 (DIR) diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c
       t@@ -45,6 +45,25 @@ _threadgetproc(void)
        }
        
        /*
       + * Called to start a new proc.
       + */
       +void
       +_threadstartproc(Proc *p)
       +{
       +        Proc *np;
       +        pthread_t tid;
       +        sigset_t all;
       +
       +        np = p->newproc;
       +        sigfillset(&all);
       +        pthread_sigmask(SIG_SETMASK, &all, nil);
       +        if(pthread_create(&tid, nil, (void*(*)(void*))_threadscheduler, 
       +                        np) < 0)
       +                sysfatal("pthread_create: %r");
       +        np->pthreadid = tid;
       +}
       +
       +/*
         * Called to associate p with the current pthread.
         */
        void
       t@@ -87,9 +106,10 @@ _threadwaitkids(Proc *p)
        
        /*
         * Separate process to wait for child messages.
       + * Also runs signal handlers.
         */
       -Channel *_threadexecchan;
       -void
       +static Channel *_threadexecchan;
       +static void
        _threadwaitproc(void *v)
        {
                Channel *c;
       t@@ -124,6 +144,9 @@ _threadfirstexec(void)
        {
        }
        
       +/*
       + * Called from mainlauncher before threadmain.
       + */
        void
        _threadmaininit(void)
        {
       t@@ -141,27 +164,12 @@ _threadmaininit(void)
                unlock(&_threadpq.lock);
        }
        
       +/*
       + * Called after forking the exec child.
       + */
        void
        _threadafterexec(void)
        {
                nbsendul(_threadexecchan, 1);
        }
        
       -/*
       - * Called to start a new proc.
       - */
       -void
       -_threadstartproc(Proc *p)
       -{
       -        Proc *np;
       -        pthread_t tid;
       -        sigset_t all;
       -
       -        np = p->newproc;
       -        sigfillset(&all);
       -        pthread_sigmask(SIG_SETMASK, &all, nil);
       -        if(pthread_create(&tid, nil, (void*(*)(void*))_threadscheduler, 
       -                        np) < 0)
       -                sysfatal("pthread_create: %r");
       -        np->pthreadid = tid;
       -}
 (DIR) diff --git a/src/libthread/sched.c b/src/libthread/sched.c
       t@@ -51,28 +51,43 @@ _threadscheduler(void *arg)
        
                        /*
                         * If thread needs to die, kill it.
       +                 * t->proc == p may not be true if we're
       +                 * trying to jump into the exec proc (see exec-unix.c).
                         */
                        if(t->moribund){
                                _threaddebug(DBGSCHED, "moribund %d.%d", p->id, t->id);
       +                        if(t->moribund != 1)
       +                                print("moribund broke %p %d\n", &t->moribund, t->moribund);
                                assert(t->moribund == 1);
                                t->state = Dead;
       -                        if(t->prevt)
       -                                t->prevt->nextt = t->nextt;
       -                        else
       -                                p->threads.head = t->nextt;
       -                        if(t->nextt)
       -                                t->nextt->prevt = t->prevt;
       -                        else
       -                                p->threads.tail = t->prevt;
       +                        _procdelthread(p, t);
                                unlock(&p->lock);
                                _threadfree(t);
       -                        p->nthreads--;
                                t = nil;
                                continue;
                        }
       +
       +                /*
       +                 * If the thread has asked to move to another proc,
       +                 * let it go (only to be used in *very* special situations).
       +                if(t->nextproc != p)
       +                        _procdelthread(p, t);
       +                 */
       +
                        unlock(&p->lock);
        
                        /*
       +                 * If the thread has asked to move to another proc,
       +                 * add it to the new proc.
       +                 */
       +                if(t->nextproc != p){
       +                //        lock(&t->nextproc->lock);
       +                //        _procaddthread(t->nextproc, t);
       +                //        unlock(&t->nextproc->lock);
       +                        t->proc = t->nextproc;
       +                }
       +
       +                /*
                         * If there is a request to run a function on the 
                         * scheduling stack, do so.
                         */
       t@@ -87,7 +102,7 @@ _threadscheduler(void *arg)
                         * Move the thread along.
                         */
                        t->state = t->nextstate;
       -                _threaddebug(DBGSCHED, "moveon %d.%d", p->id, t->id);
       +                _threaddebug(DBGSCHED, "moveon %d.%d", t->proc->id, t->id);
                        if(t->state == Ready)
                                _threadready(t);
                }
 (DIR) diff --git a/src/libthread/texec.c b/src/libthread/texec.c
       t@@ -22,15 +22,20 @@ threadmain(int argc, char **argv)
        {
                Channel *c;
                Waitmsg *w;
       +        int (*mk)(void(*)(void*), void*, uint);
        
       +        mk = threadcreate;
                ARGBEGIN{
                case 'D':
                        _threaddebuglevel = ~0;
                        break;
       +        case 'p':
       +                mk = proccreate;
       +                break;
                }ARGEND
        
                c = threadwaitchan();
       -        proccreate(doexec, argv, 8192);
       +        mk(doexec, argv, 8192);
                w = recvp(c);
                if(w == nil)
                        print("exec/recvp failed: %r\n");
 (DIR) diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
       t@@ -70,11 +70,13 @@ struct Thread
                int                asleep;                /* thread is in _threadsleep */
                Label        context;                /* for context switches */
                int                 grp;                        /* thread group */
       +        Proc                *homeproc;        /* ``home'' proc */
                int                id;                        /* thread id */
                int                moribund;        /* thread needs to die */
                char                *name;                /* name of thread */
                Thread        *next;                /* next on ready queue */
                Thread        *nextt;                /* next on list of threads in this proc */
       +        Proc                *nextproc;        /* next proc in which to run (rarely changes) */
                State                nextstate;                /* next run state */
                Proc                *proc;                /* proc of this thread */
                Thread        *prevt;                /* prev on list of threads in this proc */
       t@@ -117,6 +119,7 @@ struct Proc
                Thread        *thread;                /* running thread */
                Thread        *idle;                        /* idle thread */
                int                id;
       +        int                procid;
        
                int                needexec;
                Execargs        exec;                /* exec argument */
       t@@ -195,7 +198,9 @@ void                threadstatus(void);
        void                _threadstartproc(Proc*);
        void                _threadexitproc(char*);
        void                _threadexitallproc(char*);
       +void                _threadefork(int[3], int[2], char*, char**);
        
       +extern int                        _threadmainpid;
        extern int                        _threadnprocs;
        extern int                        _threaddebuglevel;
        extern char*                _threadexitsallstatus;
       t@@ -214,3 +219,11 @@ extern void _threadmemset(void*, int, int);
        extern void _threaddebugmemset(void*, int, int);
        extern int _threadprocs;
        extern void _threadstacklimit(void*, void*);
       +extern void _procdelthread(Proc*, Thread*);
       +extern void _procaddthread(Proc*, Thread*);
       +
       +extern void _threadafterexec(void);
       +extern void _threadmaininit(void);
       +extern void _threadfirstexec(void);
       +extern int _threadexec(Channel*, int[3], char*, char*[], int);
       +extern int _callthreadexec(Channel*, int[3], char*, char*[], int);