Subversion Repositories HelenOS

Rev

Rev 4377 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4377 Rev 4692
Line 96... Line 96...
96
    rc = waitq_sleep_timeout_unsafe(wq, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
96
    rc = waitq_sleep_timeout_unsafe(wq, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
97
 
97
 
98
    waitq_sleep_finish(wq, rc, ipl);
98
    waitq_sleep_finish(wq, rc, ipl);
99
}
99
}
100
 
100
 
101
/** Do a preliminary check that a debugging session is in progress.
-
 
102
 *
-
 
103
 * This only requires the THREAD->udebug.lock mutex (and not TASK->udebug.lock
-
 
104
 * mutex). For an undebugged task, this will never block (while there could be
-
 
105
 * collisions by different threads on the TASK mutex), thus improving SMP
-
 
106
 * perormance for undebugged tasks.
-
 
107
 *
-
 
108
 * @return  True if the thread was in a debugging session when the function
-
 
109
 *      checked, false otherwise.
-
 
110
 */
-
 
111
static bool udebug_thread_precheck(void)
-
 
112
{
-
 
113
    bool res;
-
 
114
 
-
 
115
    mutex_lock(&THREAD->udebug.lock);
-
 
116
    res = THREAD->udebug.active;
-
 
117
    mutex_unlock(&THREAD->udebug.lock);
-
 
118
 
-
 
119
    return res;
-
 
120
}
-
 
121
 
-
 
122
/** Start of stoppable section.
101
/** Start of stoppable section.
123
 *
102
 *
124
 * A stoppable section is a section of code where if the thread can be stoped. In other words,
103
 * A stoppable section is a section of code where if the thread can be stoped. In other words,
125
 * if a STOP operation is issued, the thread is guaranteed not to execute
104
 * if a STOP operation is issued, the thread is guaranteed not to execute
126
 * any userspace instructions until the thread is resumed.
105
 * any userspace instructions until the thread is resumed.
Line 135... Line 114...
135
    call_t *db_call, *go_call;
114
    call_t *db_call, *go_call;
136
 
115
 
137
    ASSERT(THREAD);
116
    ASSERT(THREAD);
138
    ASSERT(TASK);
117
    ASSERT(TASK);
139
 
118
 
140
    /* Early check for undebugged tasks */
-
 
141
    if (!udebug_thread_precheck()) {
-
 
142
        return;
-
 
143
    }
-
 
144
 
-
 
145
    mutex_lock(&TASK->udebug.lock);
119
    mutex_lock(&TASK->udebug.lock);
146
 
120
 
147
    nsc = --TASK->udebug.not_stoppable_count;
121
    nsc = --TASK->udebug.not_stoppable_count;
148
 
122
 
149
    /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
123
    /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
Line 200... Line 174...
200
 * This is the point where the thread will block if it is stopped.
174
 * This is the point where the thread will block if it is stopped.
201
 * (As, by definition, a stopped thread must not leave its stoppable section).
175
 * (As, by definition, a stopped thread must not leave its stoppable section).
202
 */
176
 */
203
void udebug_stoppable_end(void)
177
void udebug_stoppable_end(void)
204
{
178
{
205
    /* Early check for undebugged tasks */
-
 
206
    if (!udebug_thread_precheck()) {
-
 
207
        return;
-
 
208
    }
-
 
209
 
-
 
210
restart:
179
restart:
211
    mutex_lock(&TASK->udebug.lock);
180
    mutex_lock(&TASK->udebug.lock);
212
    mutex_lock(&THREAD->udebug.lock);
181
    mutex_lock(&THREAD->udebug.lock);
213
 
182
 
214
    if (THREAD->udebug.active && THREAD->udebug.go == false) {
183
    if (THREAD->udebug.active && THREAD->udebug.go == false) {
Line 253... Line 222...
253
    call_t *call;
222
    call_t *call;
254
    udebug_event_t etype;
223
    udebug_event_t etype;
255
 
224
 
256
    etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B;
225
    etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B;
257
 
226
 
258
    /* Early check for undebugged tasks */
-
 
259
    if (!udebug_thread_precheck()) {
-
 
260
        return;
-
 
261
    }
-
 
262
 
-
 
263
    mutex_lock(&TASK->udebug.lock);
227
    mutex_lock(&TASK->udebug.lock);
264
    mutex_lock(&THREAD->udebug.lock);
228
    mutex_lock(&THREAD->udebug.lock);
265
 
229
 
266
    /* Must only generate events when in debugging session and is go. */
230
    /* Must only generate events when in debugging session and is go. */
267
    if (THREAD->udebug.active != true || THREAD->udebug.go == false ||
231
    if (THREAD->udebug.active != true || THREAD->udebug.go == false ||
Line 269... Line 233...
269
        mutex_unlock(&THREAD->udebug.lock);
233
        mutex_unlock(&THREAD->udebug.lock);
270
        mutex_unlock(&TASK->udebug.lock);
234
        mutex_unlock(&TASK->udebug.lock);
271
        return;
235
        return;
272
    }
236
    }
273
 
237
 
274
    //printf("udebug_syscall_event\n");
238
    /* Fill in the GO response. */
275
    call = THREAD->udebug.go_call;
239
    call = THREAD->udebug.go_call;
276
    THREAD->udebug.go_call = NULL;
240
    THREAD->udebug.go_call = NULL;
277
 
241
 
278
    IPC_SET_RETVAL(call->data, 0);
242
    IPC_SET_RETVAL(call->data, 0);
279
    IPC_SET_ARG1(call->data, etype);
243
    IPC_SET_ARG1(call->data, etype);
280
    IPC_SET_ARG2(call->data, id);
244
    IPC_SET_ARG2(call->data, id);
281
    IPC_SET_ARG3(call->data, rc);
245
    IPC_SET_ARG3(call->data, rc);
282
    //printf("udebug_syscall_event/ipc_answer\n");
-
 
283
 
246
 
284
    THREAD->udebug.syscall_args[0] = a1;
247
    THREAD->udebug.syscall_args[0] = a1;
285
    THREAD->udebug.syscall_args[1] = a2;
248
    THREAD->udebug.syscall_args[1] = a2;
286
    THREAD->udebug.syscall_args[2] = a3;
249
    THREAD->udebug.syscall_args[2] = a3;
287
    THREAD->udebug.syscall_args[3] = a4;
250
    THREAD->udebug.syscall_args[3] = a4;
Line 327... Line 290...
327
    mutex_lock(&TASK->udebug.lock);
290
    mutex_lock(&TASK->udebug.lock);
328
    mutex_lock(&THREAD->udebug.lock);
291
    mutex_lock(&THREAD->udebug.lock);
329
 
292
 
330
    thread_attach(t, ta);
293
    thread_attach(t, ta);
331
 
294
 
332
    LOG("udebug_thread_b_event\n");
-
 
333
    LOG("- check state\n");
295
    LOG("Check state");
334
 
296
 
335
    /* Must only generate events when in debugging session */
297
    /* Must only generate events when in debugging session */
336
    if (THREAD->udebug.active != true) {
298
    if (THREAD->udebug.active != true) {
337
        LOG("- udebug.active: %s, udebug.go: %s\n",
299
        LOG("udebug.active: %s, udebug.go: %s",
338
            THREAD->udebug.active ? "yes(+)" : "no(-)",
300
            THREAD->udebug.active ? "Yes(+)" : "No",
339
            THREAD->udebug.go ? "yes(-)" : "no(+)");
301
            THREAD->udebug.go ? "Yes(-)" : "No");
340
        mutex_unlock(&THREAD->udebug.lock);
302
        mutex_unlock(&THREAD->udebug.lock);
341
        mutex_unlock(&TASK->udebug.lock);
303
        mutex_unlock(&TASK->udebug.lock);
342
        return;
304
        return;
343
    }
305
    }
344
 
306
 
345
    LOG("- trigger event\n");
307
    LOG("Trigger event");
346
 
-
 
347
    call = THREAD->udebug.go_call;
308
    call = THREAD->udebug.go_call;
348
    THREAD->udebug.go_call = NULL;
309
    THREAD->udebug.go_call = NULL;
349
    IPC_SET_RETVAL(call->data, 0);
310
    IPC_SET_RETVAL(call->data, 0);
350
    IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B);
311
    IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B);
351
    IPC_SET_ARG2(call->data, (unative_t)t);
312
    IPC_SET_ARG2(call->data, (unative_t)t);
Line 361... Line 322...
361
    ipc_answer(&TASK->answerbox, call);
322
    ipc_answer(&TASK->answerbox, call);
362
 
323
 
363
    mutex_unlock(&THREAD->udebug.lock);
324
    mutex_unlock(&THREAD->udebug.lock);
364
    mutex_unlock(&TASK->udebug.lock);
325
    mutex_unlock(&TASK->udebug.lock);
365
 
326
 
366
    LOG("- sleep\n");
327
    LOG("Wait for Go");
367
    udebug_wait_for_go(&THREAD->udebug.go_wq);
328
    udebug_wait_for_go(&THREAD->udebug.go_wq);
368
}
329
}
369
 
330
 
370
/** Thread-termination event hook.
331
/** Thread-termination event hook.
371
 *
332
 *
Line 377... Line 338...
377
    call_t *call;
338
    call_t *call;
378
 
339
 
379
    mutex_lock(&TASK->udebug.lock);
340
    mutex_lock(&TASK->udebug.lock);
380
    mutex_lock(&THREAD->udebug.lock);
341
    mutex_lock(&THREAD->udebug.lock);
381
 
342
 
382
    LOG("udebug_thread_e_event\n");
-
 
383
    LOG("- check state\n");
343
    LOG("Check state");
384
 
344
 
385
    /* Must only generate events when in debugging session. */
345
    /* Must only generate events when in debugging session. */
386
    if (THREAD->udebug.active != true) {
346
    if (THREAD->udebug.active != true) {
387
/*      printf("- udebug.active: %s, udebug.go: %s\n",
347
        LOG("udebug.active: %s, udebug.go: %s",
388
            THREAD->udebug.active ? "yes(+)" : "no(-)",
348
            THREAD->udebug.active ? "Yes" : "No",
389
            THREAD->udebug.go ? "yes(-)" : "no(+)");*/
349
            THREAD->udebug.go ? "Yes" : "No");
390
        mutex_unlock(&THREAD->udebug.lock);
350
        mutex_unlock(&THREAD->udebug.lock);
391
        mutex_unlock(&TASK->udebug.lock);
351
        mutex_unlock(&TASK->udebug.lock);
392
        return;
352
        return;
393
    }
353
    }
394
 
354
 
395
    LOG("- trigger event\n");
355
    LOG("Trigger event");
396
 
-
 
397
    call = THREAD->udebug.go_call;
356
    call = THREAD->udebug.go_call;
398
    THREAD->udebug.go_call = NULL;
357
    THREAD->udebug.go_call = NULL;
399
    IPC_SET_RETVAL(call->data, 0);
358
    IPC_SET_RETVAL(call->data, 0);
400
    IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E);
359
    IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E);
401
 
360
 
Line 486... Line 445...
486
    thread_t *t;
445
    thread_t *t;
487
    link_t *cur;
446
    link_t *cur;
488
    int flags;
447
    int flags;
489
    ipl_t ipl;
448
    ipl_t ipl;
490
 
449
 
491
    LOG("udebug_task_cleanup()\n");
-
 
492
    LOG("task %" PRIu64 "\n", ta->taskid);
-
 
493
 
-
 
494
    if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
450
    if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
495
        ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
451
        ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
496
        LOG("udebug_task_cleanup(): task not being debugged\n");
-
 
497
        return EINVAL;
452
        return EINVAL;
498
    }
453
    }
499
 
454
 
-
 
455
    LOG("Task %" PRIu64, ta->taskid);
-
 
456
 
500
    /* Finish debugging of all userspace threads */
457
    /* Finish debugging of all userspace threads */
501
    for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
458
    for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
502
        t = list_get_instance(cur, thread_t, th_link);
459
        t = list_get_instance(cur, thread_t, th_link);
503
 
460
 
504
        mutex_lock(&t->udebug.lock);
461
        mutex_lock(&t->udebug.lock);
Line 524... Line 481...
524
                 * this doesn't affect anything.
481
                 * this doesn't affect anything.
525
                 */
482
                 */
526
                t->udebug.go = false;  
483
                t->udebug.go = false;  
527
 
484
 
528
                /* Answer GO call */
485
                /* Answer GO call */
529
                LOG("answer GO call with EVENT_FINISHED\n");
486
                LOG("Answer GO call with EVENT_FINISHED.");
530
                IPC_SET_RETVAL(t->udebug.go_call->data, 0);
487
                IPC_SET_RETVAL(t->udebug.go_call->data, 0);
531
                IPC_SET_ARG1(t->udebug.go_call->data,
488
                IPC_SET_ARG1(t->udebug.go_call->data,
532
                    UDEBUG_EVENT_FINISHED);
489
                    UDEBUG_EVENT_FINISHED);
533
 
490
 
534
                ipc_answer(&ta->answerbox, t->udebug.go_call);
491
                ipc_answer(&ta->answerbox, t->udebug.go_call);