Add support for user-level 9P servers/clients and various bug fixes to go with them.
This commit is contained in:
parent
ac244f8d28
commit
32f69c36e0
60 changed files with 965 additions and 485 deletions
|
|
@ -41,9 +41,9 @@ _xdec:
|
|||
movl 4(%esp), %eax
|
||||
lock decl 0(%eax)
|
||||
jz iszero
|
||||
movl %eax, 1
|
||||
movl $1, %eax
|
||||
ret
|
||||
iszero:
|
||||
movl %eax, 0
|
||||
movl $0, %eax
|
||||
ret
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
#include "threadimpl.h"
|
||||
|
||||
Pqueue _threadpq;
|
||||
|
||||
int _threadmultiproc;
|
||||
int _threadprocs;
|
||||
|
||||
static int nextID(void);
|
||||
|
||||
|
|
@ -90,7 +89,6 @@ proccreate(void (*f)(void*), void *arg, uint stacksize)
|
|||
werrstr("cannot create procs once there is an idle thread");
|
||||
return -1;
|
||||
}
|
||||
_threadmultiproc = 1;
|
||||
return procrfork(f, arg, stacksize, 0);
|
||||
}
|
||||
|
||||
|
|
@ -125,11 +123,12 @@ threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize)
|
|||
{
|
||||
int id;
|
||||
|
||||
if(_threadmultiproc){
|
||||
if(_threadprocs!=1){
|
||||
werrstr("cannot have idle thread in multi-proc program");
|
||||
return -1;
|
||||
}
|
||||
id = newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp());
|
||||
_threaddebug(DBGSCHED, "idle is %d", id);
|
||||
_threadidle();
|
||||
return id;
|
||||
}
|
||||
|
|
@ -154,6 +153,7 @@ _newproc(void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp, i
|
|||
else
|
||||
*_threadpq.tail = p;
|
||||
_threadpq.tail = &p->next;
|
||||
_threadprocs++;
|
||||
unlock(&_threadpq.lock);
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "threadimpl.h"
|
||||
|
||||
void
|
||||
procexec(Channel *pidc, char *prog, char *args[])
|
||||
procexec(Channel *pidc, int fd[3], char *prog, char *args[])
|
||||
{
|
||||
int n;
|
||||
Proc *p;
|
||||
|
|
@ -45,6 +45,7 @@ procexec(Channel *pidc, char *prog, char *args[])
|
|||
assert(p->needexec==0);
|
||||
p->exec.prog = prog;
|
||||
p->exec.args = args;
|
||||
p->exec.stdfd = fd;
|
||||
p->needexec = 1;
|
||||
_sched();
|
||||
|
||||
|
|
@ -56,7 +57,11 @@ procexec(Channel *pidc, char *prog, char *args[])
|
|||
goto Bad;
|
||||
}
|
||||
close(p->exec.fd[0]);
|
||||
|
||||
close(fd[0]);
|
||||
if(fd[1] != fd[0])
|
||||
close(fd[1]);
|
||||
if(fd[2] != fd[1] && fd[2] != fd[0])
|
||||
close(fd[2]);
|
||||
if(pidc)
|
||||
sendul(pidc, t->ret);
|
||||
|
||||
|
|
@ -66,9 +71,9 @@ procexec(Channel *pidc, char *prog, char *args[])
|
|||
}
|
||||
|
||||
void
|
||||
procexecl(Channel *pidc, char *f, ...)
|
||||
procexecl(Channel *pidc, int fd[3], char *f, ...)
|
||||
{
|
||||
procexec(pidc, f, &f+1);
|
||||
procexec(pidc, fd, f, &f+1);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -107,10 +112,17 @@ efork(void *ve)
|
|||
{
|
||||
char buf[ERRMAX];
|
||||
Execargs *e;
|
||||
int i;
|
||||
|
||||
e = ve;
|
||||
_threaddebug(DBGEXEC, "_schedexec %s -- calling execv", e->prog);
|
||||
execv(e->prog, e->args);
|
||||
dup(e->stdfd[0], 0);
|
||||
dup(e->stdfd[1], 1);
|
||||
dup(e->stdfd[2], 2);
|
||||
for(i=3; i<40; i++)
|
||||
if(i != e->fd[1])
|
||||
close(i);
|
||||
execvp(e->prog, e->args);
|
||||
_threaddebug(DBGEXEC, "_schedexec failed: %r");
|
||||
rerrstr(buf, sizeof buf);
|
||||
if(buf[0]=='\0')
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#define PIPEMNT "/mnt/temp"
|
||||
|
||||
void
|
||||
procexec(Channel *pidc, char *prog, char *args[])
|
||||
procexec(Channel *pidc, int fd[3], char *prog, char *args[])
|
||||
{
|
||||
int n;
|
||||
Proc *p;
|
||||
|
|
@ -50,6 +50,7 @@ procexec(Channel *pidc, char *prog, char *args[])
|
|||
assert(p->needexec==0);
|
||||
p->exec.prog = prog;
|
||||
p->exec.args = args;
|
||||
p->exec.stdfd = fd;
|
||||
p->needexec = 1;
|
||||
_sched();
|
||||
|
||||
|
|
@ -61,7 +62,11 @@ procexec(Channel *pidc, char *prog, char *args[])
|
|||
goto Bad;
|
||||
}
|
||||
close(p->exec.fd[0]);
|
||||
|
||||
close(fd[0]);
|
||||
if(fd[1] != fd[0])
|
||||
close(fd[1]);
|
||||
if(fd[2] != fd[1] && fd[2] != fd[0])
|
||||
close(fd[2]);
|
||||
if(pidc)
|
||||
sendul(pidc, t->ret);
|
||||
|
||||
|
|
@ -70,8 +75,8 @@ procexec(Channel *pidc, char *prog, char *args[])
|
|||
}
|
||||
|
||||
void
|
||||
procexecl(Channel *pidc, char *f, ...)
|
||||
procexecl(Channel *pidc, int fd[3], char *f, ...)
|
||||
{
|
||||
procexec(pidc, f, &f+1);
|
||||
procexec(pidc, fd, f, &f+1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ main(int argc, char **argv)
|
|||
_systhreadinit();
|
||||
_qlockinit(_threadrendezvous);
|
||||
_sysfatal = _threadsysfatal;
|
||||
// notify(_threadnote);
|
||||
notify(_threadnote);
|
||||
if(mainstacksize == 0)
|
||||
mainstacksize = 32*1024;
|
||||
|
||||
|
|
@ -98,6 +98,7 @@ _schedexit(Proc *p)
|
|||
break;
|
||||
}
|
||||
}
|
||||
_threadprocs--;
|
||||
unlock(&_threadpq.lock);
|
||||
|
||||
strncpy(ex, p->exitstr, sizeof ex);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
int _threadnopasser;
|
||||
|
||||
#ifdef NOTDEF
|
||||
#define NFN 33
|
||||
#define ERRLEN 48
|
||||
typedef struct Note Note;
|
||||
|
|
@ -85,7 +84,7 @@ _threadnote(void *v, char *s)
|
|||
Note *n;
|
||||
|
||||
_threaddebug(DBGNOTE, "Got note %s", s);
|
||||
if(strncmp(s, "sys:", 4) == 0)
|
||||
if(strncmp(s, "sys:", 4) == 0 && strcmp(s, "sys: write on closed pipe") != 0)
|
||||
noted(NDFLT);
|
||||
|
||||
// if(_threadexitsallstatus){
|
||||
|
|
@ -112,7 +111,6 @@ _threadnote(void *v, char *s)
|
|||
delayednotes(p, v);
|
||||
noted(NCONT);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
_procsplhi(void)
|
||||
|
|
|
|||
|
|
@ -98,17 +98,18 @@ runthread(Proc *p)
|
|||
q = &p->ready;
|
||||
lock(&p->readylock);
|
||||
if(q->head == nil){
|
||||
q->asleep = 1;
|
||||
if(p->idle){
|
||||
if(p->idle->state != Ready){
|
||||
fprint(2, "everyone is asleep\n");
|
||||
exits("everyone is asleep");
|
||||
}
|
||||
unlock(&p->readylock);
|
||||
_threaddebug(DBGSCHED, "running idle thread", p->nthreads);
|
||||
return p->idle;
|
||||
}
|
||||
|
||||
_threaddebug(DBGSCHED, "sleeping for more work (%d threads)", p->nthreads);
|
||||
q->asleep = 1;
|
||||
unlock(&p->readylock);
|
||||
while(rendezvous((ulong)q, 0) == ~0){
|
||||
if(_threadexitsallstatus)
|
||||
|
|
@ -148,7 +149,7 @@ Resched:
|
|||
_threaddelproc();
|
||||
_schedexit(p);
|
||||
}
|
||||
// _threaddebug(DBGSCHED, "running %d.%d", t->proc->pid, t->id);
|
||||
_threaddebug(DBGSCHED, "running %d.%d", t->proc->pid, t->id);
|
||||
p->thread = t;
|
||||
if(t->moribund){
|
||||
_threaddebug(DBGSCHED, "%d.%d marked to die");
|
||||
|
|
@ -176,8 +177,10 @@ _threadready(Thread *t)
|
|||
{
|
||||
Tqueue *q;
|
||||
|
||||
if(t == t->proc->idle)
|
||||
if(t == t->proc->idle){
|
||||
_threaddebug(DBGSCHED, "idle thread is ready");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(t->state == Ready);
|
||||
_threaddebug(DBGSCHED, "readying %d.%d", t->proc->pid, t->id);
|
||||
|
|
@ -206,18 +209,25 @@ void
|
|||
_threadidle(void)
|
||||
{
|
||||
Tqueue *q;
|
||||
Thread *t;
|
||||
Thread *t, *idle;
|
||||
Proc *p;
|
||||
|
||||
p = _threadgetproc();
|
||||
q = &p->ready;
|
||||
lock(&p->readylock);
|
||||
assert(q->head);
|
||||
t = q->head;
|
||||
q->head = t->next;
|
||||
if(q->tail == t)
|
||||
assert(q->tail);
|
||||
idle = q->tail;
|
||||
if(q->head == idle){
|
||||
q->head = nil;
|
||||
q->tail = nil;
|
||||
p->idle = t;
|
||||
}else{
|
||||
for(t=q->head; t->next!=q->tail; t=t->next)
|
||||
;
|
||||
t->next = nil;
|
||||
q->tail = t;
|
||||
}
|
||||
p->idle = idle;
|
||||
_threaddebug(DBGSCHED, "p->idle is %d\n", idle->id);
|
||||
unlock(&p->readylock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ struct Execargs
|
|||
char *prog;
|
||||
char **args;
|
||||
int fd[2];
|
||||
int *stdfd;
|
||||
};
|
||||
|
||||
struct Proc
|
||||
|
|
@ -214,4 +215,5 @@ extern void _stackfree(void*);
|
|||
extern int _threadgetpid(void);
|
||||
extern void _threadmemset(void*, int, int);
|
||||
extern void _threaddebugmemset(void*, int, int);
|
||||
extern int _threadprocs;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue