ttry to implement the daemonize hack. - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit 5093c3fa40717e78b0a63955640a8ac9071b5c07
parent 048610b7ea50507c6987d5b0cc0c4810cda87d53
Author: rsc 
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(-)
---
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"
 /*
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--;
+}
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);
 }
 
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);
         }
 }
 
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
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
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
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;
-}
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);
         }
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");
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);