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 |