aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-10-01 02:53:00 +0000
committerrsc <devnull@localhost>2003-10-01 02:53:00 +0000
commita46395ecf932ea4e91ad047e92d1c70395e15673 (patch)
treef6f6d26edf773119b7e8e12d1b225c556c30bda5
parenta995e477ffb4dd1184da87e9e46a9e57f3178c63 (diff)
downloadplan9port-a46395ecf932ea4e91ad047e92d1c70395e15673.tar.gz
plan9port-a46395ecf932ea4e91ad047e92d1c70395e15673.tar.bz2
plan9port-a46395ecf932ea4e91ad047e92d1c70395e15673.zip
More Darwin.
-rw-r--r--src/lib9/ffork-Darwin.c26
-rw-r--r--src/lib9/lib9.h246
-rw-r--r--src/lib9/rendez-Darwin.c2
-rw-r--r--src/lib9/rendez-FreeBSD.c1
-rw-r--r--src/lib9/rendez-Linux.c1
-rw-r--r--src/lib9/rendez-pthread.c168
-rw-r--r--src/lib9/rendez-signal.c (renamed from src/lib9/rendez.c)0
-rw-r--r--src/libthread/Darwin.c5
-rw-r--r--src/libthread/PowerMacintosh.c28
-rw-r--r--src/libthread/asm-Darwin-PowerMacintosh.s80
10 files changed, 311 insertions, 246 deletions
diff --git a/src/lib9/ffork-Darwin.c b/src/lib9/ffork-Darwin.c
new file mode 100644
index 00000000..189ac94f
--- /dev/null
+++ b/src/lib9/ffork-Darwin.c
@@ -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();
+}
+
diff --git a/src/lib9/lib9.h b/src/lib9/lib9.h
deleted file mode 100644
index bb7e5404..00000000
--- a/src/lib9/lib9.h
+++ /dev/null
@@ -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_ */
diff --git a/src/lib9/rendez-Darwin.c b/src/lib9/rendez-Darwin.c
new file mode 100644
index 00000000..2f099fc4
--- /dev/null
+++ b/src/lib9/rendez-Darwin.c
@@ -0,0 +1,2 @@
+#include "rendez-pthread.c"
+
diff --git a/src/lib9/rendez-FreeBSD.c b/src/lib9/rendez-FreeBSD.c
new file mode 100644
index 00000000..05c52ae7
--- /dev/null
+++ b/src/lib9/rendez-FreeBSD.c
@@ -0,0 +1 @@
+#include "rendez-signal.c"
diff --git a/src/lib9/rendez-Linux.c b/src/lib9/rendez-Linux.c
new file mode 100644
index 00000000..05c52ae7
--- /dev/null
+++ b/src/lib9/rendez-Linux.c
@@ -0,0 +1 @@
+#include "rendez-signal.c"
diff --git a/src/lib9/rendez-pthread.c b/src/lib9/rendez-pthread.c
new file mode 100644
index 00000000..9b5d4342
--- /dev/null
+++ b/src/lib9/rendez-pthread.c
@@ -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;
+}
+
diff --git a/src/lib9/rendez.c b/src/lib9/rendez-signal.c
index 320bd11a..320bd11a 100644
--- a/src/lib9/rendez.c
+++ b/src/lib9/rendez-signal.c
diff --git a/src/libthread/Darwin.c b/src/libthread/Darwin.c
new file mode 100644
index 00000000..fd260957
--- /dev/null
+++ b/src/libthread/Darwin.c
@@ -0,0 +1,5 @@
+int
+_schedfork(Proc *p)
+{
+ return ffork(RFMEM|RFNOWAIT, _schedinit, p);
+}
diff --git a/src/libthread/PowerMacintosh.c b/src/libthread/PowerMacintosh.c
new file mode 100644
index 00000000..ddacea37
--- /dev/null
+++ b/src/libthread/PowerMacintosh.c
@@ -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;
+}
+
diff --git a/src/libthread/asm-Darwin-PowerMacintosh.s b/src/libthread/asm-Darwin-PowerMacintosh.s
new file mode 100644
index 00000000..c503e1d6
--- /dev/null
+++ b/src/libthread/asm-Darwin-PowerMacintosh.s
@@ -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