Subversion Repositories HelenOS

Rev

Rev 2071 | Rev 2089 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2071 Rev 2087
Line 63... Line 63...
63
/** Spinlock protecting the tasks_btree B+tree. */
63
/** Spinlock protecting the tasks_btree B+tree. */
64
SPINLOCK_INITIALIZE(tasks_lock);
64
SPINLOCK_INITIALIZE(tasks_lock);
65
 
65
 
66
/** B+tree of active tasks.
66
/** B+tree of active tasks.
67
 *
67
 *
68
 * The task is guaranteed to exist after it was found in the tasks_btree as long as:
68
 * The task is guaranteed to exist after it was found in the tasks_btree as
-
 
69
 * long as:
69
 * @li the tasks_lock is held,
70
 * @li the tasks_lock is held,
70
 * @li the task's lock is held when task's lock is acquired before releasing tasks_lock or
71
 * @li the task's lock is held when task's lock is acquired before releasing
-
 
72
 *     tasks_lock or
71
 * @li the task's refcount is greater than 0
73
 * @li the task's refcount is greater than 0
72
 *
74
 *
73
 */
75
 */
74
btree_t tasks_btree;
76
btree_t tasks_btree;
75
 
77
 
Line 123... Line 125...
123
    ta->cycles = 0;
125
    ta->cycles = 0;
124
   
126
   
125
    ipc_answerbox_init(&ta->answerbox);
127
    ipc_answerbox_init(&ta->answerbox);
126
    for (i = 0; i < IPC_MAX_PHONES; i++)
128
    for (i = 0; i < IPC_MAX_PHONES; i++)
127
        ipc_phone_init(&ta->phones[i]);
129
        ipc_phone_init(&ta->phones[i]);
128
    if ((ipc_phone_0) && (context_check(ipc_phone_0->task->context, ta->context)))
130
    if ((ipc_phone_0) && (context_check(ipc_phone_0->task->context,
-
 
131
        ta->context)))
129
        ipc_phone_connect(&ta->phones[0], ipc_phone_0);
132
        ipc_phone_connect(&ta->phones[0], ipc_phone_0);
130
    atomic_set(&ta->active_calls, 0);
133
    atomic_set(&ta->active_calls, 0);
131
 
134
 
132
    mutex_initialize(&ta->futexes_lock);
135
    mutex_initialize(&ta->futexes_lock);
133
    btree_create(&ta->futexes);
136
    btree_create(&ta->futexes);
Line 200... Line 203...
200
        as_destroy(as);
203
        as_destroy(as);
201
        return NULL;
204
        return NULL;
202
    }
205
    }
203
   
206
   
204
    kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
207
    kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
-
 
208
    kernel_uarg->uspace_entry =
205
    kernel_uarg->uspace_entry = (void *) ((elf_header_t *) program_addr)->e_entry;
209
        (void *) ((elf_header_t *) program_addr)->e_entry;
206
    kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
210
    kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
207
    kernel_uarg->uspace_thread_function = NULL;
211
    kernel_uarg->uspace_thread_function = NULL;
208
    kernel_uarg->uspace_thread_arg = NULL;
212
    kernel_uarg->uspace_thread_arg = NULL;
209
    kernel_uarg->uspace_uarg = NULL;
213
    kernel_uarg->uspace_uarg = NULL;
210
   
214
   
Line 212... Line 216...
212
    ASSERT(task);
216
    ASSERT(task);
213
 
217
 
214
    /*
218
    /*
215
     * Create the data as_area.
219
     * Create the data as_area.
216
     */
220
     */
217
    a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
221
    a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
218
        LOADED_PROG_STACK_PAGES_NO*PAGE_SIZE,
222
        LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
219
        USTACK_ADDRESS, AS_AREA_ATTR_NONE, &anon_backend, NULL);
223
        AS_AREA_ATTR_NONE, &anon_backend, NULL);
220
 
224
 
221
    /*
225
    /*
222
     * Create the main thread.
226
     * Create the main thread.
223
     */
227
     */
224
    t1 = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, "uinit", false);
228
    t1 = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE,
-
 
229
        "uinit", false);
225
    ASSERT(t1);
230
    ASSERT(t1);
226
   
231
   
227
    /*
232
    /*
228
     * Create killer thread for the new task.
233
     * Create killer thread for the new task.
229
     */
234
     */
Line 236... Line 241...
236
    return task;
241
    return task;
237
}
242
}
238
 
243
 
239
/** Syscall for reading task ID from userspace.
244
/** Syscall for reading task ID from userspace.
240
 *
245
 *
241
 * @param uspace_task_id Userspace address of 8-byte buffer where to store current task ID.
246
 * @param uspace_task_id Userspace address of 8-byte buffer where to store
-
 
247
 * current task ID.
242
 *
248
 *
243
 * @return 0 on success or an error code from @ref errno.h.
249
 * @return 0 on success or an error code from @ref errno.h.
244
 */
250
 */
245
unative_t sys_task_get_id(task_id_t *uspace_task_id)
251
unative_t sys_task_get_id(task_id_t *uspace_task_id)
246
{
252
{
247
    /*
253
    /*
248
     * No need to acquire lock on TASK because taskid
254
     * No need to acquire lock on TASK because taskid
249
     * remains constant for the lifespan of the task.
255
     * remains constant for the lifespan of the task.
250
     */
256
     */
251
    return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, sizeof(TASK->taskid));
257
    return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid,
-
 
258
        sizeof(TASK->taskid));
252
}
259
}
253
 
260
 
254
/** Find task structure corresponding to task ID.
261
/** Find task structure corresponding to task ID.
255
 *
262
 *
256
 * The tasks_lock must be already held by the caller of this function
263
 * The tasks_lock must be already held by the caller of this function
Line 286... Line 293...
286
        thread_t *thr = list_get_instance(cur, thread_t, th_link);
293
        thread_t *thr = list_get_instance(cur, thread_t, th_link);
287
       
294
       
288
        spinlock_lock(&thr->lock);
295
        spinlock_lock(&thr->lock);
289
        /* Process only counted threads */
296
        /* Process only counted threads */
290
        if (!thr->uncounted) {
297
        if (!thr->uncounted) {
-
 
298
            if (thr == THREAD) {
291
            if (thr == THREAD) /* Update accounting of current thread */
299
                /* Update accounting of current thread */
292
                thread_update_accounting();
300
                thread_update_accounting();
-
 
301
            }
293
            ret += thr->cycles;
302
            ret += thr->cycles;
294
        }
303
        }
295
        spinlock_unlock(&thr->lock);
304
        spinlock_unlock(&thr->lock);
296
    }
305
    }
297
   
306
   
Line 374... Line 383...
374
   
383
   
375
    /* Messing with thread structures, avoid deadlock */
384
    /* Messing with thread structures, avoid deadlock */
376
    ipl = interrupts_disable();
385
    ipl = interrupts_disable();
377
    spinlock_lock(&tasks_lock);
386
    spinlock_lock(&tasks_lock);
378
   
387
   
379
    printf("taskid name       ctx address    as         cycles     threads calls  callee\n");
388
    printf("taskid name       ctx address    as         cycles     threads "
-
 
389
        "calls  callee\n");
380
    printf("------ ---------- --- ---------- ---------- ---------- ------- ------ ------>\n");
390
    printf("------ ---------- --- ---------- ---------- ---------- ------- "        "------ ------>\n");
381
 
391
 
382
    for (cur = tasks_btree.leaf_head.next; cur != &tasks_btree.leaf_head; cur = cur->next) {
392
    for (cur = tasks_btree.leaf_head.next; cur != &tasks_btree.leaf_head;
-
 
393
        cur = cur->next) {
383
        btree_node_t *node;
394
        btree_node_t *node;
384
        int i;
395
        int i;
385
       
396
       
386
        node = list_get_instance(cur, btree_node_t, leaf_link);
397
        node = list_get_instance(cur, btree_node_t, leaf_link);
387
        for (i = 0; i < node->keys; i++) {
398
        for (i = 0; i < node->keys; i++) {
Line 394... Line 405...
394
           
405
           
395
            uint64_t cycles;
406
            uint64_t cycles;
396
            char suffix;
407
            char suffix;
397
            order(task_get_accounting(t), &cycles, &suffix);
408
            order(task_get_accounting(t), &cycles, &suffix);
398
           
409
           
399
            printf("%-6lld %-10s %-3ld %#10zx %#10zx %9llu%c %7zd %6zd", t->taskid, t->name, t->context, t, t->as, cycles, suffix, t->refcount, atomic_get(&t->active_calls));
410
            printf("%-6lld %-10s %-3ld %#10zx %#10zx %9llu%c %7zd "
-
 
411
                "%6zd", t->taskid, t->name, t->context, t, t->as,
-
 
412
                cycles, suffix, t->refcount,
-
 
413
                atomic_get(&t->active_calls));
400
            for (j = 0; j < IPC_MAX_PHONES; j++) {
414
            for (j = 0; j < IPC_MAX_PHONES; j++) {
401
                if (t->phones[j].callee)
415
                if (t->phones[j].callee)
-
 
416
                    printf(" %zd:%#zx", j,
402
                    printf(" %zd:%#zx", j, t->phones[j].callee);
417
                        t->phones[j].callee);
403
            }
418
            }
404
            printf("\n");
419
            printf("\n");
405
           
420
           
406
            spinlock_unlock(&t->lock);
421
            spinlock_unlock(&t->lock);
407
        }
422
        }
Line 463... Line 478...
463
        scheduler();
478
        scheduler();
464
        goto loop;
479
        goto loop;
465
    }
480
    }
466
   
481
   
467
    if (t != THREAD) {
482
    if (t != THREAD) {
468
        ASSERT(t != main_thread);   /* uninit is joined and detached in ktaskgc */
483
        ASSERT(t != main_thread);   /* uninit is joined and detached
-
 
484
                         * in ktaskgc */
469
        thread_join(t);
485
        thread_join(t);
470
        thread_detach(t);
486
        thread_detach(t);
471
        goto loop;  /* go for another thread */
487
        goto loop;          /* go for another thread */
472
    }
488
    }
473
   
489
   
474
    /*
490
    /*
475
     * Now there are no other threads in this task
491
     * Now there are no other threads in this task
476
     * and no new threads can be created.
492
     * and no new threads can be created.
Line 495... Line 511...
495
loop:  
511
loop:  
496
    /*
512
    /*
497
     * Userspace threads cannot detach themselves,
513
     * Userspace threads cannot detach themselves,
498
     * therefore the thread pointer is guaranteed to be valid.
514
     * therefore the thread pointer is guaranteed to be valid.
499
     */
515
     */
500
    if (thread_join_timeout(t, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) {  /* sleep uninterruptibly here! */
516
    if (thread_join_timeout(t, 1000000, SYNCH_FLAGS_NONE) ==
-
 
517
        ESYNCH_TIMEOUT) {   /* sleep uninterruptibly here! */
501
        ipl_t ipl;
518
        ipl_t ipl;
502
        link_t *cur;
519
        link_t *cur;
503
        thread_t *thr = NULL;
520
        thread_t *thr = NULL;
504
   
521
   
505
        /*
522
        /*
506
         * The join timed out. Try to do some garbage collection of Undead threads.
523
         * The join timed out. Try to do some garbage collection of
-
 
524
         * Undead threads.
507
         */
525
         */
508
more_gc:       
526
more_gc:       
509
        ipl = interrupts_disable();
527
        ipl = interrupts_disable();
510
        spinlock_lock(&TASK->lock);
528
        spinlock_lock(&TASK->lock);
511
       
529
       
512
        for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
530
        for (cur = TASK->th_head.next; cur != &TASK->th_head;
-
 
531
            cur = cur->next) {
513
            thr = list_get_instance(cur, thread_t, th_link);
532
            thr = list_get_instance(cur, thread_t, th_link);
514
            spinlock_lock(&thr->lock);
533
            spinlock_lock(&thr->lock);
515
            if (thr != t && thr->state == Undead && thr->join_type == None) {
534
            if (thr != t && thr->state == Undead &&
-
 
535
                thr->join_type == None) {
516
                thr->join_type = TaskGC;
536
                thr->join_type = TaskGC;
517
                spinlock_unlock(&thr->lock);
537
                spinlock_unlock(&thr->lock);
518
                break;
538
                break;
519
            }
539
            }
520
            spinlock_unlock(&thr->lock);
540
            spinlock_unlock(&thr->lock);