Subversion Repositories HelenOS

Rev

Rev 2872 | Rev 2874 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2872 Rev 2873
1
/** @addtogroup sctrace
1
/** @addtogroup sctrace
2
 * @{
2
 * @{
3
 */
3
 */
4
/** @file
4
/** @file
5
 */
5
 */
6
 
6
 
7
#include <stdio.h>
7
#include <stdio.h>
8
#include <unistd.h>
8
#include <unistd.h>
9
#include <syscall.h>
9
#include <syscall.h>
10
#include <ipc/ipc.h>
10
#include <ipc/ipc.h>
11
#include <fibril.h>
11
#include <fibril.h>
12
#include <errno.h>
12
#include <errno.h>
13
#include <udebug.h>
13
#include <udebug.h>
14
#include <async.h>
14
#include <async.h>
15
 
15
 
16
#include "syscalls.h"
16
#include "syscalls.h"
17
#include "ipc.h"
17
#include "ipc.h"
18
#include "errors.h"
18
#include "errors.h"
19
#include "debug_api.h"
19
#include "debug_api.h"
20
 
20
 
21
#define THBUF_SIZE 64
21
#define THBUF_SIZE 64
22
unsigned thread_hash_buf[THBUF_SIZE];
22
unsigned thread_hash_buf[THBUF_SIZE];
23
unsigned n_threads;
23
unsigned n_threads;
24
 
24
 
25
int next_thread_id;
25
int next_thread_id;
26
 
26
 
27
int phoneid;
27
int phoneid;
28
int abort_trace;
28
int abort_trace;
29
 
29
 
30
void thread_trace_start(unsigned thread_hash);
30
void thread_trace_start(unsigned thread_hash);
31
 
31
 
32
 
32
 
33
int task_connect(int taskid)
33
int task_connect(int taskid)
34
{
34
{
35
    int rc;
35
    int rc;
36
 
36
 
37
    printf("ipc_connect_task(%d)...\n", taskid);
37
    printf("ipc_connect_task(%d)...\n", taskid);
38
    rc = ipc_connect_kbox(taskid);
38
    rc = ipc_connect_kbox(taskid);
39
    printf("-> %d\n", rc);
39
    printf("-> %d\n", rc);
40
    phoneid = rc;
40
    phoneid = rc;
41
    if (rc < 0) return rc;
41
    if (rc < 0) return rc;
42
 
42
 
43
    printf("debug_begin()\n");
43
    printf("debug_begin()\n");
44
    rc = debug_begin(phoneid);
44
    rc = debug_begin(phoneid);
45
    printf("-> %d\n", rc);
45
    printf("-> %d\n", rc);
46
    if (rc < 0) return rc;
46
    if (rc < 0) return rc;
47
 
47
 
48
    return 0;
48
    return 0;
49
}
49
}
50
 
50
 
51
int get_thread_list(void)
51
int get_thread_list(void)
52
{
52
{
53
    int rc;
53
    int rc;
54
    int tb_copied;
54
    int tb_copied;
55
    int tb_needed;
55
    int tb_needed;
56
    int i;
56
    int i;
57
 
57
 
58
 
58
 
59
    printf("send IPC_M_DEBUG_THREAD_READ message\n");
59
    printf("send IPC_M_DEBUG_THREAD_READ message\n");
60
    rc = debug_thread_read(phoneid, (unsigned)thread_hash_buf,
60
    rc = debug_thread_read(phoneid, (unsigned)thread_hash_buf,
61
        THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
61
        THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
62
    printf("-> %d\n", rc);
62
    printf("-> %d\n", rc);
63
    if (rc < 0) return rc;
63
    if (rc < 0) return rc;
64
 
64
 
65
    n_threads = tb_copied / sizeof(unsigned);
65
    n_threads = tb_copied / sizeof(unsigned);
66
 
66
 
67
    printf("thread IDs:");
67
    printf("thread IDs:");
68
    for (i=0; i<n_threads; i++) {
68
    for (i=0; i<n_threads; i++) {
69
        printf(" %u", thread_hash_buf[i]);
69
        printf(" %u", thread_hash_buf[i]);
70
    }
70
    }
71
    printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned));
71
    printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned));
72
 
72
 
73
    return 0;
73
    return 0;
74
}
74
}
75
 
75
 
76
void print_sc_retval(int retval, rv_type_t rv_type)
76
void print_sc_retval(int retval, rv_type_t rv_type)
77
{
77
{
78
    printf (" -> ");
78
    printf (" -> ");
79
    if (rv_type == RV_INTEGER) {
79
    if (rv_type == RV_INTEGER) {
80
        printf("%d", retval);
80
        printf("%d", retval);
81
    } else if (rv_type == RV_HASH) {
81
    } else if (rv_type == RV_HASH) {
82
        printf("0x%08x", retval);
82
        printf("0x%08x", retval);
83
    } else if (rv_type == RV_ERRNO) {
83
    } else if (rv_type == RV_ERRNO) {
84
        if (retval >= -15 && retval <= 0) {
84
        if (retval >= -15 && retval <= 0) {
85
            printf("%d %s (%s)", retval,
85
            printf("%d %s (%s)", retval,
86
                err_desc[retval].name,
86
                err_desc[retval].name,
87
                err_desc[retval].desc);
87
                err_desc[retval].desc);
88
        } else {
88
        } else {
89
            printf("%d", retval);
89
            printf("%d", retval);
90
        }
90
        }
91
    } else if (rv_type == RV_INT_ERRNO) {
91
    } else if (rv_type == RV_INT_ERRNO) {
92
        if (retval >= -15 && retval < 0) {
92
        if (retval >= -15 && retval < 0) {
93
            printf("%d %s (%s)", retval,
93
            printf("%d %s (%s)", retval,
94
                err_desc[retval].name,
94
                err_desc[retval].name,
95
                err_desc[retval].desc);
95
                err_desc[retval].desc);
96
        } else {
96
        } else {
97
            printf("%d", retval);
97
            printf("%d", retval);
98
        }
98
        }
99
    }
99
    }
100
    putchar('\n');
100
    putchar('\n');
101
}
101
}
102
 
102
 
103
void print_sc_args(unsigned *sc_args, int n)
103
void print_sc_args(unsigned *sc_args, int n)
104
{
104
{
105
    int i;
105
    int i;
106
 
106
 
107
    putchar('(');
107
    putchar('(');
108
    if (n > 0) printf("%d", sc_args[0]);
108
    if (n > 0) printf("%d", sc_args[0]);
109
    for (i=1; i<n; i++) {
109
    for (i=1; i<n; i++) {
110
        printf(", %d", sc_args[i]);
110
        printf(", %d", sc_args[i]);
111
    }
111
    }
112
    putchar(')');
112
    putchar(')');
113
}
113
}
114
 
114
 
115
void sc_ipc_call_async_fast(unsigned *sc_args, int sc_rc)
115
void sc_ipc_call_async_fast(unsigned *sc_args, int sc_rc)
116
{
116
{
117
    ipc_call_t call;
117
    ipc_call_t call;
118
    int phoneid;
118
    int phoneid;
119
   
119
   
120
    if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
120
    if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
121
        return;
121
        return;
122
 
122
 
123
    phoneid = sc_args[0];
123
    phoneid = sc_args[0];
124
 
124
 
125
    IPC_SET_METHOD(call, sc_args[1]);
125
    IPC_SET_METHOD(call, sc_args[1]);
126
    IPC_SET_ARG1(call, sc_args[2]);
126
    IPC_SET_ARG1(call, sc_args[2]);
127
    IPC_SET_ARG2(call, sc_args[3]);
127
    IPC_SET_ARG2(call, sc_args[3]);
128
    IPC_SET_ARG3(call, sc_args[4]);
128
    IPC_SET_ARG3(call, sc_args[4]);
129
    IPC_SET_ARG4(call, sc_args[5]);
129
    IPC_SET_ARG4(call, sc_args[5]);
130
    IPC_SET_ARG5(call, 0);
130
    IPC_SET_ARG5(call, 0);
131
 
131
 
132
    ipc_parse_call_out(phoneid, &call, sc_rc);
132
    ipc_parse_call_out(phoneid, &call, sc_rc);
133
}
133
}
134
 
134
 
135
void sc_ipc_call_async_slow(unsigned *sc_args, int sc_rc)
135
void sc_ipc_call_async_slow(unsigned *sc_args, int sc_rc)
136
{
136
{
137
    ipc_call_t call;
137
    ipc_call_t call;
138
    int rc;
138
    int rc;
139
 
139
 
140
    if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
140
    if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
141
        return;
141
        return;
142
 
142
 
143
    memset(&call, 0, sizeof(call));
143
    memset(&call, 0, sizeof(call));
144
    rc = debug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args));
144
    rc = debug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args));
145
 
145
 
146
    if (rc >= 0) {
146
    if (rc >= 0) {
147
        ipc_parse_call_out(sc_args[0], &call, sc_rc);
147
        ipc_parse_call_out(sc_args[0], &call, sc_rc);
148
    }
148
    }
149
}
149
}
150
 
150
 
151
void sc_ipc_call_sync_fast(unsigned *sc_args)
151
void sc_ipc_call_sync_fast(unsigned *sc_args)
152
{
152
{
153
    ipc_call_t question, reply;
153
    ipc_call_t question, reply;
154
    int rc;
154
    int rc;
155
    int phoneidx;
155
    int phoneidx;
156
 
156
 
157
    printf("sc_ipc_call_sync_fast()\n");
157
    printf("sc_ipc_call_sync_fast()\n");
158
    phoneidx = sc_args[0];
158
    phoneidx = sc_args[0];
159
 
159
 
160
    IPC_SET_METHOD(question, sc_args[1]);
160
    IPC_SET_METHOD(question, sc_args[1]);
161
    IPC_SET_ARG1(question, sc_args[2]);
161
    IPC_SET_ARG1(question, sc_args[2]);
162
    IPC_SET_ARG2(question, sc_args[3]);
162
    IPC_SET_ARG2(question, sc_args[3]);
163
    IPC_SET_ARG3(question, sc_args[4]);
163
    IPC_SET_ARG3(question, sc_args[4]);
164
    IPC_SET_ARG4(question, 0);
164
    IPC_SET_ARG4(question, 0);
165
    IPC_SET_ARG5(question, 0);
165
    IPC_SET_ARG5(question, 0);
166
 
166
 
167
    printf("memset\n");
167
    printf("memset\n");
168
    memset(&reply, 0, sizeof(reply));
168
    memset(&reply, 0, sizeof(reply));
169
    printf("debug_mem_read(phone=%d, buffer_ptr=%u, src_addr=%d, n=%d\n",
169
    printf("debug_mem_read(phone=%d, buffer_ptr=%u, src_addr=%d, n=%d\n",
170
        phoneid, &reply.args, sc_args[5], sizeof(reply.args));
170
        phoneid, &reply.args, sc_args[5], sizeof(reply.args));
171
    rc = debug_mem_read(phoneid, &reply.args, sc_args[5], sizeof(reply.args));
171
    rc = debug_mem_read(phoneid, &reply.args, sc_args[5], sizeof(reply.args));
172
    printf("dmr->%d\n", rc);
172
    printf("dmr->%d\n", rc);
173
    if (rc < 0) return;
173
    if (rc < 0) return;
174
 
174
 
175
    printf("call ipc_parse_call_sync\n");
175
    printf("call ipc_parse_call_sync\n");
176
    ipc_parse_call_sync(phoneidx, &question, &reply);
176
    ipc_parse_call_sync(phoneidx, &question, &reply);
177
}
177
}
178
 
178
 
179
void sc_ipc_call_sync_slow(unsigned *sc_args)
179
void sc_ipc_call_sync_slow(unsigned *sc_args)
180
{
180
{
181
    ipc_call_t question, reply;
181
    ipc_call_t question, reply;
182
    int rc;
182
    int rc;
183
 
183
 
184
    memset(&question, 0, sizeof(question));
184
    memset(&question, 0, sizeof(question));
185
    rc = debug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args));
185
    rc = debug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args));
186
    printf("dmr->%d\n", rc);
186
    printf("dmr->%d\n", rc);
187
    if (rc < 0) return;
187
    if (rc < 0) return;
188
 
188
 
189
    memset(&reply, 0, sizeof(reply));
189
    memset(&reply, 0, sizeof(reply));
190
    rc = debug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args));
190
    rc = debug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args));
191
    printf("dmr->%d\n", rc);
191
    printf("dmr->%d\n", rc);
192
    if (rc < 0) return;
192
    if (rc < 0) return;
193
 
193
 
194
    ipc_parse_call_sync(sc_args[0], &question, &reply);
194
    ipc_parse_call_sync(sc_args[0], &question, &reply);
195
}
195
}
196
 
196
 
197
void sc_ipc_wait(unsigned *sc_args, int sc_rc)
197
void sc_ipc_wait(unsigned *sc_args, int sc_rc)
198
{
198
{
199
    ipc_call_t call;
199
    ipc_call_t call;
200
    int rc;
200
    int rc;
201
 
201
 
202
    if (sc_rc == 0) return 0;
202
    if (sc_rc == 0) return 0;
203
 
203
 
204
    memset(&call, 0, sizeof(call));
204
    memset(&call, 0, sizeof(call));
205
    rc = debug_mem_read(phoneid, &call, sc_args[0], sizeof(call));
205
    rc = debug_mem_read(phoneid, &call, sc_args[0], sizeof(call));
206
//  printf("debug_mem_read(phone %d, dest %d, app-mem src %d, size %d -> %d\n",
206
//  printf("debug_mem_read(phone %d, dest %d, app-mem src %d, size %d -> %d\n",
207
//      phoneid, (int)&call, sc_args[0], sizeof(call), rc);
207
//      phoneid, (int)&call, sc_args[0], sizeof(call), rc);
208
 
208
 
209
    if (rc >= 0) {
209
    if (rc >= 0) {
210
        ipc_parse_call_in(&call, sc_rc);
210
        ipc_parse_call_in(&call, sc_rc);
211
    }
211
    }
212
}
212
}
213
 
213
 
214
void event_syscall(unsigned thread_id, unsigned thread_hash,  unsigned sc_id, int sc_rc)
214
void event_syscall(unsigned thread_id, unsigned thread_hash,  unsigned sc_id, int sc_rc)
215
{
215
{
216
    unsigned sc_args[6];
216
    unsigned sc_args[6];
217
    int rv_type;
217
    int rv_type;
218
    int rc;
218
    int rc;
219
 
219
 
220
    /* Read syscall arguments */
220
    /* Read syscall arguments */
221
    rc = debug_args_read(phoneid, thread_hash, sc_args);
221
    rc = debug_args_read(phoneid, thread_hash, sc_args);
222
 
222
 
223
    async_serialize_start();
223
    async_serialize_start();
224
 
224
 
225
//  printf("[%d] ", thread_id);
225
//  printf("[%d] ", thread_id);
226
 
226
 
227
    if (rc < 0) {
227
    if (rc < 0) {
228
        printf("error\n");
228
        printf("error\n");
229
        async_serialize_end();
229
        async_serialize_end();
230
        return;
230
        return;
231
    }
231
    }
232
 
232
 
233
    /* Print syscall name, id and arguments */
233
    /* Print syscall name, id and arguments */
234
    printf("%s", syscall_desc[sc_id].name);
234
    printf("%s", syscall_desc[sc_id].name);
235
    print_sc_args(sc_args, syscall_desc[sc_id].n_args);
235
    print_sc_args(sc_args, syscall_desc[sc_id].n_args);
236
    rv_type = syscall_desc[sc_id].rv_type;
236
    rv_type = syscall_desc[sc_id].rv_type;
237
    print_sc_retval(sc_rc, rv_type);
237
    print_sc_retval(sc_rc, rv_type);
238
 
238
 
239
    switch (sc_id) {
239
    switch (sc_id) {
240
    case SYS_IPC_CALL_ASYNC_FAST:
240
    case SYS_IPC_CALL_ASYNC_FAST:
241
        sc_ipc_call_async_fast(sc_args, sc_rc);
241
        sc_ipc_call_async_fast(sc_args, sc_rc);
242
        break;
242
        break;
243
    case SYS_IPC_CALL_ASYNC_SLOW:
243
    case SYS_IPC_CALL_ASYNC_SLOW:
244
        sc_ipc_call_async_slow(sc_args, sc_rc);
244
        sc_ipc_call_async_slow(sc_args, sc_rc);
245
        break;
245
        break;
246
    case SYS_IPC_CALL_SYNC_FAST:
246
    case SYS_IPC_CALL_SYNC_FAST:
247
        sc_ipc_call_sync_fast(sc_args);
247
        sc_ipc_call_sync_fast(sc_args);
248
        break;
248
        break;
249
    case SYS_IPC_CALL_SYNC_SLOW:
249
    case SYS_IPC_CALL_SYNC_SLOW:
250
        sc_ipc_call_sync_slow(sc_args);
250
        sc_ipc_call_sync_slow(sc_args);
251
        break;
251
        break;
252
    case SYS_IPC_WAIT:
252
    case SYS_IPC_WAIT:
253
        sc_ipc_wait(sc_args, sc_rc);
253
        sc_ipc_wait(sc_args, sc_rc);
254
        break;
254
        break;
255
    default:
255
    default:
256
        break;
256
        break;
257
    }
257
    }
258
 
258
 
259
    async_serialize_end();
259
    async_serialize_end();
260
}
260
}
261
 
261
 
262
void event_new_thread(unsigned hash)
262
void event_new_thread(unsigned hash)
263
{
263
{
264
    async_serialize_start();
264
    async_serialize_start();
265
    printf("new thread, hash 0x%x\n", hash);
265
    printf("new thread, hash 0x%x\n", hash);
266
    async_serialize_end();
266
    async_serialize_end();
267
 
267
 
268
    thread_trace_start(hash);
268
    thread_trace_start(hash);
269
}
269
}
270
 
270
 
271
void trace_loop(void *thread_hash_arg)
271
void trace_loop(void *thread_hash_arg)
272
{
272
{
273
    int rc;
273
    int rc;
274
    unsigned ev_type;
274
    unsigned ev_type;
275
    unsigned thread_hash;
275
    unsigned thread_hash;
276
    unsigned thread_id;
276
    unsigned thread_id;
277
    unsigned val0, val1;
277
    unsigned val0, val1;
278
 
278
 
279
    thread_hash = (unsigned)thread_hash_arg;
279
    thread_hash = (unsigned)thread_hash_arg;
280
    thread_id = next_thread_id++;
280
    thread_id = next_thread_id++;
281
 
281
 
282
    printf("trace_loop(%d)\n", thread_id); 
282
    printf("trace_loop(%d)\n", thread_id); 
283
 
283
 
284
    while (!abort_trace) {
284
    while (!abort_trace) {
285
 
285
 
286
        /* Run thread until an event occurs */
286
        /* Run thread until an event occurs */
287
        rc = debug_go(phoneid, thread_hash,
287
        rc = debug_go(phoneid, thread_hash,
288
            &ev_type, &val0, &val1);
288
            &ev_type, &val0, &val1);
289
 
289
 
290
//      printf("rc = %d, ev_type=%d\n", rc, ev_type);
290
//      printf("rc = %d, ev_type=%d\n", rc, ev_type);
291
        if (ev_type == UDEBUG_EVENT_FINISHED) {
291
        if (ev_type == UDEBUG_EVENT_FINISHED) {
292
            printf("thread %u debugging finished\n", thread_id);
292
            printf("thread %u debugging finished\n", thread_id);
293
            break;
293
            break;
294
        }
294
        }
295
 
295
 
296
        if (rc >= 0) {
296
        if (rc >= 0) {
297
            switch (ev_type) {
297
            switch (ev_type) {
298
            case UDEBUG_EVENT_SYSCALL:
298
            case UDEBUG_EVENT_SYSCALL:
299
                event_syscall(thread_id, thread_hash, val0, (int)val1);
299
                event_syscall(thread_id, thread_hash, val0, (int)val1);
300
                break;
300
                break;
301
            case UDEBUG_EVENT_NEW_THREAD:
301
            case UDEBUG_EVENT_NEW_THREAD:
302
                event_new_thread(val0);
302
                event_new_thread(val0);
303
                break;
303
                break;
304
            default:
304
            default:
305
                printf("unknown event type %d\n", ev_type);
305
                printf("unknown event type %d\n", ev_type);
306
                break;
306
                break;
307
            }
307
            }
308
        }
308
        }
309
 
309
 
310
    }
310
    }
311
 
311
 
312
    printf("trace_loop(%d) exiting\n", thread_id);
312
    printf("trace_loop(%d) exiting\n", thread_id);
313
}
313
}
314
 
314
 
315
void thread_trace_start(unsigned thread_hash)
315
void thread_trace_start(unsigned thread_hash)
316
{
316
{
317
    fid_t fid;
317
    fid_t fid;
318
 
318
 
319
    fid = fibril_create(trace_loop, (void *)thread_hash);
319
    fid = fibril_create(trace_loop, (void *)thread_hash);
320
    if (fid == 0) {
320
    if (fid == 0) {
321
        printf("Warning: Failed creating fibril\n");
321
        printf("Warning: Failed creating fibril\n");
322
    }
322
    }
323
    fibril_add_ready(fid);
323
    fibril_add_ready(fid);
324
}
324
}
325
 
325
 
326
void trace_active_task(void)
326
void trace_active_task(void)
327
{
327
{
328
    int taskid;
328
    int taskid;
329
    int i;
329
    int i;
330
    int rc;
330
    int rc;
331
 
331
 
332
    printf("Syscall Tracer\n");
332
    printf("Syscall Tracer\n");
333
    printf("Press 'c' to connect\n");
333
    printf("Press 'c' to connect\n");
334
    while ((i = getchar()) != 'c')
334
    while ((i = getchar()) != 'c')
335
        putchar(i);
335
        putchar(i);
336
 
336
 
337
    taskid = 14;
337
    taskid = 14;
338
    rc = task_connect(taskid);
338
    rc = task_connect(taskid);
339
    if (rc < 0) {
339
    if (rc < 0) {
340
        printf("Failed to connect to task %d\n", taskid);
340
        printf("Failed to connect to task %d\n", taskid);
341
        return;
341
        return;
342
    }
342
    }
343
 
343
 
344
    printf("Connected to task %d\n", taskid);
344
    printf("Connected to task %d\n", taskid);
345
 
345
 
-
 
346
    ipcp_init();
-
 
347
 
346
    rc = get_thread_list();
348
    rc = get_thread_list();
347
    if (rc < 0) {
349
    if (rc < 0) {
348
        printf("Failed to get thread list (error %d)\n", rc);
350
        printf("Failed to get thread list (error %d)\n", rc);
349
        return;
351
        return;
350
    }
352
    }
351
 
353
 
352
    abort_trace = 0;
354
    abort_trace = 0;
353
 
355
 
354
    for (i = 0; i < n_threads; i++) {
356
    for (i = 0; i < n_threads; i++) {
355
        thread_trace_start(thread_hash_buf[i]);
357
        thread_trace_start(thread_hash_buf[i]);
356
    }
358
    }
357
 
359
 
358
    getchar();
360
    getchar();
359
 
361
 
360
    printf("terminate debugging session...\n");
362
    printf("terminate debugging session...\n");
361
    abort_trace = 1;
363
    abort_trace = 1;
362
    debug_end(phoneid);
364
    debug_end(phoneid);
363
    ipc_hangup(phoneid);
365
    ipc_hangup(phoneid);
364
 
366
 
-
 
367
    ipcp_cleanup();
-
 
368
 
365
    printf("done\n");
369
    printf("done\n");
366
    return;
370
    return;
367
}
371
}
368
 
372
 
369
int main(void)
373
int main(void)
370
{
374
{
371
    next_thread_id = 1;
375
    next_thread_id = 1;
372
 
376
 
373
    while (1) {
377
    while (1) {
374
        trace_active_task();
378
        trace_active_task();
375
    }
379
    }
376
}
380
}
377
 
381
 
378
/** @}
382
/** @}
379
 */
383
 */
380
 
384