still more files
This commit is contained in:
parent
cf4f3eafc6
commit
24f4e66b12
5 changed files with 300 additions and 0 deletions
185
src/libthread/Linux-clone.c
Normal file
185
src/libthread/Linux-clone.c
Normal file
|
|
@ -0,0 +1,185 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
|
#define procid() getpid()
|
||||||
|
#define procexited(id) (kill((id), 0) < 0 && errno==ESRCH)
|
||||||
|
|
||||||
|
static int multi;
|
||||||
|
static Proc *theproc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Run all execs forked from a special exec proc.
|
||||||
|
*/
|
||||||
|
#include "execproc.ch"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use _exits to exit one proc, and signals to tear everyone else down.
|
||||||
|
*/
|
||||||
|
#include "exit-getpid.ch"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use table for _threadmultiproc, _threadsetproc, _threadgetproc.
|
||||||
|
*/
|
||||||
|
#include "proctab.ch"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use per-process stack allocation code.
|
||||||
|
*/
|
||||||
|
#include "procstack.ch"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implement _threadstartproc using clone.
|
||||||
|
*
|
||||||
|
* Cannot use this on newer kernels (2.6+) because
|
||||||
|
* on those kernels clone allows you to set up a per-thread
|
||||||
|
* segment using %gs, and the C library and compilers
|
||||||
|
* assume that you've done this. I don't want to learn
|
||||||
|
* how to do this (the code below is scary enough),
|
||||||
|
* so on those more recent kernels we use nptl (the
|
||||||
|
* pthreads implementation), which is finally good enough.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trampoline to run f(arg).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tramp(void *v)
|
||||||
|
{
|
||||||
|
void (*fn)(void*), *arg;
|
||||||
|
void **v2;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
v2 = v;
|
||||||
|
fn = v2[0];
|
||||||
|
arg = v2[1];
|
||||||
|
p = v2[2];
|
||||||
|
free(v2);
|
||||||
|
fn(arg);
|
||||||
|
abort(); /* not reached! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trampnowait runs in the child, and starts a granchild to run f(arg).
|
||||||
|
* When trampnowait proc exits, the connection between the
|
||||||
|
* grandchild running f(arg) and the parent/grandparent is lost, so the
|
||||||
|
* grandparent need not worry about cleaning up a zombie
|
||||||
|
* when the grandchild finally exits.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
trampnowait(void *v)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
int cloneflag;
|
||||||
|
void **v2;
|
||||||
|
int *pidp;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
v2 = v;
|
||||||
|
cloneflag = (int)v2[4];
|
||||||
|
pidp = v2[3];
|
||||||
|
p = v2[2];
|
||||||
|
pid = clone(tramp, p+fforkstacksize-512, cloneflag, v);
|
||||||
|
*pidp = pid;
|
||||||
|
_exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ffork(int flags, void (*fn)(void*), void *arg)
|
||||||
|
{
|
||||||
|
void **v;
|
||||||
|
char *p;
|
||||||
|
int cloneflag, pid, thepid, status, nowait;
|
||||||
|
|
||||||
|
p = mallocstack();
|
||||||
|
v = malloc(sizeof(void*)*5);
|
||||||
|
if(p==nil || v==nil){
|
||||||
|
freestack(p);
|
||||||
|
free(v);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cloneflag = 0;
|
||||||
|
flags &= ~RFPROC;
|
||||||
|
if(flags&RFMEM){
|
||||||
|
cloneflag |= CLONE_VM;
|
||||||
|
flags &= ~RFMEM;
|
||||||
|
}
|
||||||
|
if(!(flags&RFFDG))
|
||||||
|
cloneflag |= CLONE_FILES;
|
||||||
|
else
|
||||||
|
flags &= ~RFFDG;
|
||||||
|
nowait = flags&RFNOWAIT;
|
||||||
|
// if(!(flags&RFNOWAIT))
|
||||||
|
// cloneflag |= SIGCHLD;
|
||||||
|
// else
|
||||||
|
flags &= ~RFNOWAIT;
|
||||||
|
if(flags){
|
||||||
|
fprint(2, "unknown rfork flags %x\n", flags);
|
||||||
|
freestack(p);
|
||||||
|
free(v);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
v[0] = fn;
|
||||||
|
v[1] = arg;
|
||||||
|
v[2] = p;
|
||||||
|
v[3] = &thepid;
|
||||||
|
v[4] = (void*)cloneflag;
|
||||||
|
thepid = -1;
|
||||||
|
pid = clone(nowait ? trampnowait : tramp, p+fforkstacksize-16, cloneflag, v);
|
||||||
|
if(pid > 0 && nowait){
|
||||||
|
if(wait4(pid, &status, __WALL, 0) < 0)
|
||||||
|
fprint(2, "ffork wait4: %r\n");
|
||||||
|
}else
|
||||||
|
thepid = pid;
|
||||||
|
if(thepid == -1)
|
||||||
|
freestack(p);
|
||||||
|
else{
|
||||||
|
((Stack*)p)->pid = thepid;
|
||||||
|
}
|
||||||
|
return thepid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to start a new proc.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadstartproc(Proc *p)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
Proc *np;
|
||||||
|
|
||||||
|
np = p->newproc;
|
||||||
|
pid = ffork(RFPROC|RFMEM|RFNOWAIT, _threadscheduler, np);
|
||||||
|
if(pid == -1)
|
||||||
|
sysfatal("starting new proc: %r");
|
||||||
|
np->pid = pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to associate p with the current pthread.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadinitproc(Proc *p)
|
||||||
|
{
|
||||||
|
sigset_t mask;
|
||||||
|
|
||||||
|
p->pid = getpid();
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, WAITSIG);
|
||||||
|
sigprocmask(SIG_BLOCK, &mask, nil);
|
||||||
|
_threadsetproc(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from mainlauncher before threadmain.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadmaininit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
25
src/libthread/pid.c
Normal file
25
src/libthread/pid.c
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
mypid = getpid();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* signal others.
|
||||||
|
* copying all the pids first avoids other thread's
|
||||||
|
* teardown procedures getting in the way.
|
||||||
|
*/
|
||||||
|
lock(&_threadpq.lock);
|
||||||
|
npid = 0;
|
||||||
|
for(p=_threadpq.head; p; p=p->next)
|
||||||
|
npid++;
|
||||||
|
pid = _threadmalloc(npid*sizeof(pid[0]), 0);
|
||||||
|
npid = 0;
|
||||||
|
for(p = _threadpq.head; p; p=p->next)
|
||||||
|
pid[npid++] = p->pid;
|
||||||
|
unlock(&_threadpq.lock);
|
||||||
|
for(i=0; i<npid; i++){
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
36
src/libthread/setproc.c
Normal file
36
src/libthread/setproc.c
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Avoid using threading calls for single-proc programs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
|
static int multi;
|
||||||
|
static Proc *theproc;
|
||||||
|
|
||||||
|
void
|
||||||
|
_threadsetproc(Proc *p)
|
||||||
|
{
|
||||||
|
if(!multi)
|
||||||
|
theproc = p;
|
||||||
|
else
|
||||||
|
_kthreadsetproc(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
Proc*
|
||||||
|
_threadgetproc(void)
|
||||||
|
{
|
||||||
|
if(!multi)
|
||||||
|
return theproc;
|
||||||
|
return _kthreadgetproc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_threadmultiproc(void)
|
||||||
|
{
|
||||||
|
if(multi)
|
||||||
|
return;
|
||||||
|
|
||||||
|
multi = 1;
|
||||||
|
_kthreadinit();
|
||||||
|
_threadsetproc(theproc);
|
||||||
|
}
|
||||||
11
src/libthread/sysofiles.sh
Normal file
11
src/libthread/sysofiles.sh
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
case "`uname`-`uname -r`" in
|
||||||
|
Linux-2.[01234]*)
|
||||||
|
echo Linux-clone.o ucontext.o
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo pthread.o ucontext.o
|
||||||
|
exit 0
|
||||||
43
src/libthread/tsignal.c
Normal file
43
src/libthread/tsignal.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <thread.h>
|
||||||
|
|
||||||
|
extern int _threaddebuglevel;
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprint(2, "usage: tsignal [-[ednf] note]*\n");
|
||||||
|
threadexitsall("usage");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
threadmain(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Channel *c;
|
||||||
|
char *msg;
|
||||||
|
|
||||||
|
ARGBEGIN{
|
||||||
|
case 'D':
|
||||||
|
_threaddebuglevel = ~0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
case 'e':
|
||||||
|
notifyenable(EARGF(usage()));
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
notifydisable(EARGF(usage()));
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
notifyon(EARGF(usage()));
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
notifyoff(EARGF(usage()));
|
||||||
|
break;
|
||||||
|
}ARGEND
|
||||||
|
|
||||||
|
c = threadnotechan();
|
||||||
|
while((msg = recvp(c)) != nil)
|
||||||
|
print("note: %s\n", msg);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue