Changes in kernel/generic/src/proc/task.c [d3808d3:be06914] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/proc/task.c
rd3808d3 rbe06914 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_received = 0; 200 task->ipc_info.answer_sent = 0; 201 task->ipc_info.answer_received = 0; 202 task->ipc_info.irq_notif_received = 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 … … 342 351 task_t *task_find_by_id(task_id_t id) 343 352 { 353 ASSERT(interrupts_disabled()); 354 ASSERT(irq_spinlock_locked(&tasks_lock)); 355 344 356 avltree_node_t *node = 345 357 avltree_search(&tasks_tree, (avltree_key_t) id); 346 358 347 359 if (node) 348 return avltree_get_instance(node, task_t, tasks_tree_node); 360 return avltree_get_instance(node, task_t, tasks_tree_node); 349 361 350 362 return NULL; … … 353 365 /** Get accounting data of given task. 354 366 * 355 * Note that task lock of 't ' must be already held and interrupts must be367 * Note that task lock of 'task' must be already held and interrupts must be 356 368 * already disabled. 357 369 * 358 * @param t Pointer to thread.370 * @param task Pointer to the task. 359 371 * @param ucycles Out pointer to sum of all user cycles. 360 372 * @param kcycles Out pointer to sum of all kernel cycles. 361 373 * 362 374 */ 363 void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles) 364 { 375 void task_get_accounting(task_t *task, uint64_t *ucycles, uint64_t *kcycles) 376 { 377 ASSERT(interrupts_disabled()); 378 ASSERT(irq_spinlock_locked(&task->lock)); 379 365 380 /* Accumulated values of task */ 366 uint64_t uret = t ->ucycles;367 uint64_t kret = t ->kcycles;381 uint64_t uret = task->ucycles; 382 uint64_t kret = task->kcycles; 368 383 369 384 /* Current values of threads */ 370 385 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); 386 for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) { 387 thread_t *thread = list_get_instance(cur, thread_t, th_link); 388 389 irq_spinlock_lock(&thread->lock, false); 390 375 391 /* Process only counted threads */ 376 if (!thr ->uncounted) {377 if (thr == THREAD) {392 if (!thread->uncounted) { 393 if (thread == THREAD) { 378 394 /* Update accounting of current thread */ 379 395 thread_update_accounting(false); 380 } 381 uret += thr->ucycles; 382 kret += thr->kcycles; 396 } 397 398 uret += thread->ucycles; 399 kret += thread->kcycles; 383 400 } 384 spinlock_unlock(&thr->lock); 401 402 irq_spinlock_unlock(&thread->lock, false); 385 403 } 386 404 … … 389 407 } 390 408 391 static void task_kill_internal(task_t *ta )409 static void task_kill_internal(task_t *task) 392 410 { 393 411 link_t *cur; … … 396 414 * Interrupt all threads. 397 415 */ 398 spinlock_lock(&ta->lock);399 for (cur = ta ->th_head.next; cur != &ta->th_head; cur = cur->next) {400 thread_t *thr ;416 irq_spinlock_lock(&task->lock, false); 417 for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) { 418 thread_t *thread = list_get_instance(cur, thread_t, th_link); 401 419 bool sleeping = false; 402 420 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) 421 irq_spinlock_lock(&thread->lock, false); 422 423 thread->interrupted = true; 424 if (thread->state == Sleeping) 408 425 sleeping = true; 409 spinlock_unlock(&thr->lock); 426 427 irq_spinlock_unlock(&thread->lock, false); 410 428 411 429 if (sleeping) 412 waitq_interrupt_sleep(thr );430 waitq_interrupt_sleep(thread); 413 431 } 414 spinlock_unlock(&ta->lock); 432 433 irq_spinlock_unlock(&task->lock, false); 415 434 } 416 435 … … 427 446 int task_kill(task_id_t id) 428 447 { 429 ipl_t ipl;430 task_t *ta;431 432 448 if (id == 1) 433 449 return EPERM; 434 450 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);451 irq_spinlock_lock(&tasks_lock, true); 452 453 task_t *task = task_find_by_id(id); 454 if (!task) { 455 irq_spinlock_unlock(&tasks_lock, true); 440 456 return ENOENT; 441 457 } 442 task_kill_internal(ta); 443 spinlock_unlock(&tasks_lock); 444 interrupts_restore(ipl); 445 return 0; 458 459 task_kill_internal(task); 460 irq_spinlock_unlock(&tasks_lock, true); 461 462 return EOK; 446 463 } 447 464 448 465 static bool task_print_walker(avltree_node_t *node, void *arg) 449 466 { 450 task_t *t = avltree_get_instance(node, task_t, tasks_tree_node); 451 int j; 452 453 spinlock_lock(&t->lock); 467 bool *additional = (bool *) arg; 468 task_t *task = avltree_get_instance(node, task_t, tasks_tree_node); 469 irq_spinlock_lock(&task->lock, false); 454 470 455 471 uint64_t ucycles; 456 472 uint64_t kcycles; 457 473 char usuffix, ksuffix; 458 task_get_accounting(t , &ucycles, &kcycles);474 task_get_accounting(task, &ucycles, &kcycles); 459 475 order_suffix(ucycles, &ucycles, &usuffix); 460 476 order_suffix(kcycles, &kcycles, &ksuffix); 461 477 462 #ifdef __32_BITS__ 463 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)); 478 #ifdef __32_BITS__ 479 if (*additional) 480 printf("%-8" PRIu64 " %9lu %7lu", task->taskid, 481 atomic_get(&task->refcount), atomic_get(&task->active_calls)); 482 else 483 printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %10p %10p" 484 " %9" PRIu64 "%c %9" PRIu64 "%c\n", task->taskid, 485 task->name, task->context, task, task->as, 486 ucycles, usuffix, kcycles, ksuffix); 467 487 #endif 468 488 469 489 #ifdef __64_BITS__ 470 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); 490 if (*additional) 491 printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c %9lu %7lu", 492 task->taskid, ucycles, usuffix, kcycles, ksuffix, 493 atomic_get(&task->refcount), atomic_get(&task->active_calls)); 494 else 495 printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n", 496 task->taskid, task->name, task->context, task, task->as); 497 #endif 498 499 if (*additional) { 500 size_t i; 501 for (i = 0; i < IPC_MAX_PHONES; i++) { 502 if (task->phones[i].callee) 503 printf(" %" PRIs ":%p", i, task->phones[i].callee); 504 } 505 printf("\n"); 479 506 } 480 printf("\n"); 481 482 spinlock_unlock(&t->lock); 507 508 irq_spinlock_unlock(&task->lock, false); 483 509 return true; 484 510 } 485 511 486 /** Print task list */ 487 void task_print_list(void) 488 { 489 ipl_t ipl; 490 512 /** Print task list 513 * 514 * @param additional Print additional information. 515 * 516 */ 517 void task_print_list(bool additional) 518 { 491 519 /* Messing with task structures, avoid deadlock */ 492 ipl = interrupts_disable(); 493 spinlock_lock(&tasks_lock); 520 irq_spinlock_lock(&tasks_lock, true); 494 521 495 522 #ifdef __32_BITS__ 496 printf("taskid name ctx address as " 497 " ucycles kcycles threads calls callee\n"); 498 printf("------ ------------ --- ---------- ----------" 499 " ---------- ---------- ------- ------ ------>\n"); 523 if (additional) 524 printf("[id ] [threads] [calls] [callee\n"); 525 else 526 printf("[id ] [name ] [ctx] [address ] [as ]" 527 " [ucycles ] [kcycles ]\n"); 500 528 #endif 501 529 502 530 #ifdef __64_BITS__ 503 printf("taskid name ctx address as " 504 " ucycles kcycles threads calls callee\n"); 505 printf("------ ------------ --- ------------------ ------------------" 506 " ---------- ---------- ---------- ------- ------ ------>\n"); 507 #endif 508 509 avltree_walk(&tasks_tree, task_print_walker, NULL); 510 511 spinlock_unlock(&tasks_lock); 512 interrupts_restore(ipl); 531 if (additional) 532 printf("[id ] [ucycles ] [kcycles ] [threads] [calls]" 533 " [callee\n"); 534 else 535 printf("[id ] [name ] [ctx] [address ]" 536 " [as ]\n"); 537 #endif 538 539 avltree_walk(&tasks_tree, task_print_walker, &additional); 540 541 irq_spinlock_unlock(&tasks_lock, true); 513 542 } 514 543
Note:
See TracChangeset
for help on using the changeset viewer.