Commit | Line | Data |
---|---|---|
2df9fa87 MD |
1 | /* |
2 | * SYS/THREAD.H | |
3 | * | |
4 | * Implements the architecture independant portion of the LWKT | |
5 | * subsystem. | |
6 | * | |
dadab5e9 | 7 | * $DragonFly: src/sys/sys/thread.h,v 1.9 2003/06/25 03:56:10 dillon Exp $ |
2df9fa87 MD |
8 | */ |
9 | ||
10 | #ifndef _SYS_THREAD_H_ | |
11 | #define _SYS_THREAD_H_ | |
12 | ||
f1d1c3fa | 13 | struct globaldata; |
2df9fa87 MD |
14 | struct proc; |
15 | struct thread; | |
f1d1c3fa MD |
16 | struct lwkt_queue; |
17 | struct lwkt_token; | |
18 | struct lwkt_wait; | |
19 | struct lwkt_msg; | |
20 | struct lwkt_port; | |
21 | struct lwkt_cpu_msg; | |
22 | struct lwkt_cpu_port; | |
23 | struct lwkt_rwlock; | |
24 | ||
25 | typedef struct lwkt_queue *lwkt_queue_t; | |
26 | typedef struct lwkt_token *lwkt_token_t; | |
27 | typedef struct lwkt_wait *lwkt_wait_t; | |
28 | typedef struct lwkt_msg *lwkt_msg_t; | |
29 | typedef struct lwkt_port *lwkt_port_t; | |
30 | typedef struct lwkt_cpu_msg *lwkt_cpu_msg_t; | |
31 | typedef struct lwkt_cpu_port *lwkt_cpu_port_t; | |
32 | typedef struct lwkt_rwlock *lwkt_rwlock_t; | |
33 | typedef struct thread *thread_t; | |
34 | ||
35 | typedef TAILQ_HEAD(lwkt_queue, thread) lwkt_queue; | |
36 | typedef TAILQ_HEAD(lwkt_msg_queue, lwkt_msg) lwkt_msg_queue; | |
37 | ||
38 | #include <machine/thread.h> | |
39 | ||
40 | /* | |
41 | * Tokens arbitrate access to information. They are 'soft' arbitrators | |
42 | * in that they are associated with cpus rather then threads, making the | |
43 | * optimal aquisition case very fast if your cpu already happens to own the | |
44 | * token you are requesting. | |
45 | */ | |
46 | typedef struct lwkt_token { | |
47 | int t_cpu; /* the current owner of the token */ | |
48 | int t_reqcpu; /* return ownership to this cpu on release */ | |
49 | #if 0 | |
50 | int t_pri; /* raise thread priority to hold token */ | |
51 | #endif | |
52 | } lwkt_token; | |
53 | ||
54 | /* | |
55 | * Wait structures deal with blocked threads. Due to the way remote cpus | |
56 | * interact with these structures stable storage must be used. | |
57 | */ | |
58 | typedef struct lwkt_wait { | |
59 | lwkt_queue wa_waitq; /* list of waiting threads */ | |
60 | lwkt_token wa_token; /* who currently owns the list */ | |
61 | int wa_gen; | |
62 | int wa_count; | |
63 | } lwkt_wait; | |
64 | ||
65 | /* | |
66 | * The standarding message and port structure for communications between | |
67 | * threads. | |
68 | */ | |
69 | typedef struct lwkt_msg { | |
70 | TAILQ_ENTRY(lwkt_msg) ms_node; | |
71 | lwkt_port_t ms_replyport; | |
72 | int ms_cmd; | |
73 | int ms_flags; | |
74 | int ms_error; | |
75 | } lwkt_msg; | |
76 | ||
77 | #define MSGF_DONE 0x0001 | |
78 | #define MSGF_REPLY 0x0002 | |
79 | #define MSGF_QUEUED 0x0004 | |
80 | ||
81 | typedef struct lwkt_port { | |
82 | lwkt_msg_queue mp_msgq; | |
83 | lwkt_wait mp_wait; | |
84 | } lwkt_port; | |
2df9fa87 | 85 | |
f1d1c3fa | 86 | #define mp_token mp_wait.wa_token |
2df9fa87 | 87 | |
f1d1c3fa MD |
88 | /* |
89 | * The standard message and queue structure used for communications between | |
90 | * cpus. Messages are typically queued via a machine-specific non-linked | |
91 | * FIFO matrix allowing any cpu to send a message to any other cpu without | |
92 | * blocking. | |
93 | */ | |
94 | typedef struct lwkt_cpu_msg { | |
95 | void (*cm_func)(lwkt_cpu_msg_t msg); /* primary dispatch function */ | |
96 | int cm_code; /* request code if applicable */ | |
97 | int cm_cpu; /* reply to cpu */ | |
98 | thread_t cm_originator; /* originating thread for wakeup */ | |
99 | } lwkt_cpu_msg; | |
100 | ||
101 | /* | |
102 | * reader/writer lock | |
103 | */ | |
104 | typedef struct lwkt_rwlock { | |
ae8050a4 | 105 | lwkt_wait rw_wait; |
f1d1c3fa MD |
106 | thread_t rw_owner; |
107 | int rw_count; | |
17d46a8c | 108 | int rw_requests; |
f1d1c3fa MD |
109 | } lwkt_rwlock; |
110 | ||
111 | #define rw_token rw_wait.wa_token | |
112 | ||
113 | /* | |
114 | * Thread structure. Note that ownership of a thread structure is special | |
115 | * cased and there is no 'token'. A thread is always owned by td_cpu and | |
116 | * any manipulation of the thread by some other cpu must be done through | |
117 | * cpu_*msg() functions. e.g. you could request ownership of a thread that | |
118 | * way, or hand a thread off to another cpu by changing td_cpu and sending | |
119 | * a schedule request to the other cpu. | |
120 | */ | |
2df9fa87 MD |
121 | struct thread { |
122 | TAILQ_ENTRY(thread) td_threadq; | |
123 | struct proc *td_proc; /* (optional) associated process */ | |
124 | struct pcb *td_pcb; /* points to pcb and top of kstack */ | |
ae8050a4 | 125 | const char *td_wmesg; /* string name for blockage */ |
f1d1c3fa | 126 | int td_cpu; /* cpu owning the thread */ |
2df9fa87 | 127 | int td_pri; /* 0-31, 0=highest priority */ |
8ad65e08 | 128 | int td_flags; /* THF flags */ |
f1d1c3fa | 129 | int td_gen; /* wait queue chasing generation number */ |
7e1d4bf4 | 130 | char *td_kstack; /* kernel stack */ |
8ad65e08 MD |
131 | char *td_sp; /* kernel stack pointer for LWKT restore */ |
132 | void (*td_switch)(struct thread *ntd); | |
f1d1c3fa | 133 | lwkt_wait_t td_wait; /* thread sitting on wait structure */ |
ae8050a4 | 134 | lwkt_rwlock td_rwlock; /* thread arbitration */ |
d16a8831 MD |
135 | u_int64_t td_uticks; /* Statclock hits in user mode (uS) */ |
136 | u_int64_t td_sticks; /* Statclock hits in system mode (uS) */ | |
137 | u_int64_t td_iticks; /* Statclock hits processing intr (uS) */ | |
dadab5e9 | 138 | int td_locks; /* lockmgr lock debugging YYY */ |
f1d1c3fa | 139 | struct mi_thread td_mach; |
2df9fa87 MD |
140 | }; |
141 | ||
ae8050a4 MD |
142 | #define td_token td_rwlock.rw_token |
143 | ||
8ad65e08 | 144 | /* |
f1d1c3fa | 145 | * Thread flags. Note that the RUNNING state is independant from the |
8ad65e08 MD |
146 | * RUNQ/WAITQ state. That is, a thread's queueing state can be manipulated |
147 | * while it is running. If a thread is preempted it will always be moved | |
148 | * back to the RUNQ if it isn't on it. | |
149 | */ | |
8ad65e08 MD |
150 | #define TDF_RUNNING 0x0001 /* currently running */ |
151 | #define TDF_RUNQ 0x0002 /* on run queue */ | |
dadab5e9 | 152 | #define TDF_DEADLKTREAT 0x1000 /* special lockmgr deadlock treatment */ |
8ad65e08 | 153 | |
2df9fa87 MD |
154 | /* |
155 | * Thread priorities. Typically only one thread from any given | |
156 | * user process scheduling queue is on the LWKT run queue at a time. | |
157 | * Remember that there is one LWKT run queue per cpu. | |
f1d1c3fa MD |
158 | * |
159 | * Critical sections are handled by bumping td_pri above TDPRI_MAX, which | |
160 | * causes interrupts to be masked as they occur. When this occurs | |
161 | * mycpu->gd_reqpri will be raised (possibly just set to TDPRI_CRIT for | |
162 | * interrupt masking). | |
2df9fa87 | 163 | */ |
f1d1c3fa MD |
164 | #define TDPRI_IDLE_THREAD 0 /* the idle thread */ |
165 | #define TDPRI_USER_IDLE 4 /* user scheduler idle */ | |
166 | #define TDPRI_USER_NORM 6 /* user scheduler normal */ | |
167 | #define TDPRI_USER_REAL 8 /* user scheduler real time */ | |
168 | #define TDPRI_KERN_USER 10 /* kernel / block in syscall */ | |
169 | #define TDPRI_SOFT_NORM 14 /* kernel / normal */ | |
170 | #define TDPRI_SOFT_TIMER 16 /* kernel / timer */ | |
ae8050a4 | 171 | #define TDPRI_EXITING 19 /* exiting thread */ |
f1d1c3fa MD |
172 | #define TDPRI_INT_SUPPORT 20 /* kernel / high priority support */ |
173 | #define TDPRI_INT_LOW 27 /* low priority interrupt */ | |
174 | #define TDPRI_INT_MED 28 /* medium priority interrupt */ | |
175 | #define TDPRI_INT_HIGH 29 /* high priority interrupt */ | |
176 | #define TDPRI_MAX 31 | |
177 | ||
178 | #define TDPRI_MASK 31 | |
179 | #define TDPRI_CRIT 32 /* high bits of td_pri used for crit */ | |
2df9fa87 | 180 | |
7e1d4bf4 MD |
181 | #define CACHE_NTHREADS 4 |
182 | ||
2df9fa87 MD |
183 | #ifdef _KERNEL |
184 | ||
185 | extern struct vm_zone *thread_zone; | |
186 | ||
7d0bac62 MD |
187 | extern struct thread *lwkt_alloc_thread(void); |
188 | extern void lwkt_init_thread(struct thread *td, void *stack); | |
189 | extern void lwkt_init_wait(struct lwkt_wait *w); | |
8ad65e08 MD |
190 | extern void lwkt_gdinit(struct globaldata *gd); |
191 | extern void lwkt_switch(void); | |
192 | extern void lwkt_preempt(void); | |
193 | extern void lwkt_schedule(thread_t td); | |
f1d1c3fa | 194 | extern void lwkt_schedule_self(void); |
8ad65e08 | 195 | extern void lwkt_deschedule(thread_t td); |
f1d1c3fa MD |
196 | extern void lwkt_deschedule_self(void); |
197 | extern void lwkt_yield(void); | |
198 | extern void lwkt_yield_quick(void); | |
199 | ||
ae8050a4 | 200 | extern void lwkt_block(lwkt_wait_t w, const char *wmesg, int *gen); |
f1d1c3fa MD |
201 | extern void lwkt_signal(lwkt_wait_t w); |
202 | extern void lwkt_gettoken(lwkt_token_t tok); | |
203 | extern void lwkt_reltoken(lwkt_token_t tok); | |
204 | extern int lwkt_regettoken(lwkt_token_t tok); | |
ae8050a4 MD |
205 | extern void lwkt_rwlock_init(lwkt_rwlock_t lock); |
206 | extern void lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg); | |
207 | extern void lwkt_shlock(lwkt_rwlock_t lock, const char *wmesg); | |
208 | extern void lwkt_exunlock(lwkt_rwlock_t lock); | |
209 | extern void lwkt_shunlock(lwkt_rwlock_t lock); | |
8ad65e08 | 210 | |
2df9fa87 MD |
211 | #endif |
212 | ||
213 | #endif | |
214 |