X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/50b33f0fa41002e8f234c952724f58dc08561fa3..d39d3c43df31677496067ecffd73216c4ee6ad78:/sys/sys/thread.h diff --git a/sys/sys/thread.h b/sys/sys/thread.h index 4971519734..7c65bc4c02 100644 --- a/sys/sys/thread.h +++ b/sys/sys/thread.h @@ -7,7 +7,7 @@ * Types which must already be defined when this header is included by * userland: struct md_thread * - * $DragonFly: src/sys/sys/thread.h,v 1.94 2008/07/01 02:02:55 dillon Exp $ + * $DragonFly: src/sys/sys/thread.h,v 1.97 2008/09/20 04:31:02 sephe Exp $ */ #ifndef _SYS_THREAD_H_ @@ -31,6 +31,9 @@ #ifndef _SYS_SPINLOCK_H_ #include #endif +#ifndef _SYS_IOSCHED_H_ +#include +#endif #ifndef _MACHINE_THREAD_H_ #include #endif @@ -95,40 +98,47 @@ struct intrframe; * Tokens are managed through a helper reference structure, lwkt_tokref, * which is typically declared on the caller's stack. Multiple tokref's * may reference the same token. - * - * It is possible to detect that your token was temporarily lost via - * lwkt_token_is_stale(), which uses the t_lastowner field. This field - * does NOT necessarily represent the current owner and can become stale - * (not point to a valid structure). It is used solely to detect - * whether the token was temporarily lost to another thread. The lost - * state is cleared by the function. */ typedef struct lwkt_token { -#ifdef SMP - struct spinlock t_spinlock; /* Controls access */ -#else - struct spinlock t_unused01; -#endif - struct thread *t_owner; /* The current owner of the token */ - int t_count; /* Per-thread count */ - struct thread *t_lastowner; /* Last owner that acquired token */ + struct lwkt_tokref *t_ref; /* Owning ref or NULL */ + intptr_t t_flags; /* MP lock required */ + long t_collisions; /* Collision counter */ } lwkt_token; -typedef struct lwkt_tokref { - lwkt_token_t tr_tok; /* token in question */ - lwkt_tokref_t tr_next; /* linked list */ - int tr_state; /* 0 = don't have, 1 = have */ -} lwkt_tokref; +#define LWKT_TOKEN_MPSAFE 0x0001 -#define LWKT_TOKREF_INIT(tok) \ - { tok, NULL, 0 } -#define LWKT_TOKREF_DECLARE(name, tok) \ - lwkt_tokref name = LWKT_TOKREF_INIT(tok) +/* + * Static initialization for a lwkt_token. + * UP - Not MPSAFE (full MP lock will also be acquired) + * MP - Is MPSAFE (only the token will be acquired) + */ +#define LWKT_TOKEN_UP_INITIALIZER \ +{ \ + .t_ref = NULL, \ + .t_flags = 0, \ + .t_collisions = 0 \ +} + +#define LWKT_TOKEN_MP_INITIALIZER \ +{ \ + .t_ref = NULL, \ + .t_flags = LWKT_TOKEN_MPSAFE, \ + .t_collisions = 0 \ +} + +#define ASSERT_LWKT_TOKEN_HELD(tok) \ + KKASSERT((tok)->t_ref->tr_owner == curthread) + +struct lwkt_tokref { + lwkt_token_t tr_tok; /* token in question */ + struct thread *tr_owner; /* me */ + intptr_t tr_flags; /* copy of t_flags */ +}; #define MAXCPUFIFO 16 /* power of 2 */ #define MAXCPUFIFO_MASK (MAXCPUFIFO - 1) -#define LWKT_MAXTOKENS 16 /* max tokens beneficially held by thread */ +#define LWKT_MAXTOKENS 32 /* max tokens beneficially held by thread */ /* * Always cast to ipifunc_t when registering an ipi. The actual ipi function @@ -188,6 +198,11 @@ typedef struct lwkt_cpu_msg { * * NOTE: td_pri is bumped by TDPRI_CRIT when entering a critical section, * but this does not effect how the thread is scheduled by LWKT. + * + * NOTE: td_ucred is synchronized from the p_ucred on user->kernel syscall, + * trap, and AST/signal transitions to provide a stable ucred for + * (primarily) system calls. This field will be NULL for pure kernel + * threads. */ struct md_intr_info; struct caps_kinfo; @@ -195,13 +210,14 @@ struct caps_kinfo; struct thread { TAILQ_ENTRY(thread) td_threadq; TAILQ_ENTRY(thread) td_allq; + TAILQ_ENTRY(thread) td_sleepq; lwkt_port td_msgport; /* built-in message port for replies */ struct lwp *td_lwp; /* (optional) associated lwp */ struct proc *td_proc; /* (optional) associated process */ struct pcb *td_pcb; /* points to pcb and top of kstack */ struct globaldata *td_gd; /* associated with this cpu */ const char *td_wmesg; /* string name for blockage */ - void *td_wchan; /* waiting on channel */ + const volatile void *td_wchan; /* waiting on channel */ int td_pri; /* 0-31, 31=highest priority (note 1) */ int td_flags; /* TDF flags */ int td_wdomain; /* domain for wchan address (typ 0) */ @@ -216,6 +232,7 @@ struct thread { __uint64_t td_iticks; /* Statclock hits processing intr (uS) */ int td_locks; /* lockmgr lock debugging */ int td_unused01; + void *td_dsched_priv1; /* priv data for I/O schedulers */ int td_refs; /* hold position in gd_tdallq / hold free */ int td_nest_count; /* prevent splz nesting */ #ifdef SMP @@ -225,11 +242,14 @@ struct thread { int td_mpcount_unused; /* filler so size matches */ int td_cscount_unused; #endif + struct iosched_data td_iosdata; /* Dynamic I/O scheduling data */ struct timeval td_start; /* start time for a thread/process */ char td_comm[MAXCOMLEN+1]; /* typ 16+1 bytes */ struct thread *td_preempted; /* we preempted this thread */ + struct ucred *td_ucred; /* synchronized from p_ucred */ struct caps_kinfo *td_caps; /* list of client and server registrations */ - lwkt_tokref_t td_toks; /* tokens beneficially held */ + lwkt_tokref_t td_toks_stop; + struct lwkt_tokref td_toks_array[LWKT_MAXTOKENS]; #ifdef DEBUG_CRIT_SECTIONS #define CRIT_DEBUG_ARRAY_SIZE 32 #define CRIT_DEBUG_ARRAY_MASK (CRIT_DEBUG_ARRAY_SIZE - 1) @@ -240,6 +260,12 @@ struct thread { struct md_thread td_mach; }; +#define td_toks_base td_toks_array[0] +#define td_toks_end td_toks_array[LWKT_MAXTOKENS] + +#define TD_TOKS_HELD(td) ((td)->td_toks_stop != &(td)->td_toks_base) +#define TD_TOKS_NOT_HELD(td) ((td)->td_toks_stop == &(td)->td_toks_base) + /* * Thread flags. Note that TDF_RUNNING is cleared on the old thread after * we switch to the new one, which is necessary because LWKTs don't need @@ -275,7 +301,7 @@ struct thread { #define TDF_WAKEREQ 0x4000 /* resume_kproc */ #define TDF_TIMEOUT 0x8000 /* tsleep timeout */ #define TDF_INTTHREAD 0x00010000 /* interrupt thread */ -#define TDF_NORESCHED 0x00020000 /* Do not reschedule on wake */ +#define TDF_TSLEEP_DESCHEDULED 0x00020000 /* tsleep core deschedule */ #define TDF_BLOCKED 0x00040000 /* Thread is blocked */ #define TDF_PANICWARN 0x00080000 /* panic warning in switch */ #define TDF_BLOCKQ 0x00100000 /* on block queue */ @@ -283,6 +309,7 @@ struct thread { #define TDF_EXITING 0x00400000 /* thread exiting */ #define TDF_USINGFP 0x00800000 /* thread using fp coproc */ #define TDF_KERNELFP 0x01000000 /* kernel using fp coproc */ +#define TDF_NETWORK 0x02000000 /* network proto thread */ /* * Thread priorities. Typically only one thread from any given @@ -294,6 +321,7 @@ struct thread { * rollup flag will be set in mycpu->gd_reqflags. */ #define TDPRI_IDLE_THREAD 0 /* the idle thread */ +#define TDPRI_IDLE_WORK 1 /* idle work (page zero, etc) */ #define TDPRI_USER_SCHEDULER 2 /* user scheduler helper */ #define TDPRI_USER_IDLE 4 /* user scheduler idle */ #define TDPRI_USER_NORM 6 /* user scheduler normal */ @@ -313,52 +341,68 @@ struct thread { #define TDPRI_MASK 31 #define TDPRI_CRIT 32 /* high bits of td_pri used for crit */ -#ifdef _KERNEL #define LWKT_THREAD_STACK (UPAGES * PAGE_SIZE) -#endif #define CACHE_NTHREADS 6 #define IN_CRITICAL_SECT(td) ((td)->td_pri >= TDPRI_CRIT) +#ifdef _KERNEL + +/* + * Global tokens + */ +extern struct lwkt_token pmap_token; +extern struct lwkt_token dev_token; +extern struct lwkt_token vm_token; +extern struct lwkt_token vmspace_token; +extern struct lwkt_token kvm_token; +extern struct lwkt_token proc_token; +extern struct lwkt_token tty_token; +extern struct lwkt_token vnode_token; + +/* + * Procedures + */ extern void lwkt_init(void); extern struct thread *lwkt_alloc_thread(struct thread *, int, int, int); extern void lwkt_init_thread(struct thread *, void *, int, int, struct globaldata *); -extern void lwkt_set_comm(thread_t, const char *, ...); +extern void lwkt_set_comm(thread_t, const char *, ...) __printflike(2, 3); extern void lwkt_wait_free(struct thread *); extern void lwkt_free_thread(struct thread *); extern void lwkt_gdinit(struct globaldata *); extern void lwkt_switch(void); extern void lwkt_preempt(thread_t, int); extern void lwkt_schedule(thread_t); +extern void lwkt_schedule_noresched(thread_t); extern void lwkt_schedule_self(thread_t); extern void lwkt_deschedule(thread_t); extern void lwkt_deschedule_self(thread_t); extern void lwkt_yield(void); -extern void lwkt_yield_quick(void); +extern void lwkt_user_yield(void); extern void lwkt_token_wait(void); extern void lwkt_hold(thread_t); extern void lwkt_rele(thread_t); +extern void lwkt_passive_release(thread_t); -extern void lwkt_gettoken(lwkt_tokref_t, lwkt_token_t); -extern int lwkt_trytoken(lwkt_tokref_t, lwkt_token_t); -extern void lwkt_gettokref(lwkt_tokref_t); -extern int lwkt_trytokref(lwkt_tokref_t); -extern void lwkt_reltoken(lwkt_tokref_t); +extern void lwkt_gettoken(lwkt_token_t); +extern int lwkt_trytoken(lwkt_token_t); +extern void lwkt_reltoken(lwkt_token_t); extern int lwkt_getalltokens(thread_t); extern void lwkt_relalltokens(thread_t); extern void lwkt_drain_token_requests(void); -extern void lwkt_token_init(lwkt_token_t); +extern void lwkt_token_init(lwkt_token_t, int); extern void lwkt_token_uninit(lwkt_token_t); -extern int lwkt_token_is_stale(lwkt_tokref_t); extern void lwkt_token_pool_init(void); -extern lwkt_token_t lwkt_token_pool_get(void *); +extern lwkt_token_t lwkt_token_pool_lookup(void *); +extern lwkt_token_t lwkt_getpooltoken(void *); extern void lwkt_setpri(thread_t, int); +extern void lwkt_setpri_initial(thread_t, int); extern void lwkt_setpri_self(int); -extern int lwkt_checkpri_self(void); +extern int lwkt_check_resched(thread_t); extern void lwkt_setcpu_self(struct globaldata *); extern void lwkt_migratecpu(int); @@ -376,9 +420,7 @@ extern int lwkt_send_ipiq3_mask(cpumask_t, ipifunc3_t, void *, int); extern void lwkt_wait_ipiq(struct globaldata *, int); extern int lwkt_seq_ipiq(struct globaldata *); extern void lwkt_process_ipiq(void); -#ifdef _KERNEL extern void lwkt_process_ipiq_frame(struct intrframe *); -#endif extern void lwkt_smp_stopped(void); extern void lwkt_synchronize_ipiqs(const char *); @@ -394,10 +436,12 @@ extern void crit_panic(void); extern struct lwp *lwkt_preempted_proc(void); extern int lwkt_create (void (*func)(void *), void *, struct thread **, - struct thread *, int, int, const char *, ...); + struct thread *, int, int, + const char *, ...) __printflike(7, 8); extern void lwkt_exit (void) __dead2; extern void lwkt_remove_tdallq (struct thread *); -extern void lwkt_mp_lock_contested(void); + +#endif #endif