Merge from vendor branch OPENPAM:
[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.21 2005/07/07 20:28:26 hmp 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 #ifndef _MACHINE_CPUFUNC_H_
25 #include <machine/cpufunc.h>
26 #endif
27 #endif
28
29 /*
30  * Critical sections prevent preemption by raising a thread's priority
31  * above the highest possible interrupting priority.  Additionally, the
32  * current cpu will not be able to schedule a new thread but will instead
33  * place it on a pending list (with interrupts physically disabled) and
34  * set mycpu->gd_reqflags to indicate that work needs to be done, which
35  * lwkt_yield_quick() takes care of.
36  *
37  * Some of these routines take a struct thread pointer as an argument.  This
38  * pointer MUST be curthread and is only passed as an optimization.
39  *
40  * Synchronous switching and blocking is allowed while in a critical section.
41  */
42
43 static __inline void
44 crit_enter(void)
45 {
46     struct thread *td = curthread;
47
48     td->td_pri += TDPRI_CRIT;
49 #ifdef INVARIANTS
50     if (td->td_pri < 0)
51         crit_panic();
52 #endif
53     cpu_ccfence();
54 }
55
56 static __inline void
57 crit_enter_quick(struct thread *curtd)
58 {
59     curtd->td_pri += TDPRI_CRIT;
60     cpu_ccfence();
61 }
62
63 static __inline void
64 crit_enter_gd(globaldata_t mygd)
65 {
66     crit_enter_quick(mygd->gd_curthread);
67 }
68
69 static __inline void
70 crit_exit_noyield(struct thread *curtd)
71 {
72     curtd->td_pri -= TDPRI_CRIT;
73 #ifdef INVARIANTS
74     if (curtd->td_pri < 0)
75         crit_panic();
76 #endif
77     cpu_ccfence();      /* prevent compiler reordering */
78 }
79
80 static __inline void
81 crit_exit(void)
82 {
83     thread_t td = curthread;
84
85     td->td_pri -= TDPRI_CRIT;
86 #ifdef INVARIANTS
87     if (td->td_pri < 0)
88         crit_panic();
89 #endif
90     cpu_ccfence();      /* prevent compiler reordering */
91     if (td->td_gd->gd_reqflags && td->td_pri < TDPRI_CRIT)
92         lwkt_yield_quick();
93 }
94
95 static __inline void
96 crit_exit_quick(struct thread *curtd)
97 {
98     globaldata_t gd = curtd->td_gd;
99
100     curtd->td_pri -= TDPRI_CRIT;
101     cpu_ccfence();      /* prevent compiler reordering */
102     if (gd->gd_reqflags && curtd->td_pri < TDPRI_CRIT)
103         lwkt_yield_quick();
104 }
105
106 static __inline void
107 crit_exit_gd(globaldata_t mygd)
108 {
109     crit_exit_quick(mygd->gd_curthread);
110 }
111
112 static __inline int
113 crit_test(thread_t td)
114 {
115     return(td->td_pri >= TDPRI_CRIT);
116 }
117
118 /*
119  * Initialize a tokref_t.  We only need to initialize the token pointer
120  * and the magic number.  We do not have to initialize tr_next, tr_gdreqnext,
121  * or tr_reqgd.
122  */
123 static __inline void
124 lwkt_tokref_init(lwkt_tokref_t ref, lwkt_token_t tok)
125 {
126     ref->tr_magic = LWKT_TOKREF_MAGIC1;
127     ref->tr_tok = tok;
128     ref->tr_flags = 0;
129 }
130
131 /*
132  * Return whether any threads are runnable, whether they meet mp_lock
133  * requirements or not.
134  */
135 static __inline int
136 lwkt_runnable(void)
137 {
138     return (mycpu->gd_runqmask != 0);
139 }
140
141 static __inline int
142 lwkt_getpri(thread_t td)
143 {
144     return(td->td_pri & TDPRI_MASK);
145 }
146
147 static __inline int
148 lwkt_getpri_self(void)
149 {
150     return(lwkt_getpri(curthread));
151 }
152
153 #endif
154