aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/threadimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libthread/threadimpl.h')
-rw-r--r--src/libthread/threadimpl.h219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
new file mode 100644
index 00000000..24d9b214
--- /dev/null
+++ b/src/libthread/threadimpl.h
@@ -0,0 +1,219 @@
+/*
+ * Some notes on locking:
+ *
+ * All the locking woes come from implementing
+ * threadinterrupt (and threadkill).
+ *
+ * _threadgetproc()->thread is always a live pointer.
+ * p->threads, p->ready, and _threadrgrp also contain
+ * live thread pointers. These may only be consulted
+ * while holding p->lock or _threadrgrp.lock; in procs
+ * other than p, the pointers are only guaranteed to be live
+ * while the lock is still being held.
+ *
+ * Thread structures can only be freed by the proc
+ * they belong to. Threads marked with t->inrendez
+ * need to be extracted from the _threadrgrp before
+ * being freed.
+ *
+ * _threadrgrp.lock cannot be acquired while holding p->lock.
+ */
+
+#include <assert.h>
+#include <lib9.h>
+#include <thread.h>
+#include "label.h"
+
+enum{
+STKSIZE = 16384,
+STKMAGIC = 0xCAFEBEEF
+};
+
+typedef struct Thread Thread;
+typedef struct Proc Proc;
+typedef struct Tqueue Tqueue;
+typedef struct Pqueue Pqueue;
+typedef struct Rgrp Rgrp;
+typedef struct Execargs Execargs;
+
+/* must match list in sched.c */
+typedef enum
+{
+ Dead,
+ Running,
+ Ready,
+ Rendezvous,
+} State;
+
+typedef enum
+{
+ Channone,
+ Chanalt,
+ Chansend,
+ Chanrecv,
+} Chanstate;
+
+enum
+{
+ RENDHASH = 10009,
+ Printsize = 2048,
+ NPRIV = 8,
+};
+
+struct Rgrp
+{
+ Lock lock;
+ Thread *hash[RENDHASH];
+};
+
+struct Tqueue /* Thread queue */
+{
+ int asleep;
+ Thread *head;
+ Thread *tail;
+};
+
+struct Thread
+{
+ Lock lock; /* protects thread data structure */
+ Label sched; /* for context switches */
+ int id; /* thread id */
+ int grp; /* thread group */
+ int moribund; /* thread needs to die */
+ State state; /* run state */
+ State nextstate; /* next run state */
+ uchar *stk; /* top of stack (lowest address of stack) */
+ uint stksize; /* stack size */
+ Thread *next; /* next on ready queue */
+
+ Proc *proc; /* proc of this thread */
+ Thread *nextt; /* next on list of threads in this proc */
+ Thread *prevt; /* prev on list of threads in this proc */
+ int ret; /* return value for Exec, Fork */
+
+ char *cmdname; /* ptr to name of thread */
+
+ int inrendez;
+ Thread *rendhash; /* Trgrp linked list */
+ ulong rendtag; /* rendezvous tag */
+ ulong rendval; /* rendezvous value */
+ int rendbreak; /* rendezvous has been taken */
+
+ Chanstate chan; /* which channel operation is current */
+ Alt *alt; /* pointer to current alt structure (debugging) */
+
+ void* udata[NPRIV]; /* User per-thread data pointer */
+};
+
+struct Execargs
+{
+ char *prog;
+ char **args;
+ int fd[2];
+};
+
+struct Proc
+{
+ Lock lock;
+ Label sched; /* for context switches */
+ Proc *link; /* in proctab */
+ int pid; /* process id */
+ int splhi; /* delay notes */
+ Thread *thread; /* running thread */
+
+ int needexec;
+ Execargs exec; /* exec argument */
+ Proc *newproc; /* fork argument */
+ char exitstr[ERRMAX]; /* exit status */
+
+ int rforkflag;
+ int nthreads;
+ Tqueue threads; /* All threads of this proc */
+ Tqueue ready; /* Runnable threads */
+ Lock readylock;
+
+ char printbuf[Printsize];
+ int blocked; /* In a rendezvous */
+ int pending; /* delayed note pending */
+ int nonotes; /* delay notes */
+ uint nextID; /* ID of most recently created thread */
+ Proc *next; /* linked list of Procs */
+
+ void *arg; /* passed between shared and unshared stk */
+ char str[ERRMAX]; /* used by threadexits to avoid malloc */
+ char errbuf[ERRMAX]; /* errstr */
+
+ void* udata; /* User per-proc data pointer */
+};
+
+struct Pqueue { /* Proc queue */
+ Lock lock;
+ Proc *head;
+ Proc **tail;
+};
+
+struct Ioproc
+{
+ int tid;
+ Channel *c, *creply;
+ int inuse;
+ long (*op)(va_list*);
+ va_list arg;
+ long ret;
+ char err[ERRMAX];
+ Ioproc *next;
+};
+
+void _gotolabel(Label*);
+int _setlabel(Label*);
+void _freeproc(Proc*);
+Proc* _newproc(void(*)(void*), void*, uint, char*, int, int);
+int _procsplhi(void);
+void _procsplx(int);
+void _sched(void);
+int _schedexec(Execargs*);
+void _schedexecwait(void);
+void _schedexit(Proc*);
+int _schedfork(Proc*);
+void _schedinit(void*);
+void _systhreadinit(void);
+void _threadassert(char*);
+void _threadbreakrendez(void);
+void __threaddebug(ulong, char*, ...);
+#define _threaddebug if(!_threaddebuglevel){}else __threaddebug
+void _threadexitsall(char*);
+void _threadflagrendez(Thread*);
+Proc* _threadgetproc(void);
+Proc* _threaddelproc(void);
+void _threadsetproc(Proc*);
+void _threadinitstack(Thread*, void(*)(void*), void*);
+void* _threadmalloc(long, int);
+void _threadnote(void*, char*);
+void _threadready(Thread*);
+ulong _threadrendezvous(ulong, ulong);
+void _threadsignal(void);
+void _threadsysfatal(char*, va_list);
+long _xdec(long*);
+void _xinc(long*);
+void _threadremove(Proc*, Thread*);
+
+extern int _threaddebuglevel;
+extern char* _threadexitsallstatus;
+extern Pqueue _threadpq;
+extern Channel* _threadwaitchan;
+extern Rgrp _threadrgrp;
+extern void _stackfree(void*);
+
+#define DBGAPPL (1 << 0)
+#define DBGSCHED (1 << 16)
+#define DBGCHAN (1 << 17)
+#define DBGREND (1 << 18)
+/* #define DBGKILL (1 << 19) */
+#define DBGNOTE (1 << 20)
+#define DBGEXEC (1 << 21)
+
+#define ioproc_arg(io, type) (va_arg((io)->arg, type))
+extern int _threadgetpid(void);
+extern void _threadmemset(void*, int, int);
+extern void _threaddebugmemset(void*, int, int);
+