make -> mk
remove clumsy stack hack. fix exec. fix nthreads maintenance. fix threadexitsall not to kill self. add sun support.
This commit is contained in:
parent
b7e6f4150f
commit
cd7ddc9b5f
10 changed files with 105 additions and 116 deletions
|
|
@ -1,52 +0,0 @@
|
||||||
PLAN9=../..
|
|
||||||
include $(PLAN9)/src/Makehdr
|
|
||||||
|
|
||||||
LIB=libthread.a
|
|
||||||
|
|
||||||
OFILES=\
|
|
||||||
$(OBJTYPE).$O\
|
|
||||||
asm-$(SYSNAME)-$(OBJTYPE).$O\
|
|
||||||
channel.$O\
|
|
||||||
chanprint.$O\
|
|
||||||
create.$O\
|
|
||||||
debug.$O\
|
|
||||||
exec-unix.$O\
|
|
||||||
exit.$O\
|
|
||||||
getpid.$O\
|
|
||||||
id.$O\
|
|
||||||
iocall.$O\
|
|
||||||
ioclose.$O\
|
|
||||||
ioopen.$O\
|
|
||||||
ioproc.$O\
|
|
||||||
ioread.$O\
|
|
||||||
ioreadn.$O\
|
|
||||||
iowrite.$O\
|
|
||||||
kill.$O\
|
|
||||||
lib.$O\
|
|
||||||
main.$O\
|
|
||||||
memset.$O\
|
|
||||||
memsetd.$O\
|
|
||||||
note.$O\
|
|
||||||
proctab.$O\
|
|
||||||
ref.$O\
|
|
||||||
rendez.$O\
|
|
||||||
sched.$O\
|
|
||||||
|
|
||||||
HFILES=\
|
|
||||||
$(PLAN9)/include/thread.h\
|
|
||||||
label.h\
|
|
||||||
threadimpl.h\
|
|
||||||
|
|
||||||
include $(PLAN9)/src/Makesyslib
|
|
||||||
|
|
||||||
tprimes: tprimes.$O $(PLAN9)/lib/$(LIB)
|
|
||||||
$(LD) -o tprimes tprimes.$O $(LDFLAGS) -lthread -l9 -lfmt -lutf
|
|
||||||
|
|
||||||
texec: texec.$O $(PLAN9)/lib/$(LIB)
|
|
||||||
$(LD) -o texec texec.$O $(LDFLAGS) -lthread -l9 -lfmt -lutf
|
|
||||||
|
|
||||||
trend: trend.$O $(PLAN9)/lib/$(LIB)
|
|
||||||
$(LD) -o trend trend.$O $(LDFLAGS) -lthread -l9 -lfmt -lutf
|
|
||||||
|
|
||||||
CLEANFILES+=tprimes texec
|
|
||||||
|
|
||||||
|
|
@ -7,54 +7,10 @@ static int nextID(void);
|
||||||
/*
|
/*
|
||||||
* Create and initialize a new Thread structure attached to a given proc.
|
* Create and initialize a new Thread structure attached to a given proc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct Stack Stack;
|
|
||||||
struct Stack {
|
|
||||||
ulong magic;
|
|
||||||
Thread *thr;
|
|
||||||
Stack *next;
|
|
||||||
uchar buf[STKSIZE-12];
|
|
||||||
};
|
|
||||||
|
|
||||||
static Stack *stkfree;
|
|
||||||
static Lock stklock;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_stackfree(void *v)
|
_stackfree(void *v)
|
||||||
{
|
{
|
||||||
Stack *s;
|
free(v);
|
||||||
|
|
||||||
s = v;
|
|
||||||
lock(&stklock);
|
|
||||||
s->thr = nil;
|
|
||||||
s->magic = 0;
|
|
||||||
s->next = stkfree;
|
|
||||||
stkfree = s;
|
|
||||||
unlock(&stklock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Stack*
|
|
||||||
stackalloc(void)
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
Stack *s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
lock(&stklock);
|
|
||||||
while(stkfree == nil){
|
|
||||||
unlock(&stklock);
|
|
||||||
assert(STKSIZE == sizeof(Stack));
|
|
||||||
buf = malloc(STKSIZE+128*STKSIZE);
|
|
||||||
s = (Stack*)(((ulong)buf+STKSIZE)&~(STKSIZE-1));
|
|
||||||
for(i=0; i<128; i++)
|
|
||||||
_stackfree(&s[i]);
|
|
||||||
lock(&stklock);
|
|
||||||
}
|
|
||||||
s = stkfree;
|
|
||||||
stkfree = stkfree->next;
|
|
||||||
unlock(&stklock);
|
|
||||||
s->magic = STKMAGIC;
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -62,16 +18,15 @@ newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, char *name,
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
Thread *t;
|
Thread *t;
|
||||||
Stack *s;
|
char *s;
|
||||||
|
|
||||||
if(stacksize < 32)
|
if(stacksize < 32)
|
||||||
sysfatal("bad stacksize %d", stacksize);
|
sysfatal("bad stacksize %d", stacksize);
|
||||||
t = _threadmalloc(sizeof(Thread), 1);
|
t = _threadmalloc(sizeof(Thread), 1);
|
||||||
s = stackalloc();
|
s = _threadmalloc(stacksize, 0);
|
||||||
s->thr = t;
|
|
||||||
t->stk = (char*)s;
|
t->stk = (char*)s;
|
||||||
t->stksize = STKSIZE;
|
t->stksize = stacksize;
|
||||||
_threaddebugmemset(s->buf, 0xFE, sizeof s->buf);
|
_threaddebugmemset(s, 0xFE, stacksize);
|
||||||
_threadinitstack(t, f, arg);
|
_threadinitstack(t, f, arg);
|
||||||
t->proc = p;
|
t->proc = p;
|
||||||
t->grp = grp;
|
t->grp = grp;
|
||||||
|
|
@ -138,7 +93,7 @@ _freeproc(Proc *p)
|
||||||
if(t->cmdname)
|
if(t->cmdname)
|
||||||
free(t->cmdname);
|
free(t->cmdname);
|
||||||
assert(t->stk != nil);
|
assert(t->stk != nil);
|
||||||
_stackfree((Stack*)t->stk);
|
_stackfree(t->stk);
|
||||||
nextt = t->nextt;
|
nextt = t->nextt;
|
||||||
free(t);
|
free(t);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ procexec(Channel *pidc, char *prog, char *args[])
|
||||||
Proc *p;
|
Proc *p;
|
||||||
Thread *t;
|
Thread *t;
|
||||||
|
|
||||||
|
print("procexec\n");
|
||||||
_threaddebug(DBGEXEC, "procexec %s", prog);
|
_threaddebug(DBGEXEC, "procexec %s", prog);
|
||||||
/* must be only thread in proc */
|
/* must be only thread in proc */
|
||||||
p = _threadgetproc();
|
p = _threadgetproc();
|
||||||
t = p->thread;
|
t = p->thread;
|
||||||
if(p->threads.head != t || p->threads.head->nextt != nil){
|
if(p->threads.head != t || p->threads.head->nextt != nil){
|
||||||
|
print("not only thread\n");
|
||||||
werrstr("not only thread in proc");
|
werrstr("not only thread in proc");
|
||||||
Bad:
|
Bad:
|
||||||
if(pidc)
|
if(pidc)
|
||||||
|
|
@ -34,26 +36,35 @@ procexec(Channel *pidc, char *prog, char *args[])
|
||||||
* pipe to us.
|
* pipe to us.
|
||||||
*/
|
*/
|
||||||
if(pipe(p->exec.fd) < 0)
|
if(pipe(p->exec.fd) < 0)
|
||||||
|
{
|
||||||
|
print("pipe\n");
|
||||||
goto Bad;
|
goto Bad;
|
||||||
|
}
|
||||||
if(fcntl(p->exec.fd[1], F_SETFD, 1) < 0)
|
if(fcntl(p->exec.fd[1], F_SETFD, 1) < 0)
|
||||||
|
{
|
||||||
|
print("fcntl\n");
|
||||||
goto Bad;
|
goto Bad;
|
||||||
|
}
|
||||||
|
|
||||||
/* exec in parallel via the scheduler */
|
/* exec in parallel via the scheduler */
|
||||||
assert(p->needexec==0);
|
assert(p->needexec==0);
|
||||||
p->exec.prog = prog;
|
p->exec.prog = prog;
|
||||||
p->exec.args = args;
|
p->exec.args = args;
|
||||||
p->needexec = 1;
|
p->needexec = 1;
|
||||||
|
print("sched\n");
|
||||||
_sched();
|
_sched();
|
||||||
|
|
||||||
close(p->exec.fd[1]);
|
close(p->exec.fd[1]);
|
||||||
if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){ /* exec failed */
|
if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){ /* exec failed */
|
||||||
p->exitstr[n] = '\0';
|
p->exitstr[n] = '\0';
|
||||||
|
print("read got %s\n", p->exitstr);
|
||||||
errstr(p->exitstr, ERRMAX);
|
errstr(p->exitstr, ERRMAX);
|
||||||
close(p->exec.fd[0]);
|
close(p->exec.fd[0]);
|
||||||
goto Bad;
|
goto Bad;
|
||||||
}
|
}
|
||||||
close(p->exec.fd[0]);
|
close(p->exec.fd[0]);
|
||||||
|
|
||||||
|
print("exec %d\n", pidc);
|
||||||
if(pidc)
|
if(pidc)
|
||||||
sendul(pidc, t->ret);
|
sendul(pidc, t->ret);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "threadimpl.h"
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
char *_threadexitsallstatus;
|
char *_threadexitsallstatus;
|
||||||
Channel *_threadwaitchan;
|
Channel *_threadwaitchan;
|
||||||
|
|
@ -13,6 +13,7 @@ threadexits(char *exitstr)
|
||||||
p = _threadgetproc();
|
p = _threadgetproc();
|
||||||
t = p->thread;
|
t = p->thread;
|
||||||
t->moribund = 1;
|
t->moribund = 1;
|
||||||
|
_threaddebug(DBGSCHED, "threadexits %s", exitstr);
|
||||||
if(exitstr==nil)
|
if(exitstr==nil)
|
||||||
exitstr="";
|
exitstr="";
|
||||||
utfecpy(p->exitstr, p->exitstr+ERRMAX, exitstr);
|
utfecpy(p->exitstr, p->exitstr+ERRMAX, exitstr);
|
||||||
|
|
@ -26,6 +27,7 @@ threadexitsall(char *exitstr)
|
||||||
int *pid;
|
int *pid;
|
||||||
int i, npid, mypid;
|
int i, npid, mypid;
|
||||||
|
|
||||||
|
_threaddebug(DBGSCHED, "threadexitsall %s", exitstr);
|
||||||
if(exitstr == nil)
|
if(exitstr == nil)
|
||||||
exitstr = "";
|
exitstr = "";
|
||||||
_threadexitsallstatus = exitstr;
|
_threadexitsallstatus = exitstr;
|
||||||
|
|
@ -34,7 +36,7 @@ threadexitsall(char *exitstr)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* signal others.
|
* signal others.
|
||||||
* copying all the pids first avoids other threads
|
* copying all the pids first avoids other thread's
|
||||||
* teardown procedures getting in the way.
|
* teardown procedures getting in the way.
|
||||||
*/
|
*/
|
||||||
lock(&_threadpq.lock);
|
lock(&_threadpq.lock);
|
||||||
|
|
@ -46,9 +48,13 @@ threadexitsall(char *exitstr)
|
||||||
for(p = _threadpq.head; p; p=p->next)
|
for(p = _threadpq.head; p; p=p->next)
|
||||||
pid[npid++] = p->pid;
|
pid[npid++] = p->pid;
|
||||||
unlock(&_threadpq.lock);
|
unlock(&_threadpq.lock);
|
||||||
for(i=0; i<npid; i++)
|
for(i=0; i<npid; i++){
|
||||||
if(pid[i] != mypid)
|
_threaddebug(DBGSCHED, "threadexitsall kill %d", pid[i]);
|
||||||
|
if(pid[i]==0 || pid[i]==-1)
|
||||||
|
fprint(2, "bad pid in threadexitsall: %d\n", pid[i]);
|
||||||
|
else if(pid[i] != mypid)
|
||||||
kill(pid[i], SIGTERM);
|
kill(pid[i], SIGTERM);
|
||||||
|
}
|
||||||
|
|
||||||
/* leave */
|
/* leave */
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "threadimpl.h"
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
static void tinterrupt(Proc*, Thread*);
|
static void tinterrupt(Proc*, Thread*);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,14 @@ struct Label
|
||||||
// uvlong fpr[18]; /* callee saved: f14-f31 */
|
// uvlong fpr[18]; /* callee saved: f14-f31 */
|
||||||
// ulong vr[4*12]; /* callee saved: v20-v31, 256-bits each */
|
// ulong vr[4*12]; /* callee saved: v20-v31, 256-bits each */
|
||||||
};
|
};
|
||||||
|
#elif defined(__sun__)
|
||||||
|
struct Label
|
||||||
|
{
|
||||||
|
ulong input[8]; /* %i registers */
|
||||||
|
ulong local[8]; /* %l registers */
|
||||||
|
ulong sp; /* %o6 */
|
||||||
|
ulong link; /* %o7 */
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
#error "Unknown or unsupported architecture"
|
#error "Unknown or unsupported architecture"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "threadimpl.h"
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
typedef struct Mainarg Mainarg;
|
typedef struct Mainarg Mainarg;
|
||||||
struct Mainarg
|
struct Mainarg
|
||||||
|
|
@ -74,7 +74,13 @@ _threadsignalpasser(void)
|
||||||
int
|
int
|
||||||
_schedfork(Proc *p)
|
_schedfork(Proc *p)
|
||||||
{
|
{
|
||||||
return ffork(RFMEM|RFNOWAIT, _schedinit, p);
|
int pid;
|
||||||
|
lock(&p->lock);
|
||||||
|
pid = ffork(RFMEM|RFNOWAIT, _schedinit, p);
|
||||||
|
p->pid = pid;
|
||||||
|
unlock(&p->lock);
|
||||||
|
return pid;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
52
src/libthread/mkfile
Normal file
52
src/libthread/mkfile
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
PLAN9=../..
|
||||||
|
<$PLAN9/src/mkhdr
|
||||||
|
|
||||||
|
LIB=libthread.a
|
||||||
|
|
||||||
|
OFILES=\
|
||||||
|
$OBJTYPE.$O\
|
||||||
|
asm-$SYSNAME-$OBJTYPE.$O\
|
||||||
|
channel.$O\
|
||||||
|
chanprint.$O\
|
||||||
|
create.$O\
|
||||||
|
debug.$O\
|
||||||
|
exec-unix.$O\
|
||||||
|
exit.$O\
|
||||||
|
getpid.$O\
|
||||||
|
id.$O\
|
||||||
|
iocall.$O\
|
||||||
|
ioclose.$O\
|
||||||
|
ioopen.$O\
|
||||||
|
ioproc.$O\
|
||||||
|
ioread.$O\
|
||||||
|
ioreadn.$O\
|
||||||
|
iowrite.$O\
|
||||||
|
kill.$O\
|
||||||
|
lib.$O\
|
||||||
|
main.$O\
|
||||||
|
memset.$O\
|
||||||
|
memsetd.$O\
|
||||||
|
note.$O\
|
||||||
|
proctab.$O\
|
||||||
|
ref.$O\
|
||||||
|
rendez.$O\
|
||||||
|
sched.$O\
|
||||||
|
|
||||||
|
HFILES=\
|
||||||
|
$PLAN9/include/thread.h\
|
||||||
|
label.h\
|
||||||
|
threadimpl.h\
|
||||||
|
|
||||||
|
<$PLAN9/src/mksyslib
|
||||||
|
|
||||||
|
tprimes: tprimes.$O $PLAN9/lib/$LIB
|
||||||
|
$LD -o tprimes tprimes.$O $LDFLAGS -lthread -l9 -lfmt -lutf
|
||||||
|
|
||||||
|
texec: texec.$O $PLAN9/lib/$LIB
|
||||||
|
$LD -o texec texec.$O $LDFLAGS -lthread -l9 -lfmt -lutf
|
||||||
|
|
||||||
|
trend: trend.$O $PLAN9/lib/$LIB
|
||||||
|
$LD -o trend trend.$O $LDFLAGS -lthread -l9 -lfmt -lutf
|
||||||
|
|
||||||
|
CLEANFILES=$CLEANFILES tprimes texec
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "threadimpl.h"
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
//static Thread *runthread(Proc*);
|
//static Thread *runthread(Proc*);
|
||||||
|
|
||||||
|
|
@ -27,11 +27,11 @@ _schedinit(void *arg)
|
||||||
ignusr1();
|
ignusr1();
|
||||||
signal(SIGTERM, _threaddie);
|
signal(SIGTERM, _threaddie);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
p = arg;
|
p = arg;
|
||||||
|
lock(&p->lock);
|
||||||
p->pid = _threadgetpid();
|
p->pid = _threadgetpid();
|
||||||
_threadsetproc(p);
|
_threadsetproc(p);
|
||||||
|
unlock(&p->lock);
|
||||||
while(_setlabel(&p->sched))
|
while(_setlabel(&p->sched))
|
||||||
;
|
;
|
||||||
_threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus);
|
_threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus);
|
||||||
|
|
@ -59,6 +59,7 @@ _schedinit(void *arg)
|
||||||
_stackfree(t->stk);
|
_stackfree(t->stk);
|
||||||
free(t->cmdname);
|
free(t->cmdname);
|
||||||
free(t); /* XXX how do we know there are no references? */
|
free(t); /* XXX how do we know there are no references? */
|
||||||
|
p->nthreads--;
|
||||||
t = nil;
|
t = nil;
|
||||||
_sched();
|
_sched();
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +95,7 @@ runthread(Proc *p)
|
||||||
lock(&p->readylock);
|
lock(&p->readylock);
|
||||||
if(q->head == nil){
|
if(q->head == nil){
|
||||||
q->asleep = 1;
|
q->asleep = 1;
|
||||||
_threaddebug(DBGSCHED, "sleeping for more work");
|
_threaddebug(DBGSCHED, "sleeping for more work (%d threads)", p->nthreads);
|
||||||
unlock(&p->readylock);
|
unlock(&p->readylock);
|
||||||
while(rendezvous((ulong)q, 0) == ~0){
|
while(rendezvous((ulong)q, 0) == ~0){
|
||||||
if(_threadexitsallstatus)
|
if(_threadexitsallstatus)
|
||||||
|
|
@ -173,6 +174,7 @@ _threadready(Thread *t)
|
||||||
q->tail->next = t;
|
q->tail->next = t;
|
||||||
q->tail = t;
|
q->tail = t;
|
||||||
if(q->asleep){
|
if(q->asleep){
|
||||||
|
assert(q->asleep == 1);
|
||||||
q->asleep = 0;
|
q->asleep = 0;
|
||||||
/* lock passes to runthread */
|
/* lock passes to runthread */
|
||||||
_threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
|
_threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ doexec(void *v)
|
||||||
{
|
{
|
||||||
char **argv = v;
|
char **argv = v;
|
||||||
|
|
||||||
|
print("doexec\n");
|
||||||
procexec(nil, argv[0], argv);
|
procexec(nil, argv[0], argv);
|
||||||
sendp(threadwaitchan(), nil);
|
sendp(threadwaitchan(), nil);
|
||||||
}
|
}
|
||||||
|
|
@ -27,8 +28,8 @@ threadmain(int argc, char **argv)
|
||||||
proccreate(doexec, argv, 8192);
|
proccreate(doexec, argv, 8192);
|
||||||
w = recvp(c);
|
w = recvp(c);
|
||||||
if(w == nil)
|
if(w == nil)
|
||||||
print("exec failed\n");
|
print("exec failed: %r\n");
|
||||||
else
|
else
|
||||||
print("%d %lu %lu %lu %s\n", w->pid, w->time[0], w->time[1], w->time[2], w->msg);
|
print("%d %lud %lud %lud %s\n", w->pid, w->time[0], w->time[1], w->time[2], w->msg);
|
||||||
threadexits(nil);
|
threadexits(nil);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue