aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libc.h126
-rw-r--r--include/thread.h250
2 files changed, 189 insertions, 187 deletions
diff --git a/include/libc.h b/include/libc.h
index c4c40e46..ff6fd4bc 100644
--- a/include/libc.h
+++ b/include/libc.h
@@ -423,79 +423,74 @@ extern void needstack(int);
#endif
/*
+ * just enough information so that libc can be
+ * properly locked without dragging in all of libthread
+ */
+typedef struct _Thread _Thread;
+typedef struct _Threadlist _Threadlist;
+struct _Threadlist
+{
+ _Thread *head;
+ _Thread *tail;
+};
+
+extern _Thread *(*threadnow)(void);
+
+/*
* synchronization
*/
typedef struct Lock Lock;
struct Lock
{
-#ifdef PLAN9_PTHREADS
+#ifdef PLAN9PORT_USING_PTHREADS
int init;
pthread_mutex_t mutex;
-#else
- int val;
#endif
+ int held;
};
-extern int _tas(int*);
extern void lock(Lock*);
extern void unlock(Lock*);
extern int canlock(Lock*);
+extern int (*_lock)(Lock*, int, ulong);
+extern void (*_unlock)(Lock*, ulong);
-/*
- * Used to implement process sleep and wakeup,
- * either in terms of pthreads or our own primitives.
- * This will be more portable than writing our own
- * per-system implementations, and on some systems
- * non-pthreads threading implementations break libc
- * (cough, Linux, cough).
- */
-typedef struct _Procrend _Procrend;
-struct _Procrend
+typedef struct QLock QLock;
+struct QLock
{
- int asleep;
- Lock *l;
- void *arg;
- int pid;
-#ifdef PLAN9_PTHREADS
- pthread_cond_t cond;
-#endif
+ Lock l;
+ _Thread *owner;
+ _Threadlist waiting;
};
-extern void _procsleep(_Procrend*);
-extern void _procwakeup(_Procrend*);
+extern void qlock(QLock*);
+extern void qunlock(QLock*);
+extern int canqlock(QLock*);
+extern int (*_qlock)(QLock*, int, ulong); /* do not use */
+extern void (*_qunlock)(QLock*, ulong);
-typedef struct QLp QLp;
-struct QLp
+typedef struct Rendez Rendez;
+struct Rendez
{
- Lock inuse;
- QLp *next;
- _Procrend rend;
- char state;
+ QLock *l;
+ _Threadlist waiting;
};
-typedef
-struct QLock
-{
- Lock lock;
- int locked;
- QLp *head;
- QLp *tail;
-} QLock;
-
-extern void qlock(QLock*);
-extern void qunlock(QLock*);
-extern int canqlock(QLock*);
-extern void _qlockinit(void(*)(_Procrend*), void(*)(_Procrend*)); /* called only by the thread library */
+extern void rsleep(Rendez*); /* unlocks r->l, sleeps, locks r->l again */
+extern int rwakeup(Rendez*);
+extern int rwakeupall(Rendez*);
+extern void (*_rsleep)(Rendez*, ulong); /* do not use */
+extern int (*_rwakeup)(Rendez*, int, ulong);
-typedef
+typedef struct RWLock RWLock;
struct RWLock
{
- Lock lock;
- int readers; /* number of readers */
- int writer; /* number of writers */
- QLp *head; /* list of waiting processes */
- QLp *tail;
-} RWLock;
+ Lock l;
+ int readers;
+ _Thread *writer;
+ _Threadlist rwaiting;
+ _Threadlist wwaiting;
+};
extern void rlock(RWLock*);
extern void runlock(RWLock*);
@@ -503,18 +498,14 @@ extern int canrlock(RWLock*);
extern void wlock(RWLock*);
extern void wunlock(RWLock*);
extern int canwlock(RWLock*);
+extern int (*_rlock)(RWLock*, int, ulong); /* do not use */
+extern int (*_wlock)(RWLock*, int, ulong);
+extern void (*_runlock)(RWLock*, ulong);
+extern void (*_wunlock)(RWLock*, ulong);
-typedef
-struct Rendez
-{
- QLock *l;
- QLp *head;
- QLp *tail;
-} Rendez;
-
-extern void rsleep(Rendez*); /* unlocks r->l, sleeps, locks r->l again */
-extern int rwakeup(Rendez*);
-extern int rwakeupall(Rendez*);
+/*
+ * per-process private data
+ */
extern void** privalloc(void);
extern void privfree(void**);
@@ -589,7 +580,7 @@ extern void freenetconninfo(NetConnInfo*);
#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
#define OCEXEC 32 /* or'ed in, close on exec */
#define ORCLOSE 64 /* or'ed in, remove on close */
-#define ODIRECT 128 /* or'ed in, bypass the cache */
+#define ODIRECT 128 /* or'ed in, direct access */
#define OEXCL 0x1000 /* or'ed in, exclusive use (create only) */
#define OLOCK 0x2000 /* or'ed in, lock after opening */
@@ -724,6 +715,10 @@ extern int unmount(char*, char*);
*/
extern int noted(int);
extern int notify(void(*)(void*, char*));
+extern void notifyenable(char*);
+extern void notifydisable(char*);
+extern void notifyon(char*);
+extern void notifyoff(char*);
extern int p9open(char*, int);
extern int fd2path(int, char*, int);
extern int p9pipe(int*);
@@ -772,6 +767,7 @@ extern ulong rendezvous(ulong, ulong);
#define rfork p9rfork
/* #define access p9access */
#define create p9create
+#undef open
#define open p9open
#define pipe p9pipe
#endif
@@ -801,8 +797,14 @@ extern int post9pservice(int, char*);
#endif
/* compiler directives on plan 9 */
-#define USED(x) if(x){}else{}
#define SET(x) ((x)=0)
+#define USED(x) if(x){}else{}
+#ifdef __GNUC__
+# if __GNUC__ >= 3
+# undef USED
+# define USED(x) { ulong __y __attribute__ ((unused)); __y = (ulong)(x); }
+# endif
+#endif
/* command line */
extern char *argv0;
diff --git a/include/thread.h b/include/thread.h
index f2a12599..8dbabe61 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -4,150 +4,150 @@
extern "C" {
#endif
-/* avoid conflicts with socket library */
-#undef send
-#define send _threadsend
-#undef recv
-#define recv _threadrecv
-
-typedef struct Alt Alt;
-typedef struct Channel Channel;
-typedef struct Ref Ref;
-
-/* Channel structure. S is the size of the buffer. For unbuffered channels
- * s is zero. v is an array of s values. If s is zero, v is unused.
- * f and n represent the state of the queue pointed to by v.
+/*
+ * basic procs and threads
*/
+int proccreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
+int threadcreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
+void threadexits(char *);
+void threadexitsall(char *);
+void threadsetname(char*, ...);
+void threadsetstate(char*, ...);
+void _threadready(_Thread*);
+void _threadswitch(void);
+void _threadsetsysproc(void);
+void _threadsleep(Rendez*);
+_Thread *_threadwakeup(Rendez*);
+
+/*
+ * per proc and thread data
+ */
+void **procdata(void);
-enum {
- Nqwds = 2,
- Nqshift = 5, // 2log #of bits in long
- Nqmask = - 1,
- Nqbits = (1 << Nqshift) * 2,
-};
-
-struct Channel {
- int s; // Size of the channel (may be zero)
- unsigned int f; // Extraction point (insertion pt: (f + n) % s)
- unsigned int n; // Number of values in the channel
- int e; // Element size
- int freed; // Set when channel is being deleted
- volatile Alt **qentry; // Receivers/senders waiting (malloc)
- volatile int nentry; // # of entries malloc-ed
- unsigned char v[1]; // Array of s values in the channel
-};
+/*
+ * supplied by user instead of main.
+ * mainstacksize is size of stack allocated to run threadmain
+ */
+void threadmain(int argc, char *argv[]);
+extern int mainstacksize;
+/*
+ * channel communication
+ */
+typedef struct Alt Alt;
+typedef struct _Altarray _Altarray;
+typedef struct Channel Channel;
-/* Channel operations for alt: */
-typedef enum {
+enum
+{
CHANEND,
CHANSND,
CHANRCV,
CHANNOP,
CHANNOBLK,
-} ChanOp;
-
-struct Alt {
- Channel *c; /* channel */
- void *v; /* pointer to value */
- ChanOp op; /* operation */
-
- /* the next variables are used internally to alt
- * they need not be initialized
- */
- struct Thread *thread; /* thread waiting on this alt */
- int entryno; /* entry number */
};
-struct Ref {
- Lock lk;
- long ref;
+struct Alt
+{
+ void *v;
+ Channel *c;
+ uint op;
+ _Thread *thread;
+ Alt *xalt;
};
-int alt(Alt alts[]);
-Channel* chancreate(int elemsize, int bufsize);
-int chaninit(Channel *c, int elemsize, int elemcnt);
-void chanfree(Channel *c);
-int chanprint(Channel *, char *, ...);
-long decref(Ref *r); /* returns 0 iff value is now zero */
-void incref(Ref *r);
-int nbrecv(Channel *c, void *v);
-void* nbrecvp(Channel *c);
-unsigned long nbrecvul(Channel *c);
-int nbsend(Channel *c, void *v);
-int nbsendp(Channel *c, void *v);
-int nbsendul(Channel *c, unsigned long v);
-int proccreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
-int procrfork(void (*f)(void *arg), void *arg, unsigned int stacksize, int flag);
-void** procdata(void);
-void threadexec(Channel *, int[3], char *, char *[]);
-void threadexecl(Channel *, int[3], char *, ...);
-int threadspawn(int[3], char*, char*[]);
-int recv(Channel *c, void *v);
-void* recvp(Channel *c);
-unsigned long recvul(Channel *c);
-int send(Channel *c, void *v);
-int sendp(Channel *c, void *v);
-int sendul(Channel *c, unsigned long v);
-int threadcreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
-int threadcreateidle(void (*f)(void*), void*, unsigned int);
-void** threaddata(void);
-void threadexits(char *);
-void threadexitsall(char *);
-void threadfdwait(int, int);
-void threadfdwaitsetup(void);
-int threadgetgrp(void); /* return thread group of current thread */
-char* threadgetname(void);
-void threadint(int); /* interrupt thread */
-void threadintgrp(int); /* interrupt threads in grp */
-void threadkill(int); /* kill thread */
-void threadkillgrp(int); /* kill threads in group */
-void threadmain(int argc, char *argv[]);
-void threadfdnoblock(int);
-void threadnonotes(void);
-int threadnotify(int (*f)(void*, char*), int in);
-int threadid(void);
-int threadpid(int);
-long threadread(int, void*, long);
-long threadreadn(int, void*, long);
-int threadread9pmsg(int, void*, uint);
-int threadrecvfd(int);
-long threadwrite(int, const void*, long);
-int threadsendfd(int, int);
-int threadsetgrp(int); /* set thread group, return old */
-void threadsetname(char *fmt, ...);
-void threadsleep(int);
-Channel* threadwaitchan(void);
-int threadannounce(char*, char*);
-int threadlisten(char*, char*);
-int threadaccept(int, char*);
-
-int tprivalloc(void);
-void tprivfree(int);
-void **tprivaddr(int);
-int yield(void);
+struct _Altarray
+{
+ Alt **a;
+ uint n;
+ uint m;
+};
-long threadstack(void);
+struct Channel
+{
+ uint bufsize;
+ uint elemsize;
+ uchar *buf;
+ uint nbuf;
+ uint off;
+ _Altarray asend;
+ _Altarray arecv;
+ char *name;
+};
-extern int mainstacksize;
+/* [Edit .+1,./^$/ |cfn -h $PLAN9/src/libthread/channel.c] */
+int chanalt(Alt *alts);
+Channel* chancreate(int elemsize, int elemcnt);
+void chanfree(Channel *c);
+int chaninit(Channel *c, int elemsize, int elemcnt);
+int channbrecv(Channel *c, void *v);
+void* channbrecvp(Channel *c);
+ulong channbrecvul(Channel *c);
+int channbsend(Channel *c, void *v);
+int channbsendp(Channel *c, void *v);
+int channbsendul(Channel *c, ulong v);
+int chanrecv(Channel *c, void *v);
+void* chanrecvp(Channel *c);
+ulong chanrecvul(Channel *c);
+int chansend(Channel *c, void *v);
+int chansendp(Channel *c, void *v);
+int chansendul(Channel *c, ulong v);
+
+#define alt chanalt
+#define nbrecv channbrecv
+#define nbrecvp channbrecvp
+#define nvrecvul channbrecvul
+#define nbsend channbsend
+#define nbsendp channbsendp
+#define nbsendul channbsendul
+#define recv chanrecv
+#define recvp chanrecvp
+#define recvul chanrecvul
+#define send chansend
+#define sendp chansendp
+#define sendul chansendul
+
+/*
+ * reference counts
+ */
+typedef struct Ref Ref;
-/* slave I/O processes */
-typedef struct Ioproc Ioproc;
+struct Ref {
+ Lock lock;
+ long ref;
+};
-Ioproc* ioproc(void);
-void closeioproc(Ioproc*);
-void iointerrupt(Ioproc*);
+long decref(Ref *r);
+long incref(Ref *r);
-int ioclose(Ioproc*, int);
-int iodial(Ioproc*, char*, char*, char*, int*);
-int ioopen(Ioproc*, char*, int);
-long ioread(Ioproc*, int, void*, long);
-long ioreadn(Ioproc*, int, void*, long);
-long iowrite(Ioproc*, int, void*, long);
-int iosleep(Ioproc*, long);
+/*
+ * slave i/o processes
+ */
+typedef struct Ioproc Ioproc;
-long iocall(Ioproc*, long (*)(va_list*), ...);
-void ioret(Ioproc*, int);
+/* [Edit .+1,/^$/ |cfn -h $PLAN9/src/libthread/io*.c] */
+void closeioproc(Ioproc *io);
+long iocall(Ioproc *io, long (*op)(va_list*), ...);
+int ioclose(Ioproc *io, int fd);
+int iodial(Ioproc *io, char *addr, char *local, char *dir, int *cdfp);
+void iointerrupt(Ioproc *io);
+int ioopen(Ioproc *io, char *path, int mode);
+Ioproc* ioproc(void);
+long ioread(Ioproc *io, int fd, void *a, long n);
+int ioread9pmsg(Ioproc*, int, void*, int);
+long ioreadn(Ioproc *io, int fd, void *a, long n);
+int iorecvfd(Ioproc *, int);
+int iosendfd(Ioproc*, int, int);
+int iosleep(Ioproc *io, long n);
+long iowrite(Ioproc *io, int fd, void *a, long n);
+
+/*
+ * exec external programs
+ */
+void threadexec(Channel*, int[3], char*, char *[]);
+void threadexecl(Channel*, int[3], char*, ...);
+int threadspawn(int[3], char*, char*[]);
+Channel* threadwaitchan(void);
#if defined(__cplusplus)
}