Rev 3016 | Rev 3026 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3016 | Rev 3018 | ||
|---|---|---|---|
| Line 48... | Line 48... | ||
| 48 | ut->begin_call = NULL; |
48 | ut->begin_call = NULL; |
| 49 | ut->not_stoppable_count = 0; |
49 | ut->not_stoppable_count = 0; |
| 50 | ut->evmask = 0; |
50 | ut->evmask = 0; |
| 51 | } |
51 | } |
| 52 | 52 | ||
| - | 53 | void udebug_thread_initialize(udebug_thread_t *ut) |
|
| - | 54 | { |
|
| - | 55 | waitq_initialize(&ut->go_wq); |
|
| - | 56 | ut->go_call = NULL; |
|
| - | 57 | ut->uspace_state = NULL; |
|
| - | 58 | ut->stop = true; |
|
| - | 59 | ut->stoppable = true; |
|
| - | 60 | ut->debug_active = false; |
|
| - | 61 | ut->cur_event = 0; /* none */ |
|
| - | 62 | } |
|
| - | 63 | ||
| 53 | static void udebug_wait_for_go(waitq_t *wq) |
64 | static void udebug_wait_for_go(waitq_t *wq) |
| 54 | { |
65 | { |
| 55 | int rc; |
66 | int rc; |
| 56 | ipl_t ipl; |
67 | ipl_t ipl; |
| 57 | 68 | ||
| Line 88... | Line 99... | ||
| 88 | */ |
99 | */ |
| 89 | 100 | ||
| 90 | db_call = TASK->udebug.begin_call; |
101 | db_call = TASK->udebug.begin_call; |
| 91 | ASSERT(db_call); |
102 | ASSERT(db_call); |
| 92 | 103 | ||
| 93 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
104 | /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */ |
| 94 | ipl = interrupts_disable(); |
105 | ipl = interrupts_disable(); |
| 95 | spinlock_lock(&THREAD->debug_lock); |
106 | spinlock_lock(&THREAD->udebug.lock); |
| 96 | THREAD->debug_stoppable = true; |
107 | THREAD->udebug.stoppable = true; |
| 97 | spinlock_unlock(&THREAD->debug_lock); |
108 | spinlock_unlock(&THREAD->udebug.lock); |
| 98 | interrupts_restore(ipl); |
109 | interrupts_restore(ipl); |
| 99 | 110 | ||
| 100 | TASK->udebug.dt_state = UDEBUG_TS_ACTIVE; |
111 | TASK->udebug.dt_state = UDEBUG_TS_ACTIVE; |
| 101 | TASK->udebug.begin_call = NULL; |
112 | TASK->udebug.begin_call = NULL; |
| 102 | mutex_unlock(&TASK->udebug.lock); |
113 | mutex_unlock(&TASK->udebug.lock); |
| Line 108... | Line 119... | ||
| 108 | } else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
119 | } else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
| 109 | /* |
120 | /* |
| 110 | * Active debugging session |
121 | * Active debugging session |
| 111 | */ |
122 | */ |
| 112 | 123 | ||
| 113 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
124 | /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */ |
| 114 | ipl = interrupts_disable(); |
125 | ipl = interrupts_disable(); |
| 115 | spinlock_lock(&THREAD->debug_lock); |
126 | spinlock_lock(&THREAD->udebug.lock); |
| 116 | THREAD->debug_stoppable = true; |
127 | THREAD->udebug.stoppable = true; |
| 117 | 128 | ||
| 118 | if (THREAD->debug_active && THREAD->debug_stop) { |
129 | if (THREAD->udebug.debug_active && THREAD->udebug.stop) { |
| 119 | /* |
130 | /* |
| 120 | * Thread was requested to stop - answer go call |
131 | * Thread was requested to stop - answer go call |
| 121 | */ |
132 | */ |
| 122 | 133 | ||
| 123 | /* Make sure nobody takes this call away from us */ |
134 | /* Make sure nobody takes this call away from us */ |
| 124 | go_call = THREAD->debug_go_call; |
135 | go_call = THREAD->udebug.go_call; |
| 125 | THREAD->debug_go_call = NULL; |
136 | THREAD->udebug.go_call = NULL; |
| 126 | ASSERT(go_call); |
137 | ASSERT(go_call); |
| 127 | 138 | ||
| 128 | IPC_SET_RETVAL(go_call->data, 0); |
139 | IPC_SET_RETVAL(go_call->data, 0); |
| 129 | IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP); |
140 | IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP); |
| 130 | 141 | ||
| 131 | THREAD->cur_event = UDEBUG_EVENT_STOP; |
142 | THREAD->udebug.cur_event = UDEBUG_EVENT_STOP; |
| 132 | spinlock_unlock(&THREAD->debug_lock); |
143 | spinlock_unlock(&THREAD->udebug.lock); |
| 133 | interrupts_restore(ipl); |
144 | interrupts_restore(ipl); |
| 134 | 145 | ||
| 135 | ipc_answer(&TASK->answerbox, go_call); |
146 | ipc_answer(&TASK->answerbox, go_call); |
| 136 | 147 | ||
| 137 | mutex_unlock(&TASK->udebug.lock); |
148 | mutex_unlock(&TASK->udebug.lock); |
| 138 | } else { |
149 | } else { |
| 139 | /* |
150 | /* |
| 140 | * No stop request - nothing happens. |
151 | * No stop request - nothing happens. |
| 141 | */ |
152 | */ |
| 142 | spinlock_unlock(&THREAD->debug_lock); |
153 | spinlock_unlock(&THREAD->udebug.lock); |
| 143 | interrupts_restore(ipl); |
154 | interrupts_restore(ipl); |
| 144 | mutex_unlock(&TASK->udebug.lock); |
155 | mutex_unlock(&TASK->udebug.lock); |
| 145 | } |
156 | } |
| 146 | } else { |
157 | } else { |
| 147 | /* |
158 | /* |
| 148 | * All other cases - nothing special happens. |
159 | * All other cases - nothing special happens. |
| 149 | */ |
160 | */ |
| 150 | 161 | ||
| 151 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
162 | /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */ |
| 152 | ipl = interrupts_disable(); |
163 | ipl = interrupts_disable(); |
| 153 | spinlock_lock(&THREAD->debug_lock); |
164 | spinlock_lock(&THREAD->udebug.lock); |
| 154 | THREAD->debug_stoppable = true; |
165 | THREAD->udebug.stoppable = true; |
| 155 | spinlock_unlock(&THREAD->debug_lock); |
166 | spinlock_unlock(&THREAD->udebug.lock); |
| 156 | interrupts_restore(ipl); |
167 | interrupts_restore(ipl); |
| 157 | 168 | ||
| 158 | mutex_unlock(&TASK->udebug.lock); |
169 | mutex_unlock(&TASK->udebug.lock); |
| 159 | } |
170 | } |
| 160 | } |
171 | } |
| Line 164... | Line 175... | ||
| 164 | ipl_t ipl; |
175 | ipl_t ipl; |
| 165 | 176 | ||
| 166 | restart: |
177 | restart: |
| 167 | mutex_lock(&TASK->udebug.lock); |
178 | mutex_lock(&TASK->udebug.lock); |
| 168 | 179 | ||
| 169 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
180 | /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */ |
| 170 | ipl = interrupts_disable(); |
181 | ipl = interrupts_disable(); |
| 171 | spinlock_lock(&THREAD->debug_lock); |
182 | spinlock_lock(&THREAD->udebug.lock); |
| 172 | 183 | ||
| 173 | if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
184 | if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
| 174 | //klog_printf("udebug_stoppable_end"); |
185 | //klog_printf("udebug_stoppable_end"); |
| 175 | //klog_printf("debug_stop=%d", THREAD->debug_stop); |
186 | //klog_printf("udebug.stop=%d", THREAD->udebug.stop); |
| 176 | } |
187 | } |
| 177 | 188 | ||
| 178 | if (THREAD->debug_active && |
189 | if (THREAD->udebug.debug_active && |
| 179 | THREAD->debug_stop == true) { |
190 | THREAD->udebug.stop == true) { |
| 180 | TASK->udebug.begin_call = NULL; |
191 | TASK->udebug.begin_call = NULL; |
| 181 | spinlock_unlock(&THREAD->debug_lock); |
192 | spinlock_unlock(&THREAD->udebug.lock); |
| 182 | interrupts_restore(ipl); |
193 | interrupts_restore(ipl); |
| 183 | mutex_unlock(&TASK->udebug.lock); |
194 | mutex_unlock(&TASK->udebug.lock); |
| 184 | 195 | ||
| 185 | udebug_wait_for_go(&THREAD->go_wq); |
196 | udebug_wait_for_go(&THREAD->udebug.go_wq); |
| 186 | 197 | ||
| 187 | goto restart; |
198 | goto restart; |
| 188 | /* must try again - have to lose stoppability atomically */ |
199 | /* must try again - have to lose stoppability atomically */ |
| 189 | } else { |
200 | } else { |
| 190 | ++TASK->udebug.not_stoppable_count; |
201 | ++TASK->udebug.not_stoppable_count; |
| 191 | THREAD->debug_stoppable = false; |
202 | THREAD->udebug.stoppable = false; |
| 192 | 203 | ||
| 193 | spinlock_unlock(&THREAD->debug_lock); |
204 | spinlock_unlock(&THREAD->udebug.lock); |
| 194 | interrupts_restore(ipl); |
205 | interrupts_restore(ipl); |
| 195 | mutex_unlock(&TASK->udebug.lock); |
206 | mutex_unlock(&TASK->udebug.lock); |
| 196 | } |
207 | } |
| 197 | } |
208 | } |
| 198 | 209 | ||
| Line 206... | Line 217... | ||
| 206 | void udebug_before_thread_runs(void) |
217 | void udebug_before_thread_runs(void) |
| 207 | { |
218 | { |
| 208 | ipl_t ipl; |
219 | ipl_t ipl; |
| 209 | 220 | ||
| 210 | /* This will happen if we get preempted inside this function. */ |
221 | /* This will happen if we get preempted inside this function. */ |
| 211 | if (THREAD->debug_in_before_thread_runs) |
222 | if (THREAD->udebug.in_before_thread_runs) |
| 212 | return; |
223 | return; |
| 213 | 224 | ||
| 214 | THREAD->debug_in_before_thread_runs = true; |
225 | THREAD->udebug.in_before_thread_runs = true; |
| 215 | ipl = interrupts_enable(); |
226 | ipl = interrupts_enable(); |
| 216 | 227 | ||
| 217 | /* Now we're free to do whatever we need (lock mutexes, sleep, etc.) */ |
228 | /* Now we're free to do whatever we need (lock mutexes, sleep, etc.) */ |
| 218 | 229 | ||
| 219 | /* Check if we're supposed to stop */ |
230 | /* Check if we're supposed to stop */ |
| 220 | udebug_stoppable_begin(); |
231 | udebug_stoppable_begin(); |
| 221 | udebug_stoppable_end(); |
232 | udebug_stoppable_end(); |
| 222 | 233 | ||
| 223 | interrupts_restore(ipl); |
234 | interrupts_restore(ipl); |
| 224 | THREAD->debug_in_before_thread_runs = false; |
235 | THREAD->udebug.in_before_thread_runs = false; |
| 225 | } |
236 | } |
| 226 | 237 | ||
| 227 | void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3, |
238 | void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3, |
| 228 | unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc, |
239 | unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc, |
| 229 | bool end_variant) |
240 | bool end_variant) |
| Line 235... | Line 246... | ||
| 235 | etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B; |
246 | etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B; |
| 236 | 247 | ||
| 237 | mutex_lock(&TASK->udebug.lock); |
248 | mutex_lock(&TASK->udebug.lock); |
| 238 | 249 | ||
| 239 | ipl = interrupts_disable(); |
250 | ipl = interrupts_disable(); |
| 240 | spinlock_lock(&THREAD->debug_lock); |
251 | spinlock_lock(&THREAD->udebug.lock); |
| 241 | 252 | ||
| 242 | /* Must only generate events when in debugging session and have go */ |
253 | /* Must only generate events when in debugging session and have go */ |
| 243 | if (THREAD->debug_active != true || |
254 | if (THREAD->udebug.debug_active != true || |
| 244 | THREAD->debug_stop == true || |
255 | THREAD->udebug.stop == true || |
| 245 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
256 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
| 246 | spinlock_unlock(&THREAD->debug_lock); |
257 | spinlock_unlock(&THREAD->udebug.lock); |
| 247 | interrupts_restore(ipl); |
258 | interrupts_restore(ipl); |
| 248 | mutex_unlock(&TASK->udebug.lock); |
259 | mutex_unlock(&TASK->udebug.lock); |
| 249 | return; |
260 | return; |
| 250 | } |
261 | } |
| 251 | 262 | ||
| 252 | //klog_printf("udebug_syscall_event"); |
263 | //klog_printf("udebug_syscall_event"); |
| 253 | call = THREAD->debug_go_call; |
264 | call = THREAD->udebug.go_call; |
| 254 | THREAD->debug_go_call = NULL; |
265 | THREAD->udebug.go_call = NULL; |
| 255 | 266 | ||
| 256 | IPC_SET_RETVAL(call->data, 0); |
267 | IPC_SET_RETVAL(call->data, 0); |
| 257 | IPC_SET_ARG1(call->data, etype); |
268 | IPC_SET_ARG1(call->data, etype); |
| 258 | IPC_SET_ARG2(call->data, id); |
269 | IPC_SET_ARG2(call->data, id); |
| 259 | IPC_SET_ARG3(call->data, rc); |
270 | IPC_SET_ARG3(call->data, rc); |
| 260 | //klog_printf("udebug_syscall_event/ipc_answer"); |
271 | //klog_printf("udebug_syscall_event/ipc_answer"); |
| 261 | 272 | ||
| 262 | THREAD->syscall_args[0] = a1; |
273 | THREAD->udebug.syscall_args[0] = a1; |
| 263 | THREAD->syscall_args[1] = a2; |
274 | THREAD->udebug.syscall_args[1] = a2; |
| 264 | THREAD->syscall_args[2] = a3; |
275 | THREAD->udebug.syscall_args[2] = a3; |
| 265 | THREAD->syscall_args[3] = a4; |
276 | THREAD->udebug.syscall_args[3] = a4; |
| 266 | THREAD->syscall_args[4] = a5; |
277 | THREAD->udebug.syscall_args[4] = a5; |
| 267 | THREAD->syscall_args[5] = a6; |
278 | THREAD->udebug.syscall_args[5] = a6; |
| 268 | 279 | ||
| 269 | /* |
280 | /* |
| 270 | * Make sure debug_stop is true when going to sleep |
281 | * Make sure udebug.stop is true when going to sleep |
| 271 | * in case we get woken up by DEBUG_END. (At which |
282 | * in case we get woken up by DEBUG_END. (At which |
| 272 | * point it must be back to the initial true value). |
283 | * point it must be back to the initial true value). |
| 273 | */ |
284 | */ |
| 274 | THREAD->debug_stop = true; |
285 | THREAD->udebug.stop = true; |
| 275 | 286 | ||
| 276 | THREAD->cur_event = etype; |
287 | THREAD->udebug.cur_event = etype; |
| 277 | spinlock_unlock(&THREAD->debug_lock); |
288 | spinlock_unlock(&THREAD->udebug.lock); |
| 278 | interrupts_restore(ipl); |
289 | interrupts_restore(ipl); |
| 279 | 290 | ||
| 280 | ipc_answer(&TASK->answerbox, call); |
291 | ipc_answer(&TASK->answerbox, call); |
| 281 | 292 | ||
| 282 | mutex_unlock(&TASK->udebug.lock); |
293 | mutex_unlock(&TASK->udebug.lock); |
| 283 | 294 | ||
| 284 | udebug_wait_for_go(&THREAD->go_wq); |
295 | udebug_wait_for_go(&THREAD->udebug.go_wq); |
| 285 | } |
296 | } |
| 286 | 297 | ||
| 287 | void udebug_thread_b_event(struct thread *t) |
298 | void udebug_thread_b_event(struct thread *t) |
| 288 | { |
299 | { |
| 289 | call_t *call; |
300 | call_t *call; |
| 290 | ipl_t ipl; |
301 | ipl_t ipl; |
| 291 | 302 | ||
| 292 | mutex_lock(&TASK->udebug.lock); |
303 | mutex_lock(&TASK->udebug.lock); |
| 293 | 304 | ||
| 294 | ipl = interrupts_disable(); |
305 | ipl = interrupts_disable(); |
| 295 | spinlock_lock(&THREAD->debug_lock); |
306 | spinlock_lock(&THREAD->udebug.lock); |
| 296 | 307 | ||
| 297 | klog_printf("udebug_thread_b_event"); |
308 | klog_printf("udebug_thread_b_event"); |
| 298 | klog_printf("- check state"); |
309 | klog_printf("- check state"); |
| 299 | 310 | ||
| 300 | /* Must only generate events when in debugging session */ |
311 | /* Must only generate events when in debugging session */ |
| 301 | if (THREAD->debug_active != true) { |
312 | if (THREAD->udebug.debug_active != true) { |
| 302 | klog_printf("- debug_active: %s, debug_stop: %s", |
313 | klog_printf("- debug_active: %s, udebug.stop: %s", |
| 303 | THREAD->debug_active ? "yes(+)" : "no(-)", |
314 | THREAD->udebug.debug_active ? "yes(+)" : "no(-)", |
| 304 | THREAD->debug_stop ? "yes(-)" : "no(+)"); |
315 | THREAD->udebug.stop ? "yes(-)" : "no(+)"); |
| 305 | spinlock_unlock(&THREAD->debug_lock); |
316 | spinlock_unlock(&THREAD->udebug.lock); |
| 306 | interrupts_restore(ipl); |
317 | interrupts_restore(ipl); |
| 307 | mutex_unlock(&TASK->udebug.lock); |
318 | mutex_unlock(&TASK->udebug.lock); |
| 308 | return; |
319 | return; |
| 309 | } |
320 | } |
| 310 | 321 | ||
| 311 | klog_printf("- trigger event"); |
322 | klog_printf("- trigger event"); |
| 312 | 323 | ||
| 313 | call = THREAD->debug_go_call; |
324 | call = THREAD->udebug.go_call; |
| 314 | THREAD->debug_go_call = NULL; |
325 | THREAD->udebug.go_call = NULL; |
| 315 | IPC_SET_RETVAL(call->data, 0); |
326 | IPC_SET_RETVAL(call->data, 0); |
| 316 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B); |
327 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B); |
| 317 | IPC_SET_ARG2(call->data, (unative_t)t); |
328 | IPC_SET_ARG2(call->data, (unative_t)t); |
| 318 | 329 | ||
| 319 | /* |
330 | /* |
| 320 | * Make sure debug_stop is true when going to sleep |
331 | * Make sure udebug.stop is true when going to sleep |
| 321 | * in case we get woken up by DEBUG_END. (At which |
332 | * in case we get woken up by DEBUG_END. (At which |
| 322 | * point it must be back to the initial true value). |
333 | * point it must be back to the initial true value). |
| 323 | */ |
334 | */ |
| 324 | THREAD->debug_stop = true; |
335 | THREAD->udebug.stop = true; |
| 325 | 336 | ||
| 326 | THREAD->cur_event = UDEBUG_EVENT_THREAD_B; |
337 | THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B; |
| 327 | spinlock_unlock(&THREAD->debug_lock); |
338 | spinlock_unlock(&THREAD->udebug.lock); |
| 328 | interrupts_restore(ipl); |
339 | interrupts_restore(ipl); |
| 329 | 340 | ||
| 330 | ipc_answer(&TASK->answerbox, call); |
341 | ipc_answer(&TASK->answerbox, call); |
| 331 | 342 | ||
| 332 | mutex_unlock(&TASK->udebug.lock); |
343 | mutex_unlock(&TASK->udebug.lock); |
| 333 | 344 | ||
| 334 | klog_printf("- sleep"); |
345 | klog_printf("- sleep"); |
| 335 | udebug_wait_for_go(&THREAD->go_wq); |
346 | udebug_wait_for_go(&THREAD->udebug.go_wq); |
| 336 | } |
347 | } |
| 337 | 348 | ||
| 338 | void udebug_thread_e_event(void) |
349 | void udebug_thread_e_event(void) |
| 339 | { |
350 | { |
| 340 | call_t *call; |
351 | call_t *call; |
| 341 | ipl_t ipl; |
352 | ipl_t ipl; |
| 342 | 353 | ||
| 343 | mutex_lock(&TASK->udebug.lock); |
354 | mutex_lock(&TASK->udebug.lock); |
| 344 | 355 | ||
| 345 | ipl = interrupts_disable(); |
356 | ipl = interrupts_disable(); |
| 346 | spinlock_lock(&THREAD->debug_lock); |
357 | spinlock_lock(&THREAD->udebug.lock); |
| 347 | 358 | ||
| 348 | klog_printf("udebug_thread_e_event"); |
359 | klog_printf("udebug_thread_e_event"); |
| 349 | klog_printf("- check state"); |
360 | klog_printf("- check state"); |
| 350 | 361 | ||
| 351 | /* Must only generate events when in debugging session */ |
362 | /* Must only generate events when in debugging session */ |
| 352 | if (THREAD->debug_active != true) { |
363 | if (THREAD->udebug.debug_active != true) { |
| 353 | klog_printf("- debug_active: %s, debug_stop: %s", |
364 | klog_printf("- debug_active: %s, udebug.stop: %s", |
| 354 | THREAD->debug_active ? "yes(+)" : "no(-)", |
365 | THREAD->udebug.debug_active ? "yes(+)" : "no(-)", |
| 355 | THREAD->debug_stop ? "yes(-)" : "no(+)"); |
366 | THREAD->udebug.stop ? "yes(-)" : "no(+)"); |
| 356 | spinlock_unlock(&THREAD->debug_lock); |
367 | spinlock_unlock(&THREAD->udebug.lock); |
| 357 | interrupts_restore(ipl); |
368 | interrupts_restore(ipl); |
| 358 | mutex_unlock(&TASK->udebug.lock); |
369 | mutex_unlock(&TASK->udebug.lock); |
| 359 | return; |
370 | return; |
| 360 | } |
371 | } |
| 361 | 372 | ||
| 362 | klog_printf("- trigger event"); |
373 | klog_printf("- trigger event"); |
| 363 | 374 | ||
| 364 | call = THREAD->debug_go_call; |
375 | call = THREAD->udebug.go_call; |
| 365 | THREAD->debug_go_call = NULL; |
376 | THREAD->udebug.go_call = NULL; |
| 366 | IPC_SET_RETVAL(call->data, 0); |
377 | IPC_SET_RETVAL(call->data, 0); |
| 367 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E); |
378 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E); |
| 368 | 379 | ||
| 369 | /* Prevent any further debug activity in thread */ |
380 | /* Prevent any further debug activity in thread */ |
| 370 | THREAD->debug_active = false; |
381 | THREAD->udebug.debug_active = false; |
| 371 | THREAD->cur_event = 0; /* none */ |
382 | THREAD->udebug.cur_event = 0; /* none */ |
| 372 | THREAD->debug_stop = true; /* set to initial value */ |
383 | THREAD->udebug.stop = true; /* set to initial value */ |
| 373 | 384 | ||
| 374 | spinlock_unlock(&THREAD->debug_lock); |
385 | spinlock_unlock(&THREAD->udebug.lock); |
| 375 | interrupts_restore(ipl); |
386 | interrupts_restore(ipl); |
| 376 | 387 | ||
| 377 | ipc_answer(&TASK->answerbox, call); |
388 | ipc_answer(&TASK->answerbox, call); |
| 378 | 389 | ||
| 379 | mutex_unlock(&TASK->udebug.lock); |
390 | mutex_unlock(&TASK->udebug.lock); |
| Line 387... | Line 398... | ||
| 387 | ipl_t ipl; |
398 | ipl_t ipl; |
| 388 | 399 | ||
| 389 | mutex_lock(&TASK->udebug.lock); |
400 | mutex_lock(&TASK->udebug.lock); |
| 390 | 401 | ||
| 391 | ipl = interrupts_disable(); |
402 | ipl = interrupts_disable(); |
| 392 | spinlock_lock(&THREAD->debug_lock); |
403 | spinlock_lock(&THREAD->udebug.lock); |
| 393 | 404 | ||
| 394 | /* Must only generate events when in debugging session and have go */ |
405 | /* Must only generate events when in debugging session and have go */ |
| 395 | if (THREAD->debug_active != true || |
406 | if (THREAD->udebug.debug_active != true || |
| 396 | THREAD->debug_stop == true || |
407 | THREAD->udebug.stop == true || |
| 397 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
408 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
| 398 | spinlock_unlock(&THREAD->debug_lock); |
409 | spinlock_unlock(&THREAD->udebug.lock); |
| 399 | interrupts_restore(ipl); |
410 | interrupts_restore(ipl); |
| 400 | mutex_unlock(&TASK->udebug.lock); |
411 | mutex_unlock(&TASK->udebug.lock); |
| 401 | return; |
412 | return; |
| 402 | } |
413 | } |
| 403 | 414 | ||
| 404 | klog_printf("udebug_breakpoint/trap_event"); |
415 | klog_printf("udebug_breakpoint/trap_event"); |
| 405 | call = THREAD->debug_go_call; |
416 | call = THREAD->udebug.go_call; |
| 406 | THREAD->debug_go_call = NULL; |
417 | THREAD->udebug.go_call = NULL; |
| 407 | 418 | ||
| 408 | IPC_SET_RETVAL(call->data, 0); |
419 | IPC_SET_RETVAL(call->data, 0); |
| 409 | IPC_SET_ARG1(call->data, etype); |
420 | IPC_SET_ARG1(call->data, etype); |
| 410 | IPC_SET_ARG2(call->data, addr); |
421 | IPC_SET_ARG2(call->data, addr); |
| 411 | 422 | ||
| 412 | /* |
423 | /* |
| 413 | * Make sure debug_stop is true when going to sleep |
424 | * Make sure udebug.stop is true when going to sleep |
| 414 | * in case we get woken up by DEBUG_END. (At which |
425 | * in case we get woken up by DEBUG_END. (At which |
| 415 | * point it must be back to the initial true value). |
426 | * point it must be back to the initial true value). |
| 416 | */ |
427 | */ |
| 417 | THREAD->debug_stop = true; |
428 | THREAD->udebug.stop = true; |
| 418 | 429 | ||
| 419 | THREAD->cur_event = etype; |
430 | THREAD->udebug.cur_event = etype; |
| 420 | spinlock_unlock(&THREAD->debug_lock); |
431 | spinlock_unlock(&THREAD->udebug.lock); |
| 421 | interrupts_restore(ipl); |
432 | interrupts_restore(ipl); |
| 422 | klog_printf("- send answer"); |
433 | klog_printf("- send answer"); |
| 423 | 434 | ||
| 424 | ipc_answer(&TASK->answerbox, call); |
435 | ipc_answer(&TASK->answerbox, call); |
| 425 | mutex_unlock(&TASK->udebug.lock); |
436 | mutex_unlock(&TASK->udebug.lock); |
| 426 | 437 | ||
| 427 | udebug_wait_for_go(&THREAD->go_wq); |
438 | udebug_wait_for_go(&THREAD->udebug.go_wq); |
| 428 | } |
439 | } |
| 429 | 440 | ||
| 430 | void udebug_breakpoint_event(uintptr_t addr) |
441 | void udebug_breakpoint_event(uintptr_t addr) |
| 431 | { |
442 | { |
| 432 | breakpoint_trap_event(addr, UDEBUG_EVENT_BREAKPOINT); |
443 | breakpoint_trap_event(addr, UDEBUG_EVENT_BREAKPOINT); |
| Line 462... | Line 473... | ||
| 462 | /* Finish debugging of all userspace threads */ |
473 | /* Finish debugging of all userspace threads */ |
| 463 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
474 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
| 464 | t = list_get_instance(cur, thread_t, th_link); |
475 | t = list_get_instance(cur, thread_t, th_link); |
| 465 | 476 | ||
| 466 | ipl = interrupts_disable(); |
477 | ipl = interrupts_disable(); |
| 467 | spinlock_lock(&t->debug_lock); |
478 | spinlock_lock(&t->udebug.lock); |
| 468 | spinlock_lock(&t->lock); |
479 | spinlock_lock(&t->lock); |
| 469 | 480 | ||
| 470 | flags = t->flags; |
481 | flags = t->flags; |
| 471 | 482 | ||
| 472 | spinlock_unlock(&t->lock); |
483 | spinlock_unlock(&t->lock); |
| 473 | 484 | ||
| 474 | /* Only process userspace threads */ |
485 | /* Only process userspace threads */ |
| 475 | if ((flags & THREAD_FLAG_USPACE) != 0) { |
486 | if ((flags & THREAD_FLAG_USPACE) != 0) { |
| 476 | /* Prevent any further debug activity in thread */ |
487 | /* Prevent any further debug activity in thread */ |
| 477 | t->debug_active = false; |
488 | t->udebug.debug_active = false; |
| 478 | t->cur_event = 0; /* none */ |
489 | t->udebug.cur_event = 0; /* none */ |
| 479 | 490 | ||
| 480 | /* Still has go? */ |
491 | /* Still has go? */ |
| 481 | if (t->debug_stop == false) { |
492 | if (t->udebug.stop == false) { |
| 482 | /* |
493 | /* |
| 483 | * Yes, so clear go. As debug_active == false, |
494 | * Yes, so clear go. As debug_active == false, |
| 484 | * this doesn't affect anything. |
495 | * this doesn't affect anything. |
| 485 | */ |
496 | */ |
| 486 | t->debug_stop = true; |
497 | t->udebug.stop = true; |
| 487 | 498 | ||
| 488 | /* Answer GO call */ |
499 | /* Answer GO call */ |
| 489 | klog_printf("answer GO call with EVENT_FINISHED"); |
500 | klog_printf("answer GO call with EVENT_FINISHED"); |
| 490 | IPC_SET_RETVAL(t->debug_go_call->data, 0); |
501 | IPC_SET_RETVAL(t->udebug.go_call->data, 0); |
| 491 | IPC_SET_ARG1(t->debug_go_call->data, UDEBUG_EVENT_FINISHED); |
502 | IPC_SET_ARG1(t->udebug.go_call->data, UDEBUG_EVENT_FINISHED); |
| 492 | /* FIXME: must not call with interrupts disabled!!*/ |
503 | /* FIXME: must not call with interrupts disabled!!*/ |
| 493 | ipc_answer(&ta->answerbox, t->debug_go_call); |
504 | ipc_answer(&ta->answerbox, t->udebug.go_call); |
| 494 | t->debug_go_call = NULL; |
505 | t->udebug.go_call = NULL; |
| 495 | } else { |
506 | } else { |
| 496 | /* |
507 | /* |
| 497 | * Debug_stop is already at initial value. |
508 | * Debug_stop is already at initial value. |
| 498 | * Yet this means the thread needs waking up. |
509 | * Yet this means the thread needs waking up. |
| 499 | */ |
510 | */ |
| 500 | 511 | ||
| 501 | /* |
512 | /* |
| 502 | * t's lock must not be held when calling |
513 | * t's lock must not be held when calling |
| 503 | * waitq_wakeup. |
514 | * waitq_wakeup. |
| 504 | */ |
515 | */ |
| 505 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
516 | waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST); |
| 506 | } |
517 | } |
| 507 | } |
518 | } |
| 508 | spinlock_unlock(&t->debug_lock); |
519 | spinlock_unlock(&t->udebug.lock); |
| 509 | interrupts_restore(ipl); |
520 | interrupts_restore(ipl); |
| 510 | } |
521 | } |
| 511 | 522 | ||
| 512 | ta->udebug.dt_state = UDEBUG_TS_INACTIVE; |
523 | ta->udebug.dt_state = UDEBUG_TS_INACTIVE; |
| 513 | ta->udebug.debugger = NULL; |
524 | ta->udebug.debugger = NULL; |