| 684 | } |
| 685 | |
| 686 | bool OSJoinThread(OSThread_t* thread, uint32be* exitValue) |
| 687 | { |
| 688 | __OSLockScheduler(); |
| 689 | |
| 690 | if ((thread->attr & OSThread_t::ATTR_DETACHED) == 0 && thread->state != OSThread_t::THREAD_STATE::STATE_MORIBUND) |
| 691 | { |
| 692 | cemu_assert_debug(thread->joinQueue.isEmpty()); |
| 693 | // thread still running, wait in join queue |
| 694 | thread->joinQueue.queueAndWait(OSGetCurrentThread()); |
| 695 | } |
| 696 | else if (thread->state != OSThread_t::THREAD_STATE::STATE_MORIBUND) |
| 697 | { |
| 698 | // cannot join detached and active threads |
| 699 | cemuLog_logDebug(LogType::Force, "Cannot join detached active thread"); |
| 700 | __OSUnlockScheduler(); |
| 701 | return false; |
| 702 | } |
| 703 | |
| 704 | // thread already ended and is still attached, get return value |
| 705 | cemu_assert_debug(thread->state == OSThread_t::THREAD_STATE::STATE_MORIBUND); |
| 706 | cemu_assert_debug((thread->attr & OSThread_t::ATTR_DETACHED) == 0); |
| 707 | if (exitValue) |
| 708 | *exitValue = thread->exitValue; |
| 709 | // end thread |
| 710 | thread->state = OSThread_t::THREAD_STATE::STATE_NONE; |
| 711 | __OSDeactivateThread(thread); |
| 712 | coreinit::__OSRemoveThreadFromRunQueues(thread); |
| 713 | thread->id = 0x8000; |
| 714 | |
| 715 | if (!thread->deallocatorFunc.IsNull()) |
| 716 | __OSQueueThreadDeallocation(thread); |
| 717 | |
| 718 | __OSUnlockScheduler(); |
| 719 | |
| 720 | return true; |
| 721 | } |
| 722 | |
| 723 | // adds the thread to each core's run queue if in runable state |
| 724 | void __OSAddReadyThreadToRunQueue(OSThread_t* thread) |
no test coverage detected