Changeset 1871118 in mainline for kernel/generic/src/proc/thread.c
- Timestamp:
- 2023-02-10T22:59:11Z (2 years ago)
- Branches:
- master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 11d2c983
- Parents:
- daadfa6
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2023-02-10 22:53:12)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2023-02-10 22:59:11)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/proc/thread.c
rdaadfa6 r1871118 94 94 * 95 95 * Members are of type thread_t. 96 * 97 * This structure contains weak references. Any reference from it must not leave 98 * threads_lock critical section unless strengthened via thread_try_ref(). 96 99 */ 97 100 odict_t threads; … … 249 252 /** Make thread ready 250 253 * 251 * Switch thread to the ready state. 254 * Switch thread to the ready state. Consumes reference passed by the caller. 252 255 * 253 256 * @param thread Thread to make ready. … … 320 323 return NULL; 321 324 325 refcount_init(&thread->refcount); 326 322 327 if (thread_create_arch(thread, flags) != EOK) { 323 328 slab_free(thread_cache, thread); … … 368 373 369 374 thread->interrupted = false; 370 thread->detached = false;371 375 waitq_initialize(&thread->join_wq); 372 376 … … 399 403 * 400 404 */ 401 void thread_destroy(thread_t *thread, bool irq_res) 402 { 403 assert(irq_spinlock_locked(&thread->lock)); 405 static void thread_destroy(void *obj) 406 { 407 thread_t *thread = (thread_t *) obj; 408 409 irq_spinlock_lock(&thread->lock, true); 404 410 assert((thread->state == Exiting) || (thread->state == Lingering)); 405 411 assert(thread->task); … … 421 427 */ 422 428 list_remove(&thread->th_link); 423 irq_spinlock_unlock(&thread->task->lock, irq_res);429 irq_spinlock_unlock(&thread->task->lock, true); 424 430 425 431 /* … … 430 436 } 431 437 438 void thread_put(thread_t *thread) 439 { 440 if (refcount_down(&thread->refcount)) { 441 thread_destroy(thread); 442 } 443 } 444 432 445 /** Make the thread visible to the system. 433 446 * … … 441 454 void thread_attach(thread_t *thread, task_t *task) 442 455 { 456 ipl_t ipl = interrupts_disable(); 457 443 458 /* 444 459 * Attach to the specified task. 445 460 */ 446 irq_spinlock_lock(&task->lock, true);461 irq_spinlock_lock(&task->lock, false); 447 462 448 463 /* Hold a reference to the task. */ … … 455 470 list_append(&thread->th_link, &task->threads); 456 471 457 irq_spinlock_ pass(&task->lock, &threads_lock);472 irq_spinlock_unlock(&task->lock, false); 458 473 459 474 /* 460 475 * Register this thread in the system-wide dictionary. 461 476 */ 477 irq_spinlock_lock(&threads_lock, false); 462 478 odict_insert(&thread->lthreads, &threads, NULL); 463 irq_spinlock_unlock(&threads_lock, true); 479 irq_spinlock_unlock(&threads_lock, false); 480 481 interrupts_restore(ipl); 464 482 } 465 483 … … 513 531 * blocking call was interruptable. See waitq_sleep_timeout(). 514 532 * 515 * The caller must guarantee the thread object is valid during the entire516 * function, eg by holding the threads_lock lock.517 *518 533 * Interrupted threads automatically exit when returning back to user space. 519 534 * 520 * @param thread A valid thread object. The caller must guarantee it 521 * will remain valid until thread_interrupt() exits. 535 * @param thread A valid thread object. 522 536 */ 523 537 void thread_interrupt(thread_t *thread, bool irq_dis) … … 534 548 if (sleeping) 535 549 waitq_interrupt_sleep(thread); 550 551 thread_put(thread); 536 552 } 537 553 … … 581 597 582 598 /** Wait for another thread to exit. 599 * This function does not destroy the thread. Reference counting handles that. 583 600 * 584 601 * @param thread Thread to join on exit. … … 594 611 return EINVAL; 595 612 596 /*597 * Since thread join can only be called once on an undetached thread,598 * the thread pointer is guaranteed to be still valid.599 */600 601 613 irq_spinlock_lock(&thread->lock, true); 602 assert(!thread->detached);614 state_t state = thread->state; 603 615 irq_spinlock_unlock(&thread->lock, true); 604 616 605 return waitq_sleep_timeout(&thread->join_wq, usec, flags, NULL); 606 607 // FIXME: join should deallocate the thread. 608 // Current code calls detach after join, that's contrary to how 609 // join is used in other threading APIs. 610 } 611 612 /** Detach thread. 613 * 614 * Mark the thread as detached. If the thread is already 615 * in the Lingering state, deallocate its resources. 616 * 617 * @param thread Thread to be detached. 618 * 619 */ 620 void thread_detach(thread_t *thread) 621 { 622 /* 623 * Since the thread is expected not to be already detached, 624 * pointer to it must be still valid. 625 */ 626 irq_spinlock_lock(&thread->lock, true); 627 assert(!thread->detached); 628 629 if (thread->state == Lingering) { 630 /* 631 * Unlock &thread->lock and restore 632 * interrupts in thread_destroy(). 633 */ 634 thread_destroy(thread, true); 635 return; 617 if (state == Exiting) { 618 return EOK; 636 619 } else { 637 thread->detached = true; 638 } 639 640 irq_spinlock_unlock(&thread->lock, true); 620 return waitq_sleep_timeout(&thread->join_wq, usec, 621 SYNCH_FLAGS_NON_BLOCKING, NULL); 622 } 641 623 } 642 624 … … 702 684 thread_t *thread; 703 685 704 /* Messing with thread structures, avoid deadlock*/686 /* Accessing system-wide threads list through thread_first()/thread_next(). */ 705 687 irq_spinlock_lock(&threads_lock, true); 706 688 … … 730 712 } 731 713 732 /** Check whether thread exists. 733 * 734 * Note that threads_lock must be already held and 735 * interrupts must be already disabled. 736 * 737 * @param thread Pointer to thread. 738 * 739 * @return True if thread t is known to the system, false otherwise. 740 * 741 */ 742 bool thread_exists(thread_t *thread) 743 { 744 assert(interrupts_disabled()); 745 assert(irq_spinlock_locked(&threads_lock)); 746 714 static bool thread_exists(thread_t *thread) 715 { 747 716 odlink_t *odlink = odict_find_eq(&threads, thread, NULL); 748 717 return odlink != NULL; 718 } 719 720 /** Check whether the thread exists, and if so, return a reference to it. 721 */ 722 thread_t *thread_try_get(thread_t *thread) 723 { 724 irq_spinlock_lock(&threads_lock, true); 725 726 if (thread_exists(thread)) { 727 /* Try to strengthen the reference. */ 728 thread = thread_try_ref(thread); 729 } else { 730 thread = NULL; 731 } 732 733 irq_spinlock_unlock(&threads_lock, true); 734 735 return thread; 749 736 } 750 737 … … 777 764 * interrupts must be disabled. 778 765 * 766 * The returned reference is weak. 767 * If the caller needs to keep it, thread_try_ref() must be used to upgrade 768 * to a strong reference _before_ threads_lock is released. 769 * 779 770 * @param id Thread ID. 780 771 * … … 854 845 { 855 846 irq_spinlock_lock(&threads_lock, true); 856 857 thread_t *thread = thread_find_by_id(thread_id); 847 thread_t *thread = thread_try_ref(thread_find_by_id(thread_id)); 848 irq_spinlock_unlock(&threads_lock, true); 849 858 850 if (thread == NULL) { 859 851 printf("No such thread.\n"); 860 irq_spinlock_unlock(&threads_lock, true);861 852 return; 862 853 } 863 864 irq_spinlock_lock(&thread->lock, false);865 854 866 855 /* … … 876 865 */ 877 866 867 irq_spinlock_lock(&thread->lock, true); 868 878 869 bool sleeping = false; 879 870 istate_t *istate = thread->udebug.uspace_state; … … 886 877 printf("Thread interrupt state not available.\n"); 887 878 888 irq_spinlock_unlock(&thread->lock, false);879 irq_spinlock_unlock(&thread->lock, true); 889 880 890 881 if (sleeping) 891 882 waitq_interrupt_sleep(thread); 892 883 893 irq_spinlock_unlock(&threads_lock, true);884 thread_put(thread); 894 885 } 895 886
Note:
See TracChangeset
for help on using the changeset viewer.