plan9port/src/libthread/threadimpl.h

242 lines
5.8 KiB
C
Raw Normal View History

2003-09-30 17:47:42 +00:00
/*
* 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; in procs other than p, the
* pointers are only guaranteed to be live while the lock
* is still being held.
2003-09-30 17:47:42 +00:00
*
* 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.
*/
#include <u.h>
2003-09-30 17:47:42 +00:00
#include <assert.h>
#include <libc.h>
2003-09-30 17:47:42 +00:00
#include <thread.h>
#include "label.h"
typedef struct Thread Thread;
typedef struct Proc Proc;
2003-09-30 17:47:42 +00:00
typedef struct Tqueue Tqueue;
typedef struct Pqueue Pqueue;
typedef struct Execargs Execargs;
2004-11-08 16:03:20 +00:00
typedef struct Jmp Jmp;
/* sync with ../lib9/notify.c */
struct Jmp
{
p9jmp_buf b;
};
2003-09-30 17:47:42 +00:00
typedef enum
{
Dead,
Running,
Ready,
Rendezvous,
} State;
typedef enum
{
Channone,
Chanalt,
Chansend,
Chanrecv,
} Chanstate;
enum
{
NPRIV = 8,
};
struct Tqueue /* Thread queue */
{
int asleep;
Thread *head;
Thread *tail;
};
struct Pqueue { /* Proc queue */
Lock lock;
Proc *head;
Proc **tail;
};
2003-09-30 17:47:42 +00:00
struct Thread
{
Lock lock; /* protects thread data structure */
int asleep; /* thread is in _threadsleep */
Label context; /* for context switches */
2003-09-30 17:47:42 +00:00
int grp; /* thread group */
2004-10-22 18:45:08 +00:00
Proc *homeproc; /* ``home'' proc */
int id; /* thread id */
2003-09-30 17:47:42 +00:00
int moribund; /* thread needs to die */
char *name; /* name of thread */
2003-09-30 17:47:42 +00:00
Thread *next; /* next on ready queue */
Thread *nextt; /* next on list of threads in this proc */
2004-10-22 18:45:08 +00:00
Proc *nextproc; /* next proc in which to run (rarely changes) */
State nextstate; /* next run state */
Proc *proc; /* proc of this thread */
2003-09-30 17:47:42 +00:00
Thread *prevt; /* prev on list of threads in this proc */
int ret; /* return value for Exec, Fork */
State state; /* run state */
uchar *stk; /* top of stack (lowest address of stack) */
uint stksize; /* stack size */
void* udata[NPRIV]; /* User per-thread data pointer */
2003-09-30 17:47:42 +00:00
/*
* for debugging only
* (could go away without impacting correct behavior):
*/
2003-09-30 17:47:42 +00:00
Channel *altc;
_Procrend altrend;
2003-09-30 17:47:42 +00:00
Chanstate chan; /* which channel operation is current */
Alt *alt; /* pointer to current alt structure (debugging) */
2004-03-05 01:12:11 +00:00
ulong userpc;
Channel *c;
2003-09-30 17:47:42 +00:00
};
struct Execargs
{
char *prog;
char **args;
int fd[2];
int *stdfd;
2003-09-30 17:47:42 +00:00
};
struct Proc
{
Lock lock;
Label context; /* for context switches */
Proc *link; /* in ptab */
2003-09-30 17:47:42 +00:00
int splhi; /* delay notes */
Thread *thread; /* running thread */
2003-12-06 18:05:27 +00:00
Thread *idle; /* idle thread */
int id;
2004-10-22 18:45:08 +00:00
int procid;
2003-09-30 17:47:42 +00:00
int needexec;
Execargs exec; /* exec argument */
Proc *newproc; /* fork argument */
char exitstr[ERRMAX]; /* exit status */
2004-11-08 16:03:20 +00:00
int internal;
2003-09-30 17:47:42 +00:00
int rforkflag;
int nthreads;
Tqueue threads; /* All threads of this proc */
Tqueue ready; /* Runnable threads */
Lock readylock;
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 */
2004-11-08 16:03:20 +00:00
Jmp sigjmp; /* for notify implementation */
void (*schedfn)(Proc*); /* function to call in scheduler */
_Procrend rend; /* sleep here for more ready threads */
2003-09-30 17:47:42 +00:00
void *arg; /* passed between shared and unshared stk */
char str[ERRMAX]; /* used by threadexits to avoid malloc */
char errbuf[ERRMAX]; /* errstr */
Waitmsg *waitmsg;
2003-09-30 17:47:42 +00:00
void* udata; /* User per-proc data pointer */
2004-05-11 17:51:27 +00:00
int nsched;
2003-09-30 17:47:42 +00:00
/*
* for debugging only
*/
int pid; /* process id */
int pthreadid; /* pthread id */
2003-09-30 17:47:42 +00:00
};
2004-09-21 01:11:28 +00:00
void _swaplabel(Label*, Label*);
Proc* _newproc(void);
int _newthread(Proc*, void(*)(void*), void*, uint, char*, int);
2004-05-11 17:51:27 +00:00
int _sched(void);
2003-09-30 17:47:42 +00:00
int _schedexec(Execargs*);
void _schedexecwait(void);
void _schedexit(Proc*);
int _schedfork(Proc*);
void _threadfree(Thread*);
void _threadscheduler(void*);
2003-09-30 17:47:42 +00:00
void _systhreadinit(void);
void _threadassert(char*);
void __threaddebug(ulong, char*, ...);
#define _threaddebug if(!_threaddebuglevel){}else __threaddebug
void _threadexitsall(char*);
Proc* _threadgetproc(void);
extern void _threadmultiproc(void);
2003-09-30 17:47:42 +00:00
Proc* _threaddelproc(void);
2004-11-08 16:03:20 +00:00
void _kthreadinitproc(Proc*);
2003-09-30 17:47:42 +00:00
void _threadsetproc(Proc*);
void _threadinitstack(Thread*, void(*)(void*), void*);
void _threadlinkmain(void);
2003-09-30 17:47:42 +00:00
void* _threadmalloc(long, int);
void _threadnote(void*, char*);
void _threadready(Thread*);
2004-11-08 16:03:20 +00:00
void _threadschednote(void);
void _threadsetidle(int);
void _threadsleep(_Procrend*);
void _threadwakeup(_Procrend*);
2003-09-30 17:47:42 +00:00
void _threadsignal(void);
void _threadsysfatal(char*, va_list);
long _xdec(long*);
void _xinc(long*);
void _threadremove(Proc*, Thread*);
2004-03-09 12:45:12 +00:00
void threadstatus(void);
2004-10-22 18:45:08 +00:00
void _threadefork(int[3], int[2], char*, char**);
2004-11-08 16:03:20 +00:00
Jmp* _threadgetjmp(void);
void _kthreadinit(void);
void _kthreadsetproc(Proc*);
Proc* _kthreadgetproc(void);
void _kthreadstartproc(Proc*);
void _kthreadexitproc(char*);
void _kthreadexitallproc(char*);
void _threadinternalproc(void);
void _threadbackgroundinit(void);
void _kmaininit(void);
2003-09-30 17:47:42 +00:00
extern int _threadnprocs;
2003-09-30 17:47:42 +00:00
extern int _threaddebuglevel;
extern char* _threadexitsallstatus;
extern Pqueue _threadpq;
extern Channel* _threadwaitchan;
#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)
extern void _threadmemset(void*, int, int);
extern void _threaddebugmemset(void*, int, int);
extern int _threadprocs;
2004-05-11 17:51:27 +00:00
extern void _threadstacklimit(void*, void*);
2004-10-22 18:45:08 +00:00
extern void _procdelthread(Proc*, Thread*);
extern void _procaddthread(Proc*, Thread*);
extern void _threadmaininit(void);
extern int _threadexec(Channel*, int[3], char*, char*[], int);
2004-11-08 16:03:20 +00:00
extern int _kthreadexec(Channel*, int[3], char*, char*[], int);