| 132 | } |
| 133 | |
| 134 | Error |
| 135 | IOS_JoinThread(ThreadId id, |
| 136 | phys_ptr<Error> returnedValue) |
| 137 | { |
| 138 | auto currentThread = internal::getCurrentThread(); |
| 139 | |
| 140 | if (!id) { |
| 141 | id = currentThread->id; |
| 142 | } else if (id >= sData->threads.size()) { |
| 143 | return Error::Invalid; |
| 144 | } |
| 145 | |
| 146 | auto thread = phys_addrof(sData->threads[id]); |
| 147 | if (thread->pid != currentThread->pid) { |
| 148 | // Can only join threads belonging to the same process. |
| 149 | return Error::Invalid; |
| 150 | } |
| 151 | |
| 152 | if (thread == currentThread) { |
| 153 | // Can't join self. |
| 154 | return Error::Invalid; |
| 155 | } |
| 156 | |
| 157 | if (thread->flags & ThreadFlags::Detached) { |
| 158 | // Can't join a detached thread. |
| 159 | return Error::Invalid; |
| 160 | } |
| 161 | |
| 162 | /* |
| 163 | if (thread->unknown0x64 != dword_81430D4) { |
| 164 | return Error::Invalid; |
| 165 | } |
| 166 | */ |
| 167 | |
| 168 | if (thread->state != ThreadState::Dead) { |
| 169 | internal::sleepThread(phys_addrof(thread->joinQueue)); |
| 170 | internal::reschedule(); |
| 171 | } |
| 172 | |
| 173 | if (returnedValue) { |
| 174 | *returnedValue = thread->exitValue; |
| 175 | } |
| 176 | |
| 177 | thread->state = ThreadState::Available; |
| 178 | return Error::OK; |
| 179 | } |
| 180 | |
| 181 | Error |
| 182 | IOS_CancelThread(ThreadId id, |
no test coverage detected