Subversion Repositories HelenOS

Rev

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

Rev 4342 Rev 4389
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 430... Line 389...
430
    thread_t *t;
389
    thread_t *t;
431
    link_t *cur;
390
    link_t *cur;
432
    int flags;
391
    int flags;
433
    ipl_t ipl;
392
    ipl_t ipl;
434
 
393
 
435
    LOG("udebug_task_cleanup()\n");
-
 
436
    LOG("task %" PRIu64 "\n", ta->taskid);
-
 
437
 
-
 
438
    if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
394
    if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
439
        ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
395
        ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
440
        LOG("udebug_task_cleanup(): task not being debugged\n");
-
 
441
        return EINVAL;
396
        return EINVAL;
442
    }
397
    }
443
 
398
 
-
 
399
    LOG("Task %" PRIu64, ta->taskid);
-
 
400
 
444
    /* Finish debugging of all userspace threads */
401
    /* Finish debugging of all userspace threads */
445
    for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
402
    for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
446
        t = list_get_instance(cur, thread_t, th_link);
403
        t = list_get_instance(cur, thread_t, th_link);
447
 
404
 
448
        mutex_lock(&t->udebug.lock);
405
        mutex_lock(&t->udebug.lock);
Line 468... Line 425...
468
                 * this doesn't affect anything.
425
                 * this doesn't affect anything.
469
                 */
426
                 */
470
                t->udebug.go = false;  
427
                t->udebug.go = false;  
471
 
428
 
472
                /* Answer GO call */
429
                /* Answer GO call */
473
                LOG("answer GO call with EVENT_FINISHED\n");
430
                LOG("Answer GO call with EVENT_FINISHED.");
474
                IPC_SET_RETVAL(t->udebug.go_call->data, 0);
431
                IPC_SET_RETVAL(t->udebug.go_call->data, 0);
475
                IPC_SET_ARG1(t->udebug.go_call->data,
432
                IPC_SET_ARG1(t->udebug.go_call->data,
476
                    UDEBUG_EVENT_FINISHED);
433
                    UDEBUG_EVENT_FINISHED);
477
 
434
 
478
                ipc_answer(&ta->answerbox, t->udebug.go_call);
435
                ipc_answer(&ta->answerbox, t->udebug.go_call);