123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /*
- * 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.
- */
- typedef struct Pqueue Pqueue;
- typedef struct Rgrp Rgrp;
- typedef struct Tqueue Tqueue;
- typedef struct Thread Thread;
- typedef struct Execargs Execargs;
- typedef struct Proc Proc;
- /* must match list in sched.c */
- typedef enum
- {
- Dead,
- Running,
- Ready,
- Rendezvous,
- } State;
-
- typedef enum
- {
- Channone,
- Chanalt,
- Chansend,
- Chanrecv,
- } Chanstate;
- enum
- {
- RENDHASH = 13,
- 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 */
- jmp_buf 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 */
- unsigned char *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*/
- int ret; /* return value for Exec, Fork */
- char *cmdname; /* ptr to name of thread */
- int inrendez;
- Thread *rendhash; /* Trgrp linked list */
- void* rendtag; /* rendezvous tag */
- void* 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;
- jmp_buf sched; /* for context switches */
- 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 */
- void* wdata; /* Lib(worker) per-proc data pointer */
- void* udata; /* User per-proc data pointer */
- char threadint; /* tag for threadexitsall() */
- };
- struct Pqueue { /* Proc queue */
- Lock lock;
- Proc *head;
- Proc **tail;
- };
- struct Ioproc
- {
- int tid;
- Channel *c, *creply;
- int inuse;
- int32_t (*op)(va_list*);
- va_list arg;
- long ret;
- char err[ERRMAX];
- Ioproc *next;
- };
- void _freeproc(Proc*);
- void _freethread(Thread*);
- 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(uint32_t, char*, ...);
- void _threadexitsall(char*);
- void _threadflagrendez(Thread*);
- Proc* _threadgetproc(void);
- void _threadsetproc(Proc*);
- void _threadinitstack(Thread*, void(*)(void*), void*);
- void* _threadmalloc(int32_t, int);
- void _threadnote(void*, char*);
- void _threadready(Thread*);
- void* _threadrendezvous(void*, void*);
- void _threadsignal(void);
- void _threadsysfatal(char*, ...);
- void** _workerdata(void);
- void _xinc(int32_t*);
- long _xdec(int32_t*);
- extern int _threaddebuglevel;
- extern char* _threadexitsallstatus;
- extern Pqueue _threadpq;
- extern Channel* _threadwaitchan;
- extern Rgrp _threadrgrp;
- #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))
|