Do some minor critical path performance improvements in the scheduler
[dragonfly.git] / sys / sys / thread2.h
1 /*
2  * SYS/THREAD2.H
3  *
4  *      Implements inline procedure support for the LWKT subsystem. 
5  *
6  *      Generally speaking these routines only operate on threads associated
7  *      with the current cpu.  For example, a higher priority thread pending
8  *      on a different cpu will not be immediately scheduled by a yield() on
9  *      this cpu.
10  *
11  * $DragonFly: src/sys/sys/thread2.h,v 1.14 2004/04/10 20:55:24 dillon Exp $
12  */
13
14 #ifndef _SYS_THREAD2_H_
15 #define _SYS_THREAD2_H_
16
17 /*
18  * Userland will have its own globaldata which it includes prior to this.
19  */
20 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
21 #ifndef _SYS_GLOBALDATA_H_
22 #include <sys/globaldata.h>
23 #endif
24 #endif
25
26 /*
27  * Critical sections prevent preemption by raising a thread's priority
28  * above the highest possible interrupting priority.  Additionally, the
29  * current cpu will not be able to schedule a new thread but will instead
30  * place it on a pending list (with interrupts physically disabled) and
31  * set mycpu->gd_reqflags to indicate that work needs to be done, which
32  * lwkt_yield_quick() takes care of.
33  *
34  * Some of these routines take a struct thread pointer as an argument.  This
35  * pointer MUST be curthread and is only passed as an optimization.
36  *
37  * Synchronous switching and blocking is allowed while in a critical section.
38  */
39
40 static __inline void
41 crit_enter(void)
42 {
43     struct thread *td = curthread;
44
45     td->td_pri += TDPRI_CRIT;
46 #ifdef INVARIANTS
47     if (td->td_pri < 0)
48         crit_panic();
49 #endif
50 }
51
52 static __inline void
53 crit_enter_quick(struct thread *curtd)
54 {
55     curtd->td_pri += TDPRI_CRIT;
56 }
57
58 static __inline void
59 crit_enter_gd(globaldata_t mygd)
60 {
61     crit_enter_quick(mygd->gd_curthread);
62 }
63
64 static __inline void
65 crit_exit_noyield(struct thread *curtd)
66 {
67     curtd->td_pri -= TDPRI_CRIT;
68 #ifdef INVARIANTS
69     if (curtd->td_pri < 0)
70         crit_panic();
71 #endif
72 }
73
74 static __inline void
75 crit_exit(void)
76 {
77     thread_t td = curthread;
78
79     td->td_pri -= TDPRI_CRIT;
80 #ifdef INVARIANTS
81     if (td->td_pri < 0)
82         crit_panic();
83 #endif
84     if (td->td_pri < TDPRI_CRIT && td->td_gd->gd_reqflags)
85         lwkt_yield_quick();
86 }
87
88 static __inline void
89 crit_exit_quick(struct thread *curtd)
90 {
91     curtd->td_pri -= TDPRI_CRIT;
92     if (curtd->td_pri < TDPRI_CRIT && curtd->td_gd->gd_reqflags)
93         lwkt_yield_quick();
94 }
95
96 static __inline void
97 crit_exit_gd(globaldata_t mygd)
98 {
99     crit_exit_quick(mygd->gd_curthread);
100 }
101
102 static __inline int
103 crit_panic_save(void)
104 {
105     thread_t td = curthread;
106     int pri = td->td_pri;
107     td->td_pri = td->td_pri & TDPRI_MASK;
108     return(pri);
109 }
110
111 static __inline void
112 crit_panic_restore(int cpri)
113 {
114     curthread->td_pri = cpri;
115 }
116
117 /*
118  * Initialize a tokref_t.  We only need to initialize the token pointer
119  * and the magic number.  We do not have to initialize tr_next, tr_gdreqnext,
120  * or tr_reqgd.
121  */
122 static __inline void
123 lwkt_tokref_init(lwkt_tokref_t ref, lwkt_token_t tok)
124 {
125     ref->tr_magic = LWKT_TOKREF_MAGIC1;
126     ref->tr_tok = tok;
127 }
128
129 /*
130  * Return whether any threads are runnable, whether they meet mp_lock
131  * requirements or not.
132  */
133 static __inline int
134 lwkt_runnable(void)
135 {
136     return (mycpu->gd_runqmask != 0);
137 }
138
139 #endif
140