Subversion Repositories HelenOS

Rev

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

Rev 2131 Rev 2307
Line 39... Line 39...
39
#include <proc/thread.h>
39
#include <proc/thread.h>
40
#include <proc/task.h>
40
#include <proc/task.h>
41
#include <proc/uarg.h>
41
#include <proc/uarg.h>
42
#include <mm/as.h>
42
#include <mm/as.h>
43
#include <mm/slab.h>
43
#include <mm/slab.h>
-
 
44
#include <atomic.h>
44
#include <synch/spinlock.h>
45
#include <synch/spinlock.h>
45
#include <synch/waitq.h>
46
#include <synch/waitq.h>
46
#include <arch.h>
47
#include <arch.h>
47
#include <panic.h>
48
#include <panic.h>
48
#include <adt/btree.h>
49
#include <adt/btree.h>
Line 90... Line 91...
90
{
91
{
91
    TASK = NULL;
92
    TASK = NULL;
92
    btree_create(&tasks_btree);
93
    btree_create(&tasks_btree);
93
}
94
}
94
 
95
 
-
 
96
/** Kill all tasks except the current task.
-
 
97
 *
-
 
98
 */
-
 
99
void task_done(void)
-
 
100
{
-
 
101
    task_t *t;
-
 
102
    do { /* Repeat until there are any tasks except TASK */
-
 
103
       
-
 
104
        /* Messing with task structures, avoid deadlock */
-
 
105
        ipl_t ipl = interrupts_disable();
-
 
106
        spinlock_lock(&tasks_lock);
-
 
107
       
-
 
108
        t = NULL;
-
 
109
        link_t *cur;
-
 
110
        for (cur = tasks_btree.leaf_head.next; cur != &tasks_btree.leaf_head; cur = cur->next) {
-
 
111
            btree_node_t *node = list_get_instance(cur, btree_node_t, leaf_link);
-
 
112
           
-
 
113
            unsigned int i;
-
 
114
            for (i = 0; i < node->keys; i++) {
-
 
115
                if ((task_t *) node->value[i] != TASK) {
-
 
116
                    t = (task_t *) node->value[i];
-
 
117
                    break;
-
 
118
                }
-
 
119
            }
-
 
120
        }
-
 
121
       
-
 
122
        if (t != NULL) {
-
 
123
            task_id_t id = t->taskid;
-
 
124
           
-
 
125
            spinlock_unlock(&tasks_lock);
-
 
126
            interrupts_restore(ipl);
-
 
127
           
-
 
128
#ifdef CONFIG_DEBUG
-
 
129
            printf("Killing task %llu\n", id);
-
 
130
#endif          
-
 
131
            task_kill(id);
-
 
132
        } else {
-
 
133
            spinlock_unlock(&tasks_lock);
-
 
134
            interrupts_restore(ipl);
-
 
135
        }
-
 
136
       
-
 
137
    } while (t != NULL);
-
 
138
}
95
 
139
 
96
/** Create new task
140
/** Create new task
97
 *
141
 *
98
 * Create new task with no threads.
142
 * Create new task with no threads.
99
 *
143
 *
Line 138... Line 182...
138
   
182
   
139
    ipl = interrupts_disable();
183
    ipl = interrupts_disable();
140
 
184
 
141
    /*
185
    /*
142
     * Increment address space reference count.
186
     * Increment address space reference count.
143
     * TODO: Reconsider the locking scheme.
-
 
144
     */
187
     */
145
    mutex_lock(&as->lock);
188
    atomic_inc(&as->refcount);
146
    as->refcount++;
-
 
147
    mutex_unlock(&as->lock);
-
 
148
 
189
 
149
    spinlock_lock(&tasks_lock);
190
    spinlock_lock(&tasks_lock);
150
 
191
 
151
    ta->taskid = ++task_counter;
192
    ta->taskid = ++task_counter;
152
    btree_insert(&tasks_btree, (btree_key_t) ta->taskid, (void *) ta, NULL);
193
    btree_insert(&tasks_btree, (btree_key_t) ta->taskid, (void *) ta, NULL);
Line 164... Line 205...
164
void task_destroy(task_t *t)
205
void task_destroy(task_t *t)
165
{
206
{
166
    task_destroy_arch(t);
207
    task_destroy_arch(t);
167
    btree_destroy(&t->futexes);
208
    btree_destroy(&t->futexes);
168
 
209
 
169
    mutex_lock_active(&t->as->lock);
-
 
170
    if (--t->as->refcount == 0) {
210
    if (atomic_predec(&t->as->refcount) == 0)
171
        mutex_unlock(&t->as->lock);
-
 
172
        as_destroy(t->as);
211
        as_destroy(t->as);
173
        /*
-
 
174
         * t->as is destroyed.
-
 
175
         */
-
 
176
    } else
-
 
177
        mutex_unlock(&t->as->lock);
-
 
178
   
212
   
179
    free(t);
213
    free(t);
180
    TASK = NULL;
214
    TASK = NULL;
181
}
215
}
182
 
216
 
Line 380... Line 414...
380
void task_print_list(void)
414
void task_print_list(void)
381
{
415
{
382
    link_t *cur;
416
    link_t *cur;
383
    ipl_t ipl;
417
    ipl_t ipl;
384
   
418
   
385
    /* Messing with thread structures, avoid deadlock */
419
    /* Messing with task structures, avoid deadlock */
386
    ipl = interrupts_disable();
420
    ipl = interrupts_disable();
387
    spinlock_lock(&tasks_lock);
421
    spinlock_lock(&tasks_lock);
388
   
422
   
389
    printf("taskid name       ctx address    as         cycles     threads "
423
    printf("taskid name       ctx address    as         cycles     threads "
390
        "calls  callee\n");
424
        "calls  callee\n");
Line 406... Line 440...
406
           
440
           
407
            uint64_t cycles;
441
            uint64_t cycles;
408
            char suffix;
442
            char suffix;
409
            order(task_get_accounting(t), &cycles, &suffix);
443
            order(task_get_accounting(t), &cycles, &suffix);
410
           
444
           
411
            printf("%-6lld %-10s %-3ld %#10zx %#10zx %9llu%c %7zd "
445
            printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd "
412
                "%6zd", t->taskid, t->name, t->context, t, t->as,
446
                "%6zd", t->taskid, t->name, t->context, t, t->as,
413
                cycles, suffix, t->refcount,
447
                cycles, suffix, t->refcount,
414
                atomic_get(&t->active_calls));
448
                atomic_get(&t->active_calls));
415
            for (j = 0; j < IPC_MAX_PHONES; j++) {
449
            for (j = 0; j < IPC_MAX_PHONES; j++) {
416
                if (t->phones[j].callee)
450
                if (t->phones[j].callee)
Line 493... Line 527...
493
     * and no new threads can be created.
527
     * and no new threads can be created.
494
     */
528
     */
495
 
529
 
496
    ipc_cleanup();
530
    ipc_cleanup();
497
    futex_cleanup();
531
    futex_cleanup();
498
    klog_printf("Cleanup of task %lld completed.", TASK->taskid);
532
    klog_printf("Cleanup of task %llu completed.", TASK->taskid);
499
}
533
}
500
 
534
 
501
/** Kernel thread used to kill the userspace task when its main thread exits.
535
/** Kernel thread used to kill the userspace task when its main thread exits.
502
 *
536
 *
503
 * This thread waits until the main userspace thread (i.e. uninit) exits.
537
 * This thread waits until the main userspace thread (i.e. uninit) exits.