File:  [DragonFly] / src / sys / sys / thread.h
Revision 1.42: download - view: text, annotated - select for diffs
Thu Feb 12 20:43:57 2004 UTC (10 years, 6 months ago) by drhodus
Branches: MAIN
CVS tags: HEAD
*	Update function defines to match up with the work from
	this moring as to fix the kernel build process.

    1: /*
    2:  * SYS/THREAD.H
    3:  *
    4:  *	Implements the architecture independant portion of the LWKT 
    5:  *	subsystem.
    6:  *
    7:  * Types which must already be defined when this header is included by
    8:  * userland:	struct md_thread
    9:  * 
   10:  * $DragonFly: src/sys/sys/thread.h,v 1.42 2004/02/12 20:43:57 drhodus Exp $
   11:  */
   12: 
   13: #ifndef _SYS_THREAD_H_
   14: #define _SYS_THREAD_H_
   15: 
   16: #ifndef _SYS_STDINT_H_
   17: #include <sys/stdint.h>		/* __int types */
   18: #endif
   19: #ifndef _SYS_PARAM_H_
   20: #include <sys/param.h>		/* MAXCOMLEN */
   21: #endif
   22: #ifndef _SYS_QUEUE_H_
   23: #include <sys/queue.h>		/* TAILQ_* macros */
   24: #endif
   25: #ifndef _SYS_MSGPORT_H_
   26: #include <sys/msgport.h>	/* lwkt_port */
   27: #endif
   28: 
   29: struct globaldata;
   30: struct proc;
   31: struct thread;
   32: struct lwkt_queue;
   33: struct lwkt_token;
   34: struct lwkt_wait;
   35: struct lwkt_ipiq;
   36: struct lwkt_cpu_msg;
   37: struct lwkt_cpu_port;
   38: struct lwkt_rwlock;
   39: struct lwkt_msg;
   40: struct lwkt_port;
   41: union sysunion;
   42: 
   43: typedef struct lwkt_queue	*lwkt_queue_t;
   44: typedef struct lwkt_token	*lwkt_token_t;
   45: typedef struct lwkt_wait	*lwkt_wait_t;
   46: typedef struct lwkt_cpu_msg	*lwkt_cpu_msg_t;
   47: typedef struct lwkt_cpu_port	*lwkt_cpu_port_t;
   48: typedef struct lwkt_rwlock	*lwkt_rwlock_t;
   49: typedef struct lwkt_ipiq	*lwkt_ipiq_t;
   50: typedef struct thread 		*thread_t;
   51: 
   52: typedef TAILQ_HEAD(lwkt_queue, thread) lwkt_queue;
   53: 
   54: /*
   55:  * Differentiation between kernel threads and user threads.  Userland
   56:  * programs which want to access to kernel structures have to define
   57:  * _KERNEL_STRUCTURES.  This is a kinda safety valve to prevent badly
   58:  * written user programs from getting an LWKT thread that is neither the
   59:  * kernel nor the user version.
   60:  */
   61: #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
   62: #ifndef _MACHINE_THREAD_H_
   63: #include <machine/thread.h>		/* md_thread */
   64: #endif
   65: #ifndef _MACHINE_FRAME_H_
   66: #include <machine/frame.h>
   67: #endif
   68: #else
   69: struct intrframe;
   70: #endif
   71: 
   72: /*
   73:  * Tokens arbitrate access to information.  They are 'soft' arbitrators
   74:  * in that they are associated with cpus rather then threads, making the
   75:  * optimal aquisition case very fast if your cpu already happens to own the
   76:  * token you are requesting.
   77:  */
   78: typedef struct lwkt_token {
   79:     struct globaldata *t_cpu;	/* the current owner of the token */
   80:     struct globaldata *t_reqcpu;/* return ownership to this cpu on release */
   81:     int		t_gen;		/* generation number */
   82: } lwkt_token;
   83: 
   84: /*
   85:  * Wait structures deal with blocked threads.  Due to the way remote cpus
   86:  * interact with these structures stable storage must be used.
   87:  */
   88: typedef struct lwkt_wait {
   89:     lwkt_queue	wa_waitq;	/* list of waiting threads */
   90:     lwkt_token	wa_token;	/* who currently owns the list */
   91:     int		wa_gen;
   92:     int		wa_count;
   93: } lwkt_wait;
   94: 
   95: #define MAXCPUFIFO      16	/* power of 2 */
   96: #define MAXCPUFIFO_MASK	(MAXCPUFIFO - 1)
   97: 
   98: /*
   99:  * Always cast to ipifunc_t when registering an ipi.  The actual ipi function
  100:  * is called with both the data and an interrupt frame, but the ipi function
  101:  * that is registered might only declare a data argument.
  102:  */
  103: typedef void (*ipifunc_t)(void *arg);
  104: typedef void (*ipifunc2_t)(void *arg, struct intrframe *frame);
  105: 
  106: typedef struct lwkt_ipiq {
  107:     int		ip_rindex;      /* only written by target cpu */
  108:     int		ip_xindex;      /* writte by target, indicates completion */
  109:     int		ip_windex;      /* only written by source cpu */
  110:     ipifunc2_t	ip_func[MAXCPUFIFO];
  111:     void	*ip_arg[MAXCPUFIFO];
  112: } lwkt_ipiq;
  113: 
  114: /*
  115:  * The standard message and queue structure used for communications between
  116:  * cpus.  Messages are typically queued via a machine-specific non-linked
  117:  * FIFO matrix allowing any cpu to send a message to any other cpu without
  118:  * blocking.
  119:  */
  120: typedef struct lwkt_cpu_msg {
  121:     void	(*cm_func)(lwkt_cpu_msg_t msg);	/* primary dispatch function */
  122:     int		cm_code;		/* request code if applicable */
  123:     int		cm_cpu;			/* reply to cpu */
  124:     thread_t	cm_originator;		/* originating thread for wakeup */
  125: } lwkt_cpu_msg;
  126: 
  127: /*
  128:  * reader/writer lock
  129:  */
  130: typedef struct lwkt_rwlock {
  131:     lwkt_wait	rw_wait;
  132:     thread_t	rw_owner;
  133:     int		rw_count;
  134:     int		rw_requests;
  135: } lwkt_rwlock;
  136: 
  137: #define rw_token	rw_wait.wa_token
  138: 
  139: /*
  140:  * Thread structure.  Note that ownership of a thread structure is special
  141:  * cased and there is no 'token'.  A thread is always owned by the cpu
  142:  * represented by td_gd, any manipulation of the thread by some other cpu
  143:  * must be done through cpu_*msg() functions.  e.g. you could request
  144:  * ownership of a thread that way, or hand a thread off to another cpu.
  145:  *
  146:  * NOTE: td_pri is bumped by TDPRI_CRIT when entering a critical section,
  147:  * but this does not effect how the thread is scheduled by LWKT.
  148:  */
  149: struct md_intr_info;
  150: struct caps_kinfo;
  151: 
  152: struct thread {
  153:     TAILQ_ENTRY(thread) td_threadq;
  154:     TAILQ_ENTRY(thread) td_allq;
  155:     lwkt_port	td_msgport;	/* built-in message port for replies */
  156:     struct proc	*td_proc;	/* (optional) associated process */
  157:     struct pcb	*td_pcb;	/* points to pcb and top of kstack */
  158:     struct globaldata *td_gd;	/* associated with this cpu */
  159:     const char	*td_wmesg;	/* string name for blockage */
  160:     void	*td_wchan;	/* waiting on channel */
  161:     int		td_pri;		/* 0-31, 31=highest priority (note 1) */
  162:     int		td_flags;	/* TDF flags */
  163:     int		td_gen;		/* wait queue chasing generation number */
  164: 				/* maybe preempt */
  165:     void	(*td_preemptable)(struct thread *td, int critpri);
  166:     void	(*td_release)(struct thread *td);
  167:     union {
  168: 	struct md_intr_info *intdata;
  169:     } td_info;
  170:     char	*td_kstack;	/* kernel stack */
  171:     char	*td_sp;		/* kernel stack pointer for LWKT restore */
  172:     void	(*td_switch)(struct thread *ntd);
  173:     lwkt_wait_t td_wait;	/* thread sitting on wait structure */
  174:     __uint64_t	td_uticks;	/* Statclock hits in user mode (uS) */
  175:     __uint64_t	td_sticks;      /* Statclock hits in system mode (uS) */
  176:     __uint64_t	td_iticks;	/* Statclock hits processing intr (uS) */
  177:     int		td_locks;	/* lockmgr lock debugging YYY */
  178:     int		td_refs;	/* hold position in gd_tdallq / hold free */
  179:     int		td_nest_count;	/* prevent splz nesting */
  180: #ifdef SMP
  181:     int		td_mpcount;	/* MP lock held (count) */
  182: #else
  183:     int		td_unused001;
  184: #endif
  185:     char	td_comm[MAXCOMLEN+1]; /* typ 16+1 bytes */
  186:     struct thread *td_preempted; /* we preempted this thread */
  187:     struct caps_kinfo *td_caps;	/* list of client and server registrations */
  188:     struct md_thread td_mach;
  189: };
  190: 
  191: /*
  192:  * Thread flags.  Note that TDF_RUNNING is cleared on the old thread after
  193:  * we switch to the new one, which is necessary because LWKTs don't need
  194:  * to hold the BGL.  This flag is used by the exit code and the managed
  195:  * thread migration code.
  196:  *
  197:  * LWKT threads stay on their (per-cpu) run queue while running, not to
  198:  * be confused with user processes which are removed from the user scheduling
  199:  * run queue while actually running.
  200:  */
  201: #define TDF_RUNNING		0x0001	/* thread still active */
  202: #define TDF_RUNQ		0x0002	/* on an LWKT run queue */
  203: #define TDF_PREEMPT_LOCK	0x0004	/* I have been preempted */
  204: #define TDF_PREEMPT_DONE	0x0008	/* acknowledge preemption complete */
  205: #define TDF_IDLE_NOHLT		0x0010	/* we need to spin */
  206: 
  207: #define TDF_SYSTHREAD		0x0100	/* system thread */
  208: #define TDF_ALLOCATED_THREAD	0x0200	/* zalloc allocated thread */
  209: #define TDF_ALLOCATED_STACK	0x0400	/* zalloc allocated stack */
  210: #define TDF_VERBOSE		0x0800	/* verbose on exit */
  211: #define TDF_DEADLKTREAT		0x1000	/* special lockmgr deadlock treatment */
  212: #define TDF_STOPREQ		0x2000	/* suspend_kproc */
  213: #define TDF_WAKEREQ		0x4000	/* resume_kproc */
  214: #define TDF_TIMEOUT		0x8000	/* tsleep timeout */
  215: #define TDF_INTTHREAD		0x00010000	/* interrupt thread */
  216: 
  217: /*
  218:  * Thread priorities.  Typically only one thread from any given
  219:  * user process scheduling queue is on the LWKT run queue at a time.
  220:  * Remember that there is one LWKT run queue per cpu.
  221:  *
  222:  * Critical sections are handled by bumping td_pri above TDPRI_MAX, which
  223:  * causes interrupts to be masked as they occur.  When this occurs a
  224:  * rollup flag will be set in mycpu->gd_reqflags.
  225:  */
  226: #define TDPRI_IDLE_THREAD	0	/* the idle thread */
  227: #define TDPRI_USER_IDLE		4	/* user scheduler idle */
  228: #define TDPRI_USER_NORM		6	/* user scheduler normal */
  229: #define TDPRI_USER_REAL		8	/* user scheduler real time */
  230: #define TDPRI_KERN_LPSCHED	9	/* scheduler helper for userland sch */
  231: #define TDPRI_KERN_USER		10	/* kernel / block in syscall */
  232: #define TDPRI_KERN_DAEMON	12	/* kernel daemon (pageout, etc) */
  233: #define TDPRI_SOFT_NORM		14	/* kernel / normal */
  234: #define TDPRI_SOFT_TIMER	16	/* kernel / timer */
  235: #define TDPRI_EXITING		19	/* exiting thread */
  236: #define TDPRI_INT_SUPPORT	20	/* kernel / high priority support */
  237: #define TDPRI_INT_LOW		27	/* low priority interrupt */
  238: #define TDPRI_INT_MED		28	/* medium priority interrupt */
  239: #define TDPRI_INT_HIGH		29	/* high priority interrupt */
  240: #define TDPRI_MAX		31
  241: 
  242: #define TDPRI_MASK		31
  243: #define TDPRI_CRIT		32	/* high bits of td_pri used for crit */
  244: 
  245: #define CACHE_NTHREADS		6
  246: 
  247: #define IN_CRITICAL_SECT(td)	((td)->td_pri >= TDPRI_CRIT)
  248: 
  249: #ifdef _KERNEL
  250: 
  251: extern struct vm_zone	*thread_zone;
  252: 
  253: #endif
  254: 
  255: /*
  256:  * Applies both to the kernel and to liblwkt.
  257:  */
  258: extern struct thread *lwkt_alloc_thread(struct thread *template, int cpu);
  259: extern void lwkt_init_thread(struct thread *td, void *stack, int flags,
  260: 	struct globaldata *gd);
  261: extern void lwkt_set_comm(thread_t td, const char *ctl, ...);
  262: extern void lwkt_wait_free(struct thread *td);
  263: extern void lwkt_free_thread(struct thread *td);
  264: extern void lwkt_init_wait(struct lwkt_wait *w);
  265: extern void lwkt_gdinit(struct globaldata *gd);
  266: extern void lwkt_switch(void);
  267: extern void lwkt_maybe_switch(void);
  268: extern void lwkt_preempt(thread_t ntd, int critpri);
  269: extern void lwkt_schedule(thread_t td);
  270: extern void lwkt_schedule_self(void);
  271: extern void lwkt_deschedule(thread_t td);
  272: extern void lwkt_deschedule_self(void);
  273: extern void lwkt_acquire(thread_t td);
  274: extern void lwkt_yield(void);
  275: extern void lwkt_yield_quick(void);
  276: extern void lwkt_hold(thread_t td);
  277: extern void lwkt_rele(thread_t td);
  278: 
  279: extern void lwkt_block(lwkt_wait_t w, const char *wmesg, int *gen);
  280: extern void lwkt_signal(lwkt_wait_t w, int count);
  281: extern int lwkt_trytoken(lwkt_token_t tok);
  282: extern int lwkt_gettoken(lwkt_token_t tok);
  283: extern int lwkt_gentoken(lwkt_token_t tok, int *gen);
  284: extern int lwkt_reltoken(lwkt_token_t tok);
  285: extern void lwkt_inittoken(lwkt_token_t tok);
  286: extern int  lwkt_regettoken(lwkt_token_t tok);
  287: extern void lwkt_rwlock_init(lwkt_rwlock_t lock);
  288: extern void lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg);
  289: extern void lwkt_shlock(lwkt_rwlock_t lock, const char *wmesg);
  290: extern void lwkt_exunlock(lwkt_rwlock_t lock);
  291: extern void lwkt_shunlock(lwkt_rwlock_t lock);
  292: extern void lwkt_setpri(thread_t td, int pri);
  293: extern void lwkt_setpri_self(int pri);
  294: extern int  lwkt_send_ipiq(struct globaldata *targ, ipifunc_t func, void *arg);
  295: extern int  lwkt_send_ipq_bycpu(int dcpu, ipifunc_t func, void *arg);
  296: extern void lwkt_send_ipiq_mask(uint32_t mask, ipifunc_t func, void *arg);
  297: extern void lwkt_wait_ipiq(struct globaldata *targ, int seq);
  298: extern void lwkt_process_ipiq(void);
  299: #ifdef _KERNEL
  300: extern void lwkt_process_ipiq_frame(struct intrframe frame);
  301: #endif
  302: extern void crit_panic(void);
  303: extern struct proc *lwkt_preempted_proc(void);
  304: 
  305: extern int  lwkt_create (void (*func)(void *), void *arg, struct thread **ptd,
  306: 			    struct thread *template, int tdflags, int cpu,
  307: 			    const char *ctl, ...);
  308: extern void lwkt_exit (void) __dead2;
  309: 
  310: #endif
  311: