Commit Diff


commit - 048610b7ea50507c6987d5b0cc0c4810cda87d53
commit + 5093c3fa40717e78b0a63955640a8ac9071b5c07
blob - fb4c674667cb33586e8ca767c7ec208a20223ea5
blob + 313c2be5fa5ee8932e6022879936268ce7cfbc9a
--- src/libthread/386.c
+++ src/libthread/386.c
@@ -1,7 +1,7 @@
+#if defined(__linux__)
 #include "ucontext.c"
+#else
 
-#ifdef OLD
-
 #include "threadimpl.h"
 /*
  * To use this you need some patches to Valgrind that
blob - 290c52a8162df41d2bfd597d42fab968625dcdd8
blob + d2f4be259f5934c4d0624d72b9c6a1e0e56eede2
--- src/libthread/create.c
+++ src/libthread/create.c
@@ -18,6 +18,9 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, u
 
 	t = _threadmalloc(sizeof(Thread), 1);
 	t->proc = p;
+	t->nextproc = p;
+	t->homeproc = p;
+
 	t->grp = grp;
 	t->id = id = newthreadid();
 	if(name)
@@ -42,15 +45,7 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, u
 	 * 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.
@@ -123,7 +118,7 @@ threadcreateidle(void (*f)(void *arg), void *arg, uint
 {
 	int id;
 
-	assert(_threadnprocs == 1);
+	assert(_threadpq.head->next == nil);	/* only 1 */
 
 	id = threadcreate(f, arg, stacksize);
 	_threaddebug(DBGSCHED, "idle is %d", id);
@@ -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--;
+}
blob - 73a2faf7467b66059d35e96c7ac55c28c7526a21
blob + f69fedcab30760353f432aeebcd39dd14cbc2745
--- src/libthread/exec-unix.c
+++ src/libthread/exec-unix.c
@@ -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];
@@ -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);
 }
 
 /*
@@ -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);
 }
 
blob - 8768e60df715c4d78e23a552a8977bcebabf3f1b
blob + a46ea4567248428d791a631ae2a6cf5b77e72451
--- src/libthread/fdwait.c
+++ src/libthread/fdwait.c
@@ -163,7 +163,7 @@ threadfdwaitsetup(void)
 
 	if(!setup){
 		setup = 1;
-		threadcreateidle(pollidle, nil, 16384);
+		proccreate(pollidle, nil, 16384);
 	}
 }
 
blob - 83ee177c379149a93c5ccbd015a32c6f6b7c2289
blob + ec0854304fd33a201f8503daf168d6120ecba7cb
--- src/libthread/main.c
+++ src/libthread/main.c
@@ -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
@@ -25,16 +29,54 @@ 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
 	 * so that they can operate at the thread level.
blob - 20d08e09279c21a97d009ec841bc8063d54fe7de
blob + e51d195f32727b7d174beda4ab7ffb3f25358a07
--- src/libthread/mkfile
+++ src/libthread/mkfile
@@ -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\
@@ -28,7 +30,6 @@ OFILES=\
 	memset.$O\
 	memsetd.$O\
 	note.$O\
-	pthread.$O\
 	read9pmsg.$O\
 	ref.$O\
 	sched.$O\
@@ -69,3 +70,4 @@ VG=`test -d /home/rsc/pub/valgrind-debian && echo -DUS
 
 CFLAGS=$CFLAGS $VG
 
+Linux-clone.$O: execproc.ch exit-getpid.ch proctab.ch procstack.ch
blob - 94bf236a3374ebd8ff61c71fc5119be701276fc5
blob + ed40c08fb5d956428270200a53d4cb5cf8642dbf
--- src/libthread/note.c
+++ src/libthread/note.c
@@ -1,5 +1,6 @@
 #include "threadimpl.h"
 
+
 int	_threadnopasser;
 
 #define	NFN		33
blob - a914f433d12dbb51efa02f75e7a318095137209f
blob + 8d661c166e0ad6786f0615081cb181da7dec4668
--- src/libthread/pthread.c
+++ src/libthread/pthread.c
@@ -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
@@ -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;
@@ -124,6 +144,9 @@ _threadfirstexec(void)
 {
 }
 
+/*
+ * Called from mainlauncher before threadmain.
+ */
 void
 _threadmaininit(void)
 {
@@ -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;
-}
blob - 55898f08198ada2ac6a5de9e127525f4eb31638b
blob + 7e430193545527a15372f10801f57097f69d82e7
--- src/libthread/sched.c
+++ src/libthread/sched.c
@@ -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.
 		 */
@@ -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);
 	}
blob - bcfabee6d8c5739f1d5d2546d308f7b312d8f798
blob + c9682e35d7d1035174554824dc570b5032cf36e6
--- src/libthread/texec.c
+++ src/libthread/texec.c
@@ -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");
blob - 7c9a66bbfece1cb4785eb3e4759949089fa73f7c
blob + 8d7a7a75d5dc30eb01af9111011dd01dad90bff7
--- src/libthread/threadimpl.h
+++ src/libthread/threadimpl.h
@@ -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 */
@@ -117,6 +119,7 @@ struct Proc
 	Thread	*thread;		/* running thread */
 	Thread	*idle;			/* idle thread */
 	int		id;
+	int		procid;
 
 	int		needexec;
 	Execargs	exec;		/* exec argument */
@@ -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;
@@ -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);