libthread: rm FreeBSD 4 code

Pretty sure FreeBSD 4 is gone now. :-)
This commit is contained in:
Russ Cox 2020-01-19 21:25:33 -05:00
parent d15607b9dd
commit 8dcb18f71b
7 changed files with 54 additions and 504 deletions

View file

@ -86,10 +86,8 @@ typedef long p9jmp_buf[sizeof(sigjmp_buf)/sizeof(long)];
#elif defined(__FreeBSD__)
# include <sys/types.h>
# include <osreldate.h>
# if __FreeBSD_version >= 500000
# define PLAN9PORT_USING_PTHREADS 1
# include <pthread.h>
# endif
# define PLAN9PORT_USING_PTHREADS 1
# include <pthread.h>
# if !defined(_POSIX_SOURCE)
# undef _NEEDUSHORT
# undef _NEEDUINT

View file

@ -1,403 +0,0 @@
#undef exits
#undef _exits
extern int __isthreaded;
/*
* spin locks
*/
extern int _tas(int*);
void
_threadunlock(Lock *l, ulong pc)
{
USED(pc);
l->held = 0;
}
int
_threadlock(Lock *l, int block, ulong pc)
{
int i;
USED(pc);
/* once fast */
if(!_tas(&l->held))
return 1;
if(!block)
return 0;
/* a thousand times pretty fast */
for(i=0; i<1000; i++){
if(!_tas(&l->held))
return 1;
sleep(0);
}
/* increasingly slow */
for(i=0; i<10; i++){
if(!_tas(&l->held))
return 1;
usleep(1);
}
for(i=0; i<10; i++){
if(!_tas(&l->held))
return 1;
usleep(10);
}
for(i=0; i<10; i++){
if(!_tas(&l->held))
return 1;
usleep(100);
}
for(i=0; i<10; i++){
if(!_tas(&l->held))
return 1;
usleep(1000);
}
for(i=0; i<10; i++){
if(!_tas(&l->held))
return 1;
usleep(10*1000);
}
/* now nice and slow */
for(i=0; i<1000; i++){
if(!_tas(&l->held))
return 1;
usleep(100*1000);
}
/* take your time */
while(_tas(&l->held))
usleep(1000*1000);
return 1;
}
/*
* For libc.
*/
typedef struct {
volatile long access_lock;
volatile long lock_owner;
volatile char *fname;
volatile int lineno;
} spinlock_t;
void
_spinlock(spinlock_t *lk)
{
lock((Lock*)&lk->access_lock);
}
void
_spinunlock(spinlock_t *lk)
{
unlock((Lock*)&lk->access_lock);
}
/*
* sleep and wakeup
*/
static void
ign(int x)
{
USED(x);
}
static void /*__attribute__((constructor))*/
ignusr1(int restart)
{
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_handler = ign;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGUSR1);
if(restart)
sa.sa_flags = SA_RESTART;
sigaction(SIGUSR1, &sa, nil);
}
void
_procsleep(_Procrendez *r)
{
sigset_t mask;
/*
* Go to sleep.
*
* Block USR1, set the handler to interrupt system calls,
* unlock the vouslock so our waker can wake us,
* and then suspend.
*/
again:
r->asleep = 1;
r->pid = getpid();
sigprocmask(SIG_SETMASK, nil, &mask);
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_SETMASK, &mask, nil);
ignusr1(0);
unlock(r->l);
sigdelset(&mask, SIGUSR1);
sigsuspend(&mask);
/*
* We're awake. Make USR1 not interrupt system calls.
*/
lock(r->l);
ignusr1(1);
if(r->asleep && r->pid == getpid()){
/* Didn't really wake up - signal from something else */
goto again;
}
}
void
_procwakeup(_Procrendez *r)
{
if(r->asleep){
r->asleep = 0;
assert(r->pid >= 1);
kill(r->pid, SIGUSR1);
}
}
void
_procwakeupandunlock(_Procrendez *r)
{
_procwakeup(r);
unlock(r->l);
}
/*
* process creation and exit
*/
typedef struct Stackfree Stackfree;
struct Stackfree
{
Stackfree *next;
int pid;
};
static Lock stacklock;
static Stackfree *stackfree;
static void
delayfreestack(uchar *stk)
{
Stackfree *sf;
sf = (Stackfree*)stk;
sf->pid = getpid();
lock(&stacklock);
sf->next = stackfree;
stackfree = sf;
unlock(&stacklock);
}
static void
dofreestacks(void)
{
Stackfree *sf, *last, *next;
if(stackfree==nil || !canlock(&stacklock))
return;
for(last=nil,sf=stackfree; sf; last=sf,sf=next){
next = sf->next;
if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
free(sf);
if(last)
last->next = next;
else
stackfree = next;
sf = last;
}
}
unlock(&stacklock);
}
static int
startprocfn(void *v)
{
void **a;
uchar *stk;
void (*fn)(void*);
Proc *p;
a = (void**)v;
fn = a[0];
p = a[1];
stk = a[2];
free(a);
p->osprocid = getpid();
(*fn)(p);
delayfreestack(stk);
_exit(0);
return 0;
}
void
_procstart(Proc *p, void (*fn)(Proc*))
{
void **a;
uchar *stk;
int pid;
dofreestacks();
a = malloc(3*sizeof a[0]);
if(a == nil)
sysfatal("_procstart malloc: %r");
stk = malloc(65536);
if(stk == nil)
sysfatal("_procstart malloc stack: %r");
a[0] = fn;
a[1] = p;
a[2] = stk;
pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a);
if(pid < 0){
fprint(2, "_procstart rfork_thread: %r\n");
abort();
}
}
static char *threadexitsmsg;
void
sigusr2handler(int s)
{
/* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
if(threadexitsmsg)
_exits(threadexitsmsg);
}
void
threadexitsall(char *msg)
{
static int pid[1024];
int i, npid, mypid;
Proc *p;
if(msg == nil)
msg = "";
/*
* Only one guy, ever, gets to run this.
* If two guys do it, inevitably they end up
* tripping over each other in the underlying
* C library exit() implementation, which is
* trying to run the atexit handlers and apparently
* not thread safe. This has been observed on
* both Linux and OpenBSD. Sigh.
*/
{
static Lock onelock;
if(!canlock(&onelock))
_exits(threadexitsmsg);
threadexitsmsg = msg;
}
if(msg == nil)
msg = "";
mypid = getpid();
lock(&_threadprocslock);
threadexitsmsg = msg;
npid = 0;
for(p=_threadprocs; p; p=p->next)
if(p->osprocid != mypid && p->osprocid >= 1)
pid[npid++] = p->osprocid;
for(i=0; i<npid; i++)
kill(pid[i], SIGUSR2);
unlock(&_threadprocslock);
exits(msg);
}
/*
* per-process data, indexed by pid
*/
typedef struct Perproc Perproc;
struct Perproc
{
int pid;
Proc *proc;
};
static Lock perlock;
static Perproc perproc[1024];
#define P ((Proc*)-1)
static Perproc*
myperproc(void)
{
int i, pid, h;
Perproc *p;
pid = getpid();
h = pid%nelem(perproc);
for(i=0; i<nelem(perproc); i++){
p = &perproc[(i+h)%nelem(perproc)];
if(p->pid == pid)
return p;
if(p->pid == 0){
print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
break;
}
}
fprint(2, "myperproc %d: cannot find self\n", pid);
abort();
return nil;
}
static Perproc*
newperproc(void)
{
int i, pid, h;
Perproc *p;
lock(&perlock);
pid = getpid();
h = pid%nelem(perproc);
for(i=0; i<nelem(perproc); i++){
p = &perproc[(i+h)%nelem(perproc)];
if(p->pid == pid || p->pid == -1 || p->pid == 0){
p->pid = pid;
unlock(&perlock);
return p;
}
}
fprint(2, "newperproc %d: out of procs\n", pid);
abort();
return nil;
}
Proc*
_threadproc(void)
{
return myperproc()->proc;
}
void
_threadsetproc(Proc *p)
{
Perproc *pp;
if(p)
p->osprocid = getpid();
pp = newperproc();
pp->proc = p;
if(p == nil)
pp->pid = -1;
}
void
_threadpexit(void)
{
_exit(0);
}

View file

@ -1,52 +0,0 @@
.globl _tas
_tas:
movl $0xCAFEBABE, %eax
movl 4(%esp), %ecx
xchgl %eax, 0(%ecx)
ret
.globl getmcontext
getmcontext:
movl 4(%esp), %eax
movl %fs, 8(%eax)
movl %es, 12(%eax)
movl %ds, 16(%eax)
movl %ss, 76(%eax)
movl %edi, 20(%eax)
movl %esi, 24(%eax)
movl %ebp, 28(%eax)
movl %ebx, 36(%eax)
movl %edx, 40(%eax)
movl %ecx, 44(%eax)
movl $1, 48(%eax) /* %eax */
movl (%esp), %ecx /* %eip */
movl %ecx, 60(%eax)
leal 4(%esp), %ecx /* %esp */
movl %ecx, 72(%eax)
movl 44(%eax), %ecx /* restore %ecx */
movl $0, %eax
ret
.globl setmcontext
setmcontext:
movl 4(%esp), %eax
movl 8(%eax), %fs
movl 12(%eax), %es
movl 16(%eax), %ds
movl 76(%eax), %ss
movl 20(%eax), %edi
movl 24(%eax), %esi
movl 28(%eax), %ebp
movl 36(%eax), %ebx
movl 40(%eax), %edx
movl 44(%eax), %ecx
movl 72(%eax), %esp
pushl 60(%eax) /* new %eip */
movl 48(%eax), %eax
ret

View file

@ -1,34 +0,0 @@
#include "threadimpl.h"
#include "BSD.c"
/*
* FreeBSD 4 and earlier needs the context functions.
*/
void
makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
{
int *sp;
sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4;
sp -= argc;
memmove(sp, &argc+1, argc*sizeof(int));
*--sp = 0; /* return address */
ucp->uc_mcontext.mc_eip = (long)func;
ucp->uc_mcontext.mc_esp = (int)sp;
}
int
swapcontext(ucontext_t *oucp, ucontext_t *ucp)
{
if(getcontext(oucp) == 0)
setcontext(ucp);
return 0;
}
void
_pthreadinit(void)
{
__isthreaded = 1;
signal(SIGUSR2, sigusr2handler);
}

View file

@ -1 +1,52 @@
#include "FreeBSD-386-asm.s"
.globl _tas
_tas:
movl $0xCAFEBABE, %eax
movl 4(%esp), %ecx
xchgl %eax, 0(%ecx)
ret
.globl getmcontext
getmcontext:
movl 4(%esp), %eax
movl %fs, 8(%eax)
movl %es, 12(%eax)
movl %ds, 16(%eax)
movl %ss, 76(%eax)
movl %edi, 20(%eax)
movl %esi, 24(%eax)
movl %ebp, 28(%eax)
movl %ebx, 36(%eax)
movl %edx, 40(%eax)
movl %ecx, 44(%eax)
movl $1, 48(%eax) /* %eax */
movl (%esp), %ecx /* %eip */
movl %ecx, 60(%eax)
leal 4(%esp), %ecx /* %esp */
movl %ecx, 72(%eax)
movl 44(%eax), %ecx /* restore %ecx */
movl $0, %eax
ret
.globl setmcontext
setmcontext:
movl 4(%esp), %eax
movl 8(%eax), %fs
movl 12(%eax), %es
movl 16(%eax), %ds
movl 76(%eax), %ss
movl 20(%eax), %edi
movl 24(%eax), %esi
movl 28(%eax), %ebp
movl 36(%eax), %ebx
movl 40(%eax), %edx
movl 44(%eax), %ecx
movl 72(%eax), %esp
pushl 60(%eax) /* new %eip */
movl 48(%eax), %eax
ret

View file

@ -16,7 +16,6 @@ OFILES=\
<$PLAN9/src/mksyslib
HFILES=thread.h threadimpl.h
FreeBSD.$O: BSD.c
NetBSD.$O: Linux.c
tprimes: test/tprimes.$O

View file

@ -15,15 +15,6 @@
#include "libc.h"
#include "thread.h"
#if defined(__FreeBSD__) && __FreeBSD__ < 5
extern int getmcontext(mcontext_t*);
extern void setmcontext(mcontext_t*);
#define setcontext(u) setmcontext(&(u)->uc_mcontext)
#define getcontext(u) getmcontext(&(u)->uc_mcontext)
extern int swapcontext(ucontext_t*, ucontext_t*);
extern void makecontext(ucontext_t*, void(*)(), int, ...);
#endif
#if defined(__APPLE__)
/*
* OS X before 10.5 (Leopard) does not provide