Rev 2898 | Rev 2903 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2898 | Rev 2902 | ||
|---|---|---|---|
| Line 410... | Line 410... | ||
| 410 | task_destroy(t->task); |
410 | task_destroy(t->task); |
| 411 | 411 | ||
| 412 | slab_free(thread_slab, t); |
412 | slab_free(thread_slab, t); |
| 413 | } |
413 | } |
| 414 | 414 | ||
| 415 | /** Attach thread to the given task. |
- | |
| 416 | * |
- | |
| 417 | * The task's lock must already be held and interrupts must be disabled. |
- | |
| 418 | * |
- | |
| 419 | * @param t Thread to be attached to the task. |
- | |
| 420 | * @param task Task to which the thread is to be attached. |
- | |
| 421 | */ |
- | |
| 422 | static void _thread_attach_task(thread_t *t, task_t *task) |
- | |
| 423 | { |
- | |
| 424 | atomic_inc(&task->refcount); |
- | |
| 425 | atomic_inc(&task->lifecount); |
- | |
| 426 | - | ||
| 427 | list_append(&t->th_link, &task->th_head); |
- | |
| 428 | - | ||
| 429 | /* |
- | |
| 430 | * Copy task debugging state to thread struct. |
- | |
| 431 | * The thread needs to know it is being debugged, |
- | |
| 432 | * otherwise it would neither stop nor respond to |
- | |
| 433 | * debug ops. |
- | |
| 434 | */ |
- | |
| 435 | if (t->flags & THREAD_FLAG_USPACE) { |
- | |
| 436 | if (task->dt_state == UDEBUG_TS_BEGINNING || |
- | |
| 437 | task->dt_state == UDEBUG_TS_ACTIVE) { |
- | |
| 438 | t->debug_active = true; |
- | |
| 439 | } |
- | |
| 440 | } |
- | |
| 441 | } |
- | |
| 442 | - | ||
| 443 | /** Add thread to the threads tree. |
- | |
| 444 | * |
- | |
| 445 | * Interrupts must be already disabled. |
- | |
| 446 | * |
- | |
| 447 | * @param t Thread to be attached to the task. |
- | |
| 448 | * @param task Task to which the thread is to be attached. |
- | |
| 449 | */ |
- | |
| 450 | static void _thread_attach_tree(thread_t *t) |
- | |
| 451 | { |
- | |
| 452 | /* |
- | |
| 453 | * Register this thread in the system-wide list. |
- | |
| 454 | */ |
- | |
| 455 | spinlock_lock(&threads_lock); |
- | |
| 456 | avltree_insert(&threads_tree, &t->threads_tree_node); |
- | |
| 457 | spinlock_unlock(&threads_lock); |
- | |
| 458 | } |
- | |
| 459 | - | ||
| 460 | - | ||
| 461 | /** Make the thread visible to the system. |
415 | /** Make the thread visible to the system. |
| 462 | * |
416 | * |
| 463 | * Attach the thread structure to the current task and make it visible in the |
417 | * Attach the thread structure to the current task and make it visible in the |
| 464 | * threads_tree. |
418 | * threads_tree. |
| 465 | * |
419 | * |
| Line 468... | Line 422... | ||
| 468 | */ |
422 | */ |
| 469 | void thread_attach(thread_t *t, task_t *task) |
423 | void thread_attach(thread_t *t, task_t *task) |
| 470 | { |
424 | { |
| 471 | ipl_t ipl; |
425 | ipl_t ipl; |
| 472 | 426 | ||
| 473 | ipl = interrupts_disable(); |
- | |
| 474 | - | ||
| 475 | /* |
- | |
| 476 | * Attach to the current task. |
- | |
| 477 | */ |
- | |
| 478 | spinlock_lock(&task->lock); |
- | |
| 479 | _thread_attach_task(t, task); |
- | |
| 480 | spinlock_unlock(&task->lock); |
- | |
| 481 | - | ||
| 482 | /* |
427 | /* |
| 483 | * Register this thread in the system-wide list. |
428 | * Attach to the specified task. |
| 484 | */ |
429 | */ |
| 485 | _thread_attach_tree(t); |
- | |
| 486 | - | ||
| 487 | interrupts_restore(ipl); |
- | |
| 488 | } |
- | |
| 489 | - | ||
| 490 | /** Attach thread to a task given by its ID. |
- | |
| 491 | * |
- | |
| 492 | * Unlike thread_attach(), this function allows to attach a thread |
- | |
| 493 | * to an arbitrary task. |
- | |
| 494 | * |
- | |
| 495 | * @param t Thread to be attached to the task. |
- | |
| 496 | * @param taskid Task id to which the thread is to be attached. |
- | |
| 497 | * @return An error code from errno.h |
- | |
| 498 | */ |
- | |
| 499 | int thread_attach_by_id(thread_t *t, task_id_t taskid) |
- | |
| 500 | { |
- | |
| 501 | ipl_t ipl; |
- | |
| 502 | task_t *task; |
- | |
| 503 | - | ||
| 504 | ipl = interrupts_disable(); |
430 | ipl = interrupts_disable(); |
| 505 | - | ||
| 506 | spinlock_lock(&tasks_lock); |
- | |
| 507 | task = task_find_by_id(taskid); |
- | |
| 508 | if (task == NULL) { |
- | |
| 509 | spinlock_unlock(&tasks_lock); |
- | |
| 510 | interrupts_restore(ipl); |
- | |
| 511 | return ENOENT; |
- | |
| 512 | } |
- | |
| 513 | - | ||
| 514 | spinlock_lock(&task->lock); |
431 | spinlock_lock(&task->lock); |
| 515 | spinlock_unlock(&tasks_lock); |
432 | atomic_inc(&task->refcount); |
| 516 | - | ||
| 517 | /* |
- | |
| 518 | * Attach to the current task. |
433 | /* Must not count kbox thread into lifecount */ |
| 519 | */ |
434 | if (t->flags & THREAD_FLAG_USPACE) |
| - | 435 | atomic_inc(&task->lifecount); |
|
| 520 | _thread_attach_task(t, task); |
436 | list_append(&t->th_link, &task->th_head); |
| 521 | - | ||
| 522 | spinlock_unlock(&task->lock); |
437 | spinlock_unlock(&task->lock); |
| 523 | 438 | ||
| 524 | /* |
439 | /* |
| 525 | * Register this thread in the system-wide list. |
440 | * Register this thread in the system-wide list. |
| 526 | */ |
441 | */ |
| - | 442 | spinlock_lock(&threads_lock); |
|
| - | 443 | avltree_insert(&threads_tree, &t->threads_tree_node); |
|
| 527 | _thread_attach_tree(t); |
444 | spinlock_unlock(&threads_lock); |
| 528 | 445 | ||
| 529 | interrupts_restore(ipl); |
446 | interrupts_restore(ipl); |
| 530 | - | ||
| 531 | return EOK; |
- | |
| 532 | } |
447 | } |
| 533 | 448 | ||
| 534 | - | ||
| 535 | /** Terminate thread. |
449 | /** Terminate thread. |
| 536 | * |
450 | * |
| 537 | * End current thread execution and switch it to the exiting state. All pending |
451 | * End current thread execution and switch it to the exiting state. All pending |
| 538 | * timeouts are executed. |
452 | * timeouts are executed. |
| 539 | */ |
453 | */ |
| 540 | void thread_exit(void) |
454 | void thread_exit(void) |
| 541 | { |
455 | { |
| 542 | ipl_t ipl; |
456 | ipl_t ipl; |
| 543 | 457 | ||
| - | 458 | if (THREAD->flags & THREAD_FLAG_USPACE) { |
|
| 544 | if (atomic_predec(&TASK->lifecount) == 0) { |
459 | if (atomic_predec(&TASK->lifecount) == 0) { |
| 545 | /* |
460 | /* |
| 546 | * We are the last thread in the task that still has not exited. |
461 | * We are the last userspace thread in the task that |
| - | 462 | * still has not exited. With the exception of the |
|
| 547 | * With the exception of the moment the task was created, new |
463 | * moment the task was created, new userspace threads |
| 548 | * threads can only be created by threads of the same task. |
464 | * can only be created by threads of the same task. |
| 549 | * We are safe to perform cleanup. |
465 | * We are safe to perform cleanup. |
| 550 | */ |
466 | */ |
| 551 | if (THREAD->flags & THREAD_FLAG_USPACE) { |
- | |
| 552 | ipc_cleanup(); |
467 | ipc_cleanup(); |
| 553 | futex_cleanup(); |
468 | futex_cleanup(); |
| 554 | klog_printf("Cleanup of task %llu completed.", |
469 | klog_printf("Cleanup of task %llu completed.", |
| 555 | TASK->taskid); |
470 | TASK->taskid); |
| 556 | } |
471 | } |
| 557 | } |
472 | } |
| 558 | 473 | ||