mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
More Darwin.
This commit is contained in:
parent
a995e477ff
commit
a46395ecf9
10 changed files with 311 additions and 246 deletions
26
src/lib9/ffork-Darwin.c
Normal file
26
src/lib9/ffork-Darwin.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <lib9.h>
|
||||
#include <pthread.h>
|
||||
|
||||
extern int __isthreaded;
|
||||
int
|
||||
ffork(int flags, void(*fn)(void*), void *arg)
|
||||
{
|
||||
void *p;
|
||||
pthread_t tid;
|
||||
|
||||
if(flags != (RFMEM|RFNOWAIT)){
|
||||
werrstr("ffork unsupported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(pthread_create(&tid, NULL, (void*(*)(void*))fn, arg) < 0)
|
||||
return -1;
|
||||
return (int)tid;
|
||||
}
|
||||
|
||||
int
|
||||
getfforkid(void)
|
||||
{
|
||||
return (int)pthread_self();
|
||||
}
|
||||
|
246
src/lib9/lib9.h
246
src/lib9/lib9.h
|
@ -1,246 +0,0 @@
|
|||
/*
|
||||
* Lib9 is miscellany from the Plan 9 C library that doesn't
|
||||
* fit into libutf or into libfmt, but is still missing from traditional
|
||||
* Unix C libraries.
|
||||
*/
|
||||
#ifndef _LIB9H_
|
||||
#define _LIB9H_ 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _FMTH_
|
||||
# include <fmt.h>
|
||||
#endif
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
#define _NEEDUCHAR 1
|
||||
#define _NEEDUSHORT 1
|
||||
#define _NEEDUINT 1
|
||||
#define _NEEDULONG 1
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/types.h>
|
||||
# if defined(__USE_MISC)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# if !defined(_POSIX_SOURCE)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef signed char schar;
|
||||
typedef unsigned int u32int;
|
||||
#ifdef _NEEDUCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#ifdef _NEEDUSHORT
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
#ifdef _NEEDUINT
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#ifdef _NEEDULONG
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long long vlong;
|
||||
|
||||
/* rfork to create new process running fn(arg) */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef RFFDG
|
||||
#undef RFNOTEG
|
||||
#undef RFPROC
|
||||
#undef RFMEM
|
||||
#undef RFNOWAIT
|
||||
#undef RFCFDG
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/* RFNAMEG = (1<<0), */
|
||||
/* RFENVG = (1<<1), */
|
||||
RFFDG = (1<<2),
|
||||
RFNOTEG = (1<<3),
|
||||
RFPROC = (1<<4),
|
||||
RFMEM = (1<<5),
|
||||
RFNOWAIT = (1<<6),
|
||||
/* RFCNAMEG = (1<<10), */
|
||||
/* RFCENVG = (1<<11), */
|
||||
RFCFDG = (1<<12),
|
||||
/* RFREND = (1<<13), */
|
||||
/* RFNOMNT = (1<<14) */
|
||||
};
|
||||
extern int ffork(int, void(*)(void*), void*);
|
||||
|
||||
/* wait for processes */
|
||||
#define wait _p9wait
|
||||
typedef struct Waitmsg Waitmsg;
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
};
|
||||
extern int await(char*, int);
|
||||
extern Waitmsg* wait(void);
|
||||
|
||||
/* synchronization */
|
||||
typedef struct Lock Lock;
|
||||
struct Lock
|
||||
{
|
||||
int val;
|
||||
};
|
||||
|
||||
extern int _tas(void*);
|
||||
extern void lock(Lock*);
|
||||
extern void unlock(Lock*);
|
||||
extern int canlock(Lock*);
|
||||
|
||||
typedef struct QLp QLp;
|
||||
struct QLp
|
||||
{
|
||||
int inuse;
|
||||
QLp *next;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef struct QLock QLock;
|
||||
struct QLock
|
||||
{
|
||||
Lock lock;
|
||||
int locked;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void qlock(QLock*);
|
||||
extern void qunlock(QLock*);
|
||||
extern int canqlock(QLock*);
|
||||
extern void _qlockinit(ulong (*)(ulong, ulong));
|
||||
|
||||
typedef struct RWLock RWLock;
|
||||
struct RWLock
|
||||
{
|
||||
Lock lock;
|
||||
int readers;
|
||||
int writer;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rlock(RWLock*);
|
||||
extern void runlock(RWLock*);
|
||||
extern int canrlock(RWLock*);
|
||||
extern void wlock(RWLock*);
|
||||
extern void wunlock(RWLock*);
|
||||
extern int canwlock(RWLock*);
|
||||
|
||||
typedef struct Rendez Rendez;
|
||||
struct Rendez
|
||||
{
|
||||
QLock *l;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rsleep(Rendez*);
|
||||
extern int rwakeup(Rendez*);
|
||||
extern int rwakeupall(Rendez*);
|
||||
|
||||
extern ulong rendezvous(ulong, ulong);
|
||||
|
||||
/* one of a kind */
|
||||
extern void sysfatal(char*, ...);
|
||||
extern int nrand(int);
|
||||
extern void setmalloctag(void*, ulong);
|
||||
extern void setrealloctag(void*, ulong);
|
||||
extern void *mallocz(ulong, int);
|
||||
extern long readn(int, void*, long);
|
||||
extern void exits(char*);
|
||||
extern void _exits(char*);
|
||||
extern ulong getcallerpc(void*);
|
||||
|
||||
/* string routines */
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
extern int cistrncmp(char*, char*, int);
|
||||
extern int cistrcmp(char*, char*);
|
||||
extern char* cistrstr(char*, char*);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
extern int gettokens(char *, char **, int, char *);
|
||||
|
||||
/* formatting helpers */
|
||||
extern int dec64(uchar*, int, char*, int);
|
||||
extern int enc64(char*, int, uchar*, int);
|
||||
extern int dec32(uchar*, int, char*, int);
|
||||
extern int enc32(char*, int, uchar*, int);
|
||||
extern int dec16(uchar*, int, char*, int);
|
||||
extern int enc16(char*, int, uchar*, int);
|
||||
extern int encodefmt(Fmt*);
|
||||
|
||||
/* error string */
|
||||
enum
|
||||
{
|
||||
ERRMAX = 128
|
||||
};
|
||||
extern void rerrstr(char*, uint);
|
||||
extern void werrstr(char*, ...);
|
||||
extern int errstr(char*, uint);
|
||||
|
||||
/* compiler directives on plan 9 */
|
||||
#define USED(x) if(x){}else{}
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
/* command line */
|
||||
extern char *argv0;
|
||||
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
|
||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
||||
argc--, argv++) {\
|
||||
char *_args, *_argt;\
|
||||
Rune _argc;\
|
||||
_args = &argv[0][1];\
|
||||
if(_args[0]=='-' && _args[1]==0){\
|
||||
argc--; argv++; break;\
|
||||
}\
|
||||
_argc = 0;\
|
||||
while(*_args && (_args += chartorune(&_argc, _args)))\
|
||||
switch(_argc)
|
||||
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
|
||||
#define ARGF() (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
|
||||
#define EARGF(x) (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
|
||||
|
||||
#define ARGC() _argc
|
||||
|
||||
#define OREAD O_RDONLY
|
||||
#define OWRITE O_WRONLY
|
||||
#define AEXIST 0
|
||||
#define AREAD 4
|
||||
#define AWRITE 2
|
||||
#define AEXEC 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIB9H_ */
|
2
src/lib9/rendez-Darwin.c
Normal file
2
src/lib9/rendez-Darwin.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "rendez-pthread.c"
|
||||
|
1
src/lib9/rendez-FreeBSD.c
Normal file
1
src/lib9/rendez-FreeBSD.c
Normal file
|
@ -0,0 +1 @@
|
|||
#include "rendez-signal.c"
|
1
src/lib9/rendez-Linux.c
Normal file
1
src/lib9/rendez-Linux.c
Normal file
|
@ -0,0 +1 @@
|
|||
#include "rendez-signal.c"
|
168
src/lib9/rendez-pthread.c
Normal file
168
src/lib9/rendez-pthread.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
NAME
|
||||
rendezvous - user level process synchronization
|
||||
|
||||
SYNOPSIS
|
||||
ulong rendezvous(ulong tag, ulong value)
|
||||
|
||||
DESCRIPTION
|
||||
The rendezvous system call allows two processes to synchro-
|
||||
nize and exchange a value. In conjunction with the shared
|
||||
memory system calls (see segattach(2) and fork(2)), it
|
||||
enables parallel programs to control their scheduling.
|
||||
|
||||
Two processes wishing to synchronize call rendezvous with a
|
||||
common tag, typically an address in memory they share. One
|
||||
process will arrive at the rendezvous first; it suspends
|
||||
execution until a second arrives. When a second process
|
||||
meets the rendezvous the value arguments are exchanged
|
||||
between the processes and returned as the result of the
|
||||
respective rendezvous system calls. Both processes are
|
||||
awakened when the rendezvous succeeds.
|
||||
|
||||
The set of tag values which two processes may use to
|
||||
rendezvous-their tag space-is inherited when a process
|
||||
forks, unless RFREND is set in the argument to rfork; see
|
||||
fork(2).
|
||||
|
||||
If a rendezvous is interrupted the return value is ~0, so
|
||||
that value should not be used in normal communication.
|
||||
|
||||
* This assumes we're using pthreads and simulates rendezvous using
|
||||
* shared memory and mutexes.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <lib9.h>
|
||||
|
||||
enum
|
||||
{
|
||||
VOUSHASH = 257,
|
||||
};
|
||||
|
||||
typedef struct Vous Vous;
|
||||
struct Vous
|
||||
{
|
||||
Vous *link;
|
||||
Lock lk;
|
||||
ulong val;
|
||||
ulong tag;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
static void
|
||||
ign(int x)
|
||||
{
|
||||
USED(x);
|
||||
}
|
||||
|
||||
void /*__attribute__((constructor))*/
|
||||
ignusr1(void)
|
||||
{
|
||||
signal(SIGUSR1, ign);
|
||||
}
|
||||
|
||||
static Vous vouspool[2048];
|
||||
static int nvousused;
|
||||
static Vous *vousfree;
|
||||
static Vous *voushash[VOUSHASH];
|
||||
static Lock vouslock;
|
||||
|
||||
static Vous*
|
||||
getvous(void)
|
||||
{
|
||||
Vous *v;
|
||||
|
||||
if(vousfree){
|
||||
v = vousfree;
|
||||
vousfree = v->link;
|
||||
}else if(nvousused < nelem(vouspool)){
|
||||
v = &vouspool[nvousused++];
|
||||
pthread_mutex_init(&v->mutex, NULL);
|
||||
}else
|
||||
abort();
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
putvous(Vous *v)
|
||||
{
|
||||
lock(&vouslock);
|
||||
v->link = vousfree;
|
||||
vousfree = v;
|
||||
unlock(&vouslock);
|
||||
}
|
||||
|
||||
static Vous*
|
||||
findvous(ulong tag, ulong val, int *found)
|
||||
{
|
||||
int h;
|
||||
Vous *v, **l;
|
||||
|
||||
lock(&vouslock);
|
||||
h = tag%VOUSHASH;
|
||||
for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
|
||||
if(v->tag == tag){
|
||||
*l = v->link;
|
||||
*found = 1;
|
||||
unlock(&vouslock);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
v = getvous();
|
||||
v->link = voushash[h];
|
||||
v->val = val;
|
||||
v->tag = tag;
|
||||
lock(&v->lk);
|
||||
voushash[h] = v;
|
||||
unlock(&vouslock);
|
||||
*found = 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
#define DBG 0
|
||||
ulong
|
||||
rendezvous(ulong tag, ulong val)
|
||||
{
|
||||
int found;
|
||||
ulong rval;
|
||||
Vous *v;
|
||||
|
||||
v = findvous(tag, val, &found);
|
||||
if(!found){
|
||||
if(DBG)fprint(2, "tag %lux, sleeping on %p\n", tag, v);
|
||||
/*
|
||||
* No rendezvous partner was found; the next guy
|
||||
* through will find v and wake us, so we must go
|
||||
* to sleep. Do this by locking the mutex (it is
|
||||
* unlocked) and then locking it again (our waker will
|
||||
* unlock it for us).
|
||||
*/
|
||||
if(pthread_mutex_lock(&v->mutex) != 0)
|
||||
abort();
|
||||
unlock(&v->lk);
|
||||
if(pthread_mutex_lock(&v->mutex) != 0)
|
||||
abort();
|
||||
rval = v->val;
|
||||
pthread_mutex_unlock(&v->mutex);
|
||||
if(DBG)fprint(2, " awake on %p\n", v);
|
||||
unlock(&v->lk);
|
||||
putvous(v);
|
||||
}else{
|
||||
/*
|
||||
* Found someone to meet. Wake him:
|
||||
*
|
||||
* A. lock v->lk (waits for him to lock the mutex once.
|
||||
* B. unlock the mutex (wakes him up)
|
||||
*/
|
||||
if(DBG)fprint(2, "found tag %lux on %p, waking\n", tag, v);
|
||||
lock(&v->lk);
|
||||
rval = v->val;
|
||||
v->val = val;
|
||||
if(pthread_mutex_unlock(&v->mutex) != 0)
|
||||
abort();
|
||||
/* lock passes to him */
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
5
src/libthread/Darwin.c
Normal file
5
src/libthread/Darwin.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
int
|
||||
_schedfork(Proc *p)
|
||||
{
|
||||
return ffork(RFMEM|RFNOWAIT, _schedinit, p);
|
||||
}
|
28
src/libthread/PowerMacintosh.c
Normal file
28
src/libthread/PowerMacintosh.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "threadimpl.h"
|
||||
|
||||
static void
|
||||
launcherpower(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
|
||||
void (*f)(void *arg), void *arg)
|
||||
{
|
||||
(*f)(arg);
|
||||
threadexits(nil);
|
||||
}
|
||||
|
||||
void
|
||||
_threadinitstack(Thread *t, void (*f)(void*), void *arg)
|
||||
{
|
||||
ulong *tos, *stk;
|
||||
int n;
|
||||
|
||||
tos = (ulong*)&t->stk[t->stksize&~7];
|
||||
stk = tos;
|
||||
--stk;
|
||||
--stk;
|
||||
--stk;
|
||||
--stk;
|
||||
*--stk = (ulong)arg;
|
||||
*--stk = (ulong)f;
|
||||
t->sched.pc = (ulong)launcherpower+LABELDPC;
|
||||
t->sched.sp = (ulong)tos-80;
|
||||
}
|
||||
|
80
src/libthread/asm-Darwin-PowerMacintosh.s
Normal file
80
src/libthread/asm-Darwin-PowerMacintosh.s
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* get FPR and VR use flags with sc 0x7FF3 */
|
||||
/* get vsave with mfspr reg, 256 */
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
.globl __setlabel
|
||||
|
||||
__setlabel: /* xxx: instruction scheduling */
|
||||
mflr r0
|
||||
mfcr r5
|
||||
mfctr r6
|
||||
mfxer r7
|
||||
stw r0, 0*4(r3)
|
||||
stw r5, 1*4(r3)
|
||||
stw r6, 2*4(r3)
|
||||
stw r7, 3*4(r3)
|
||||
|
||||
stw r1, 4*4(r3)
|
||||
stw r2, 5*4(r3)
|
||||
|
||||
stw r13, (0+6)*4(r3) /* callee-save GPRs */
|
||||
stw r14, (1+6)*4(r3) /* xxx: block move */
|
||||
stw r15, (2+6)*4(r3)
|
||||
stw r16, (3+6)*4(r3)
|
||||
stw r17, (4+6)*4(r3)
|
||||
stw r18, (5+6)*4(r3)
|
||||
stw r19, (6+6)*4(r3)
|
||||
stw r20, (7+6)*4(r3)
|
||||
stw r21, (8+6)*4(r3)
|
||||
stw r22, (9+6)*4(r3)
|
||||
stw r23, (10+6)*4(r3)
|
||||
stw r24, (11+6)*4(r3)
|
||||
stw r25, (12+6)*4(r3)
|
||||
stw r26, (13+6)*4(r3)
|
||||
stw r27, (14+6)*4(r3)
|
||||
stw r28, (15+6)*4(r3)
|
||||
stw r29, (16+6)*4(r3)
|
||||
stw r30, (17+6)*4(r3)
|
||||
stw r31, (18+6)*4(r3)
|
||||
|
||||
li r3, 0 /* return */
|
||||
blr
|
||||
|
||||
.globl __gotolabel
|
||||
|
||||
__gotolabel:
|
||||
lwz r13, (0+6)*4(r3) /* callee-save GPRs */
|
||||
lwz r14, (1+6)*4(r3) /* xxx: block move */
|
||||
lwz r15, (2+6)*4(r3)
|
||||
lwz r16, (3+6)*4(r3)
|
||||
lwz r17, (4+6)*4(r3)
|
||||
lwz r18, (5+6)*4(r3)
|
||||
lwz r19, (6+6)*4(r3)
|
||||
lwz r20, (7+6)*4(r3)
|
||||
lwz r21, (8+6)*4(r3)
|
||||
lwz r22, (9+6)*4(r3)
|
||||
lwz r23, (10+6)*4(r3)
|
||||
lwz r24, (11+6)*4(r3)
|
||||
lwz r25, (12+6)*4(r3)
|
||||
lwz r26, (13+6)*4(r3)
|
||||
lwz r27, (14+6)*4(r3)
|
||||
lwz r28, (15+6)*4(r3)
|
||||
lwz r29, (16+6)*4(r3)
|
||||
lwz r30, (17+6)*4(r3)
|
||||
lwz r31, (18+6)*4(r3)
|
||||
|
||||
lwz r1, 4*4(r3)
|
||||
lwz r2, 5*4(r3)
|
||||
|
||||
lwz r0, 0*4(r3)
|
||||
mtlr r0
|
||||
lwz r0, 1*4(r3)
|
||||
mtcr r0 /* mtcrf 0xFF, r0 */
|
||||
lwz r0, 2*4(r3)
|
||||
mtctr r0
|
||||
lwz r0, 3*4(r3)
|
||||
mtxer r0
|
||||
li r3, 1
|
||||
blr
|
Loading…
Reference in a new issue