- Test m_pkthdr.fw_flags against DUMMYNET_MBUF_TAGGED before trying to locate
[dragonfly/netmp.git] / sys / sys / thread2.h
blobebac5f53ac2001680e8c00f879c41f1173c65109
1 /*
2 * SYS/THREAD2.H
4 * Implements inline procedure support for the LWKT subsystem.
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.
11 * $DragonFly: src/sys/sys/thread2.h,v 1.28 2006/12/23 00:27:03 swildner Exp $
14 #ifndef _SYS_THREAD2_H_
15 #define _SYS_THREAD2_H_
17 #ifndef _KERNEL
19 #error "This file should not be included by userland programs."
21 #else
24 * Userland will have its own globaldata which it includes prior to this.
26 #ifndef _SYS_SYSTM_H_
27 #include <sys/systm.h>
28 #endif
29 #ifndef _SYS_GLOBALDATA_H_
30 #include <sys/globaldata.h>
31 #endif
32 #ifndef _MACHINE_CPUFUNC_H_
33 #include <machine/cpufunc.h>
34 #endif
37 * Critical section debugging
39 #ifdef DEBUG_CRIT_SECTIONS
40 #define __DEBUG_CRIT_ARG__ const char *id
41 #define __DEBUG_CRIT_ADD_ARG__ , const char *id
42 #define __DEBUG_CRIT_PASS_ARG__ , id
43 #define __DEBUG_CRIT_ENTER(td) _debug_crit_enter((td), id)
44 #define __DEBUG_CRIT_EXIT(td) _debug_crit_exit((td), id)
45 #define crit_enter() _crit_enter(__FUNCTION__)
46 #define crit_enter_id(id) _crit_enter(id)
47 #define crit_enter_quick(curtd) _crit_enter_quick((curtd), __FUNCTION__)
48 #define crit_enter_gd(curgd) _crit_enter_gd(curgd, __FUNCTION__)
49 #define crit_exit() _crit_exit(__FUNCTION__)
50 #define crit_exit_id(id) _crit_exit(id)
51 #define crit_exit_quick(curtd) _crit_exit_quick((curtd), __FUNCTION__)
52 #define crit_exit_noyield(curtd) _crit_exit_noyield((curtd),__FUNCTION__)
53 #define crit_exit_gd(curgd) _crit_exit_gd((curgd), __FUNCTION__)
54 #else
55 #define __DEBUG_CRIT_ARG__ void
56 #define __DEBUG_CRIT_ADD_ARG__
57 #define __DEBUG_CRIT_PASS_ARG__
58 #define __DEBUG_CRIT_ENTER(td)
59 #define __DEBUG_CRIT_EXIT(td)
60 #define crit_enter() _crit_enter()
61 #define crit_enter_id(id) _crit_enter()
62 #define crit_enter_quick(curtd) _crit_enter_quick(curtd)
63 #define crit_enter_gd(curgd) _crit_enter_gd(curgd)
64 #define crit_exit() _crit_exit()
65 #define crit_exit_id(id) _crit_exit()
66 #define crit_exit_quick(curtd) _crit_exit_quick(curtd)
67 #define crit_exit_noyield(curtd) _crit_exit_noyield(curtd)
68 #define crit_exit_gd(curgd) _crit_exit_gd(curgd)
69 #endif
72 * Track crit_enter()/crit_exit() pairs and warn on mismatches.
74 #ifdef DEBUG_CRIT_SECTIONS
76 static __inline void
77 _debug_crit_enter(thread_t td, const char *id)
79 int wi = td->td_crit_debug_index;
81 td->td_crit_debug_array[wi & CRIT_DEBUG_ARRAY_MASK] = id;
82 ++td->td_crit_debug_index;
85 static __inline void
86 _debug_crit_exit(thread_t td, const char *id)
88 const char *gid;
89 int wi;
91 wi = td->td_crit_debug_index - 1;
92 if ((gid = td->td_crit_debug_array[wi & CRIT_DEBUG_ARRAY_MASK]) != id) {
93 if (td->td_in_crit_report == 0) {
94 td->td_in_crit_report = 1;
95 kprintf("crit_exit(%s) expected id %s\n", id, gid);
96 td->td_in_crit_report = 0;
99 --td->td_crit_debug_index;
102 #endif
105 * Critical sections prevent preemption by raising a thread's priority
106 * above the highest possible interrupting priority. Additionally, the
107 * current cpu will not be able to schedule a new thread but will instead
108 * place it on a pending list (with interrupts physically disabled) and
109 * set mycpu->gd_reqflags to indicate that work needs to be done, which
110 * lwkt_yield_quick() takes care of.
112 * Some of these routines take a struct thread pointer as an argument. This
113 * pointer MUST be curthread and is only passed as an optimization.
115 * Synchronous switching and blocking is allowed while in a critical section.
118 static __inline void
119 _crit_enter(__DEBUG_CRIT_ARG__)
121 struct thread *td = curthread;
123 #ifdef INVARIANTS
124 if (td->td_pri < 0)
125 crit_panic();
126 #endif
127 td->td_pri += TDPRI_CRIT;
128 __DEBUG_CRIT_ENTER(td);
129 cpu_ccfence();
132 static __inline void
133 _crit_enter_quick(struct thread *curtd __DEBUG_CRIT_ADD_ARG__)
135 curtd->td_pri += TDPRI_CRIT;
136 __DEBUG_CRIT_ENTER(curtd);
137 cpu_ccfence();
140 static __inline void
141 _crit_enter_gd(globaldata_t mygd __DEBUG_CRIT_ADD_ARG__)
143 _crit_enter_quick(mygd->gd_curthread __DEBUG_CRIT_PASS_ARG__);
146 static __inline void
147 _crit_exit_noyield(struct thread *curtd __DEBUG_CRIT_ADD_ARG__)
149 __DEBUG_CRIT_EXIT(curtd);
150 curtd->td_pri -= TDPRI_CRIT;
151 #ifdef INVARIANTS
152 if (curtd->td_pri < 0)
153 crit_panic();
154 #endif
155 cpu_ccfence(); /* prevent compiler reordering */
158 static __inline void
159 _crit_exit(__DEBUG_CRIT_ARG__)
161 thread_t td = curthread;
163 __DEBUG_CRIT_EXIT(td);
164 td->td_pri -= TDPRI_CRIT;
165 #ifdef INVARIANTS
166 if (td->td_pri < 0)
167 crit_panic();
168 #endif
169 cpu_ccfence(); /* prevent compiler reordering */
170 if (td->td_gd->gd_reqflags && td->td_pri < TDPRI_CRIT)
171 lwkt_yield_quick();
174 static __inline void
175 _crit_exit_quick(struct thread *curtd __DEBUG_CRIT_ADD_ARG__)
177 globaldata_t gd = curtd->td_gd;
179 __DEBUG_CRIT_EXIT(curtd);
180 curtd->td_pri -= TDPRI_CRIT;
181 cpu_ccfence(); /* prevent compiler reordering */
182 if (gd->gd_reqflags && curtd->td_pri < TDPRI_CRIT)
183 lwkt_yield_quick();
186 static __inline void
187 _crit_exit_gd(globaldata_t mygd __DEBUG_CRIT_ADD_ARG__)
189 _crit_exit_quick(mygd->gd_curthread __DEBUG_CRIT_PASS_ARG__);
192 static __inline int
193 crit_test(thread_t td)
195 return(td->td_pri >= TDPRI_CRIT);
199 * Initialize a tokref_t. We only need to initialize the token pointer
200 * and the magic number. We do not have to initialize tr_next, tr_gdreqnext,
201 * or tr_reqgd.
203 static __inline void
204 lwkt_tokref_init(lwkt_tokref_t ref, lwkt_token_t tok)
206 ref->tr_tok = tok;
207 ref->tr_state = 0;
211 * Return whether any threads are runnable, whether they meet mp_lock
212 * requirements or not.
214 static __inline int
215 lwkt_runnable(void)
217 return (mycpu->gd_runqmask != 0);
220 static __inline int
221 lwkt_getpri(thread_t td)
223 return(td->td_pri & TDPRI_MASK);
226 static __inline int
227 lwkt_getpri_self(void)
229 return(lwkt_getpri(curthread));
232 #ifdef SMP
235 * IPIQ messaging wrappers. IPIQ remote functions are passed three arguments:
236 * a void * pointer, an integer, and a pointer to the trap frame (or NULL if
237 * the trap frame is not known). However, we wish to provide opaque
238 * interfaces for simpler callbacks... the basic IPI messaging function as
239 * used by the kernel takes a single argument.
241 static __inline int
242 lwkt_send_ipiq(globaldata_t target, ipifunc1_t func, void *arg)
244 return(lwkt_send_ipiq3(target, (ipifunc3_t)func, arg, 0));
247 static __inline int
248 lwkt_send_ipiq2(globaldata_t target, ipifunc2_t func, void *arg1, int arg2)
250 return(lwkt_send_ipiq3(target, (ipifunc3_t)func, arg1, arg2));
253 static __inline int
254 lwkt_send_ipiq_mask(u_int32_t mask, ipifunc1_t func, void *arg)
256 return(lwkt_send_ipiq3_mask(mask, (ipifunc3_t)func, arg, 0));
259 static __inline int
260 lwkt_send_ipiq2_mask(u_int32_t mask, ipifunc2_t func, void *arg1, int arg2)
262 return(lwkt_send_ipiq3_mask(mask, (ipifunc3_t)func, arg1, arg2));
265 static __inline int
266 lwkt_send_ipiq_nowait(globaldata_t target, ipifunc1_t func, void *arg)
268 return(lwkt_send_ipiq3_nowait(target, (ipifunc3_t)func, arg, 0));
271 static __inline int
272 lwkt_send_ipiq2_nowait(globaldata_t target, ipifunc2_t func,
273 void *arg1, int arg2)
275 return(lwkt_send_ipiq3_nowait(target, (ipifunc3_t)func, arg1, arg2));
278 static __inline int
279 lwkt_send_ipiq_passive(globaldata_t target, ipifunc1_t func, void *arg)
281 return(lwkt_send_ipiq3_passive(target, (ipifunc3_t)func, arg, 0));
284 static __inline int
285 lwkt_send_ipiq2_passive(globaldata_t target, ipifunc2_t func,
286 void *arg1, int arg2)
288 return(lwkt_send_ipiq3_passive(target, (ipifunc3_t)func, arg1, arg2));
291 static __inline int
292 lwkt_send_ipiq_bycpu(int dcpu, ipifunc1_t func, void *arg)
294 return(lwkt_send_ipiq3_bycpu(dcpu, (ipifunc3_t)func, arg, 0));
297 static __inline int
298 lwkt_send_ipiq2_bycpu(int dcpu, ipifunc2_t func, void *arg1, int arg2)
300 return(lwkt_send_ipiq3_bycpu(dcpu, (ipifunc3_t)func, arg1, arg2));
303 #endif /* SMP */
304 #endif /* _KERNEL */
305 #endif /* _SYS_THREAD2_H_ */