Changeset da1bafb in mainline for kernel/generic/src/proc/task.c
- Timestamp:
- 2010-05-24T18:57:31Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0095368
- Parents:
- 666f492
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/proc/task.c
r666f492 rda1bafb 60 60 61 61 /** Spinlock protecting the tasks_tree AVL tree. */ 62 SPINLOCK_INITIALIZE(tasks_lock);62 IRQ_SPINLOCK_INITIALIZE(tasks_lock); 63 63 64 64 /** AVL tree of active tasks. … … 81 81 /* Forward declarations. */ 82 82 static void task_kill_internal(task_t *); 83 static int tsk_constructor(void *, int); 84 85 /** Initialize kernel tasks support. */ 83 static int tsk_constructor(void *, unsigned int); 84 85 /** Initialize kernel tasks support. 86 * 87 */ 86 88 void task_init(void) 87 89 { … … 92 94 } 93 95 94 /* 96 /** Task finish walker. 97 * 95 98 * The idea behind this walker is to kill and count all tasks different from 96 99 * TASK. 100 * 97 101 */ 98 102 static bool task_done_walker(avltree_node_t *node, void *arg) 99 103 { 100 task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);101 unsigned *cnt = (unsigned*) arg;102 103 if (t != TASK) {104 task_t *task = avltree_get_instance(node, task_t, tasks_tree_node); 105 size_t *cnt = (size_t *) arg; 106 107 if (task != TASK) { 104 108 (*cnt)++; 109 105 110 #ifdef CONFIG_DEBUG 106 printf("[%"PRIu64"] ", t->taskid); 107 #endif 108 task_kill_internal(t); 111 printf("[%"PRIu64"] ", task->taskid); 112 #endif 113 114 task_kill_internal(task); 109 115 } 110 116 … … 113 119 } 114 120 115 /** Kill all tasks except the current task. */ 121 /** Kill all tasks except the current task. 122 * 123 */ 116 124 void task_done(void) 117 125 { 118 unsignedtasks_left;119 120 do {/* Repeat until there are any tasks except TASK */121 /* Messing with task structures, avoid deadlock */126 size_t tasks_left; 127 128 /* Repeat until there are any tasks except TASK */ 129 do { 122 130 #ifdef CONFIG_DEBUG 123 131 printf("Killing tasks... "); 124 132 #endif 125 ipl_t ipl = interrupts_disable();126 spinlock_lock(&tasks_lock);133 134 irq_spinlock_lock(&tasks_lock, true); 127 135 tasks_left = 0; 128 136 avltree_walk(&tasks_tree, task_done_walker, &tasks_left); 129 spinlock_unlock(&tasks_lock);130 interrupts_restore(ipl);137 irq_spinlock_unlock(&tasks_lock, true); 138 131 139 thread_sleep(1); 140 132 141 #ifdef CONFIG_DEBUG 133 142 printf("\n"); 134 143 #endif 135 } while (tasks_left); 136 } 137 138 int tsk_constructor(void *obj, int kmflags) 139 { 140 task_t *ta = obj; 141 int i; 142 143 atomic_set(&ta->refcount, 0); 144 atomic_set(&ta->lifecount, 0); 145 atomic_set(&ta->active_calls, 0); 146 147 spinlock_initialize(&ta->lock, "task_ta_lock"); 148 mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE); 149 150 list_initialize(&ta->th_head); 151 list_initialize(&ta->sync_box_head); 152 153 ipc_answerbox_init(&ta->answerbox, ta); 144 } while (tasks_left > 0); 145 } 146 147 int tsk_constructor(void *obj, unsigned int kmflags) 148 { 149 task_t *task = (task_t *) obj; 150 151 atomic_set(&task->refcount, 0); 152 atomic_set(&task->lifecount, 0); 153 atomic_set(&task->active_calls, 0); 154 155 irq_spinlock_initialize(&task->lock, "task_t_lock"); 156 mutex_initialize(&task->futexes_lock, MUTEX_PASSIVE); 157 158 list_initialize(&task->th_head); 159 list_initialize(&task->sync_box_head); 160 161 ipc_answerbox_init(&task->answerbox, task); 162 163 size_t i; 154 164 for (i = 0; i < IPC_MAX_PHONES; i++) 155 ipc_phone_init(&ta ->phones[i]);165 ipc_phone_init(&task->phones[i]); 156 166 157 167 #ifdef CONFIG_UDEBUG 158 168 /* Init kbox stuff */ 159 ta ->kb.thread = NULL;160 ipc_answerbox_init(&ta ->kb.box, ta);161 mutex_initialize(&ta ->kb.cleanup_lock, MUTEX_PASSIVE);169 task->kb.thread = NULL; 170 ipc_answerbox_init(&task->kb.box, task); 171 mutex_initialize(&task->kb.cleanup_lock, MUTEX_PASSIVE); 162 172 #endif 163 173 … … 175 185 task_t *task_create(as_t *as, const char *name) 176 186 { 177 ipl_t ipl; 178 task_t *ta; 179 180 ta = (task_t *) slab_alloc(task_slab, 0); 181 task_create_arch(ta); 182 ta->as = as; 183 memcpy(ta->name, name, TASK_NAME_BUFLEN); 184 ta->name[TASK_NAME_BUFLEN - 1] = 0; 185 186 ta->context = CONTEXT; 187 ta->capabilities = 0; 188 ta->ucycles = 0; 189 ta->kcycles = 0; 190 191 ta->ipc_info.call_sent = 0; 192 ta->ipc_info.call_recieved = 0; 193 ta->ipc_info.answer_sent = 0; 194 ta->ipc_info.answer_recieved = 0; 195 ta->ipc_info.irq_notif_recieved = 0; 196 ta->ipc_info.forwarded = 0; 197 187 task_t *task = (task_t *) slab_alloc(task_slab, 0); 188 task_create_arch(task); 189 190 task->as = as; 191 str_cpy(task->name, TASK_NAME_BUFLEN, name); 192 193 task->context = CONTEXT; 194 task->capabilities = 0; 195 task->ucycles = 0; 196 task->kcycles = 0; 197 198 task->ipc_info.call_sent = 0; 199 task->ipc_info.call_recieved = 0; 200 task->ipc_info.answer_sent = 0; 201 task->ipc_info.answer_recieved = 0; 202 task->ipc_info.irq_notif_recieved = 0; 203 task->ipc_info.forwarded = 0; 204 198 205 #ifdef CONFIG_UDEBUG 199 206 /* Init debugging stuff */ 200 udebug_task_init(&ta ->udebug);207 udebug_task_init(&task->udebug); 201 208 202 209 /* Init kbox stuff */ 203 ta ->kb.finished = false;210 task->kb.finished = false; 204 211 #endif 205 212 206 213 if ((ipc_phone_0) && 207 (context_check(ipc_phone_0->task->context, ta ->context)))208 ipc_phone_connect(&ta ->phones[0], ipc_phone_0);209 210 btree_create(&ta ->futexes);214 (context_check(ipc_phone_0->task->context, task->context))) 215 ipc_phone_connect(&task->phones[0], ipc_phone_0); 216 217 btree_create(&task->futexes); 211 218 212 219 /* 213 220 * Get a reference to the address space. 214 221 */ 215 as_hold(ta ->as);216 217 i pl = interrupts_disable();218 spinlock_lock(&tasks_lock);219 ta ->taskid = ++task_counter;220 avltree_node_initialize(&ta ->tasks_tree_node);221 ta ->tasks_tree_node.key = ta->taskid;222 avltree_insert(&tasks_tree, &ta ->tasks_tree_node);223 spinlock_unlock(&tasks_lock);224 i nterrupts_restore(ipl);225 226 return ta ;222 as_hold(task->as); 223 224 irq_spinlock_lock(&tasks_lock, true); 225 226 task->taskid = ++task_counter; 227 avltree_node_initialize(&task->tasks_tree_node); 228 task->tasks_tree_node.key = task->taskid; 229 avltree_insert(&tasks_tree, &task->tasks_tree_node); 230 231 irq_spinlock_unlock(&tasks_lock, true); 232 233 return task; 227 234 } 228 235 229 236 /** Destroy task. 230 237 * 231 * @param t Task to be destroyed.232 * 233 */ 234 void task_destroy(task_t *t )238 * @param task Task to be destroyed. 239 * 240 */ 241 void task_destroy(task_t *task) 235 242 { 236 243 /* 237 244 * Remove the task from the task B+tree. 238 245 */ 239 spinlock_lock(&tasks_lock);240 avltree_delete(&tasks_tree, &t ->tasks_tree_node);241 spinlock_unlock(&tasks_lock);246 irq_spinlock_lock(&tasks_lock, true); 247 avltree_delete(&tasks_tree, &task->tasks_tree_node); 248 irq_spinlock_unlock(&tasks_lock, true); 242 249 243 250 /* 244 251 * Perform architecture specific task destruction. 245 252 */ 246 task_destroy_arch(t );253 task_destroy_arch(task); 247 254 248 255 /* 249 256 * Free up dynamically allocated state. 250 257 */ 251 btree_destroy(&t ->futexes);258 btree_destroy(&task->futexes); 252 259 253 260 /* 254 261 * Drop our reference to the address space. 255 262 */ 256 as_release(t ->as);257 258 slab_free(task_slab, t );263 as_release(task->as); 264 265 slab_free(task_slab, task); 259 266 } 260 267 … … 263 270 * Holding a reference to a task prevents destruction of that task. 264 271 * 265 * @param t Task to be held. 266 */ 267 void task_hold(task_t *t) 268 { 269 atomic_inc(&t->refcount); 272 * @param task Task to be held. 273 * 274 */ 275 void task_hold(task_t *task) 276 { 277 atomic_inc(&task->refcount); 270 278 } 271 279 … … 274 282 * The last one to release a reference to a task destroys the task. 275 283 * 276 * @param t Task to be released. 277 */ 278 void task_release(task_t *t) 279 { 280 if ((atomic_predec(&t->refcount)) == 0) 281 task_destroy(t); 284 * @param task Task to be released. 285 * 286 */ 287 void task_release(task_t *task) 288 { 289 if ((atomic_predec(&task->refcount)) == 0) 290 task_destroy(task); 282 291 } 283 292 … … 346 355 347 356 if (node) 348 return avltree_get_instance(node, task_t, tasks_tree_node); 357 return avltree_get_instance(node, task_t, tasks_tree_node); 349 358 350 359 return NULL; … … 356 365 * already disabled. 357 366 * 358 * @param t Pointer to thread.367 * @param task Pointer to the task. 359 368 * @param ucycles Out pointer to sum of all user cycles. 360 369 * @param kcycles Out pointer to sum of all kernel cycles. 361 370 * 362 371 */ 363 void task_get_accounting(task_t *t , uint64_t *ucycles, uint64_t *kcycles)372 void task_get_accounting(task_t *task, uint64_t *ucycles, uint64_t *kcycles) 364 373 { 365 374 /* Accumulated values of task */ 366 uint64_t uret = t ->ucycles;367 uint64_t kret = t ->kcycles;375 uint64_t uret = task->ucycles; 376 uint64_t kret = task->kcycles; 368 377 369 378 /* Current values of threads */ 370 379 link_t *cur; 371 for (cur = t->th_head.next; cur != &t->th_head; cur = cur->next) { 372 thread_t *thr = list_get_instance(cur, thread_t, th_link); 373 374 spinlock_lock(&thr->lock); 380 for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) { 381 thread_t *thread = list_get_instance(cur, thread_t, th_link); 382 383 irq_spinlock_lock(&thread->lock, false); 384 375 385 /* Process only counted threads */ 376 if (!thr ->uncounted) {377 if (thr == THREAD) {386 if (!thread->uncounted) { 387 if (thread == THREAD) { 378 388 /* Update accounting of current thread */ 379 389 thread_update_accounting(false); 380 } 381 uret += thr->ucycles; 382 kret += thr->kcycles; 390 } 391 392 uret += thread->ucycles; 393 kret += thread->kcycles; 383 394 } 384 spinlock_unlock(&thr->lock); 395 396 irq_spinlock_unlock(&thread->lock, false); 385 397 } 386 398 … … 389 401 } 390 402 391 static void task_kill_internal(task_t *ta )403 static void task_kill_internal(task_t *task) 392 404 { 393 405 link_t *cur; … … 396 408 * Interrupt all threads. 397 409 */ 398 spinlock_lock(&ta->lock);399 for (cur = ta ->th_head.next; cur != &ta->th_head; cur = cur->next) {400 thread_t *thr ;410 irq_spinlock_lock(&task->lock, false); 411 for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) { 412 thread_t *thread = list_get_instance(cur, thread_t, th_link); 401 413 bool sleeping = false; 402 414 403 thr = list_get_instance(cur, thread_t, th_link); 404 405 spinlock_lock(&thr->lock); 406 thr->interrupted = true; 407 if (thr->state == Sleeping) 415 irq_spinlock_lock(&thread->lock, false); 416 417 thread->interrupted = true; 418 if (thread->state == Sleeping) 408 419 sleeping = true; 409 spinlock_unlock(&thr->lock); 420 421 irq_spinlock_unlock(&thread->lock, false); 410 422 411 423 if (sleeping) 412 waitq_interrupt_sleep(thr );424 waitq_interrupt_sleep(thread); 413 425 } 414 spinlock_unlock(&ta->lock); 426 427 irq_spinlock_unlock(&task->lock, false); 415 428 } 416 429 … … 427 440 int task_kill(task_id_t id) 428 441 { 429 ipl_t ipl;430 task_t *ta;431 432 442 if (id == 1) 433 443 return EPERM; 434 444 435 i pl = interrupts_disable();436 spinlock_lock(&tasks_lock);437 if (!(ta = task_find_by_id(id))) {438 spinlock_unlock(&tasks_lock);439 i nterrupts_restore(ipl);445 irq_spinlock_lock(&tasks_lock, true); 446 447 task_t *task = task_find_by_id(id); 448 if (!task) { 449 irq_spinlock_unlock(&tasks_lock, true); 440 450 return ENOENT; 441 451 } 442 task_kill_internal(ta); 443 spinlock_unlock(&tasks_lock); 444 interrupts_restore(ipl); 445 return 0; 452 453 task_kill_internal(task); 454 irq_spinlock_unlock(&tasks_lock, true); 455 456 return EOK; 446 457 } 447 458 448 459 static bool task_print_walker(avltree_node_t *node, void *arg) 449 460 { 450 task_t *t = avltree_get_instance(node, task_t, tasks_tree_node); 451 int j; 452 453 spinlock_lock(&t->lock); 461 task_t *task = avltree_get_instance(node, task_t, tasks_tree_node); 462 irq_spinlock_lock(&task->lock, false); 454 463 455 464 uint64_t ucycles; 456 465 uint64_t kcycles; 457 466 char usuffix, ksuffix; 458 task_get_accounting(t , &ucycles, &kcycles);467 task_get_accounting(task, &ucycles, &kcycles); 459 468 order_suffix(ucycles, &ucycles, &usuffix); 460 469 order_suffix(kcycles, &kcycles, &ksuffix); 461 470 462 #ifdef __32_BITS__ 471 #ifdef __32_BITS__ 463 472 printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 "%c %9" 464 PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as,465 ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount),466 atomic_get(&t->active_calls));473 PRIu64 "%c %7ld %6ld", task->taskid, task->name, task->context, 474 task, task->as, ucycles, usuffix, kcycles, ksuffix, 475 atomic_get(&task->refcount), atomic_get(&task->active_calls)); 467 476 #endif 468 477 469 478 #ifdef __64_BITS__ 470 479 printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 "%c %9" 471 PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, 472 ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount), 473 atomic_get(&t->active_calls)); 474 #endif 475 476 for (j = 0; j < IPC_MAX_PHONES; j++) { 477 if (t->phones[j].callee) 478 printf(" %d:%p", j, t->phones[j].callee); 480 PRIu64 "%c %7ld %6ld", task->taskid, task->name, task->context, 481 task, task->as, ucycles, usuffix, kcycles, ksuffix, 482 atomic_get(&task->refcount), atomic_get(&task->active_calls)); 483 #endif 484 485 size_t i; 486 for (i = 0; i < IPC_MAX_PHONES; i++) { 487 if (task->phones[i].callee) 488 printf(" %" PRIs ":%p", i, task->phones[i].callee); 479 489 } 480 490 printf("\n"); 481 491 482 spinlock_unlock(&t->lock);492 irq_spinlock_unlock(&task->lock, false); 483 493 return true; 484 494 } … … 487 497 void task_print_list(void) 488 498 { 489 ipl_t ipl;490 491 499 /* Messing with task structures, avoid deadlock */ 492 ipl = interrupts_disable(); 493 spinlock_lock(&tasks_lock); 500 irq_spinlock_lock(&tasks_lock, true); 494 501 495 502 #ifdef __32_BITS__ … … 509 516 avltree_walk(&tasks_tree, task_print_walker, NULL); 510 517 511 spinlock_unlock(&tasks_lock); 512 interrupts_restore(ipl); 518 irq_spinlock_unlock(&tasks_lock, true); 513 519 } 514 520
Note:
See TracChangeset
for help on using the changeset viewer.