diff options
Diffstat (limited to 'src/core/hle/kernel/process.cpp')
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 914bbe0a1..121f741fd 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -7,10 +7,12 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/common_funcs.h" | 8 | #include "common/common_funcs.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | ||
| 10 | #include "core/hle/kernel/errors.h" | 11 | #include "core/hle/kernel/errors.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 12 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/kernel/process.h" | 13 | #include "core/hle/kernel/process.h" |
| 13 | #include "core/hle/kernel/resource_limit.h" | 14 | #include "core/hle/kernel/resource_limit.h" |
| 15 | #include "core/hle/kernel/scheduler.h" | ||
| 14 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 15 | #include "core/hle/kernel/vm_manager.h" | 17 | #include "core/hle/kernel/vm_manager.h" |
| 16 | #include "core/memory.h" | 18 | #include "core/memory.h" |
| @@ -128,6 +130,91 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | |||
| 128 | Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this); | 130 | Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this); |
| 129 | } | 131 | } |
| 130 | 132 | ||
| 133 | void Process::PrepareForTermination() { | ||
| 134 | status = ProcessStatus::Exited; | ||
| 135 | |||
| 136 | const auto stop_threads = [this](const std::vector<SharedPtr<Thread>>& thread_list) { | ||
| 137 | for (auto& thread : thread_list) { | ||
| 138 | if (thread->owner_process != this) | ||
| 139 | continue; | ||
| 140 | |||
| 141 | if (thread == GetCurrentThread()) | ||
| 142 | continue; | ||
| 143 | |||
| 144 | // TODO(Subv): When are the other running/ready threads terminated? | ||
| 145 | ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny || | ||
| 146 | thread->status == ThreadStatus::WaitSynchAll, | ||
| 147 | "Exiting processes with non-waiting threads is currently unimplemented"); | ||
| 148 | |||
| 149 | thread->Stop(); | ||
| 150 | } | ||
| 151 | }; | ||
| 152 | |||
| 153 | auto& system = Core::System::GetInstance(); | ||
| 154 | stop_threads(system.Scheduler(0)->GetThreadList()); | ||
| 155 | stop_threads(system.Scheduler(1)->GetThreadList()); | ||
| 156 | stop_threads(system.Scheduler(2)->GetThreadList()); | ||
| 157 | stop_threads(system.Scheduler(3)->GetThreadList()); | ||
| 158 | } | ||
| 159 | |||
| 160 | /** | ||
| 161 | * Finds a free location for the TLS section of a thread. | ||
| 162 | * @param tls_slots The TLS page array of the thread's owner process. | ||
| 163 | * Returns a tuple of (page, slot, alloc_needed) where: | ||
| 164 | * page: The index of the first allocated TLS page that has free slots. | ||
| 165 | * slot: The index of the first free slot in the indicated page. | ||
| 166 | * alloc_needed: Whether there's a need to allocate a new TLS page (All pages are full). | ||
| 167 | */ | ||
| 168 | static std::tuple<std::size_t, std::size_t, bool> FindFreeThreadLocalSlot( | ||
| 169 | const std::vector<std::bitset<8>>& tls_slots) { | ||
| 170 | // Iterate over all the allocated pages, and try to find one where not all slots are used. | ||
| 171 | for (std::size_t page = 0; page < tls_slots.size(); ++page) { | ||
| 172 | const auto& page_tls_slots = tls_slots[page]; | ||
| 173 | if (!page_tls_slots.all()) { | ||
| 174 | // We found a page with at least one free slot, find which slot it is | ||
| 175 | for (std::size_t slot = 0; slot < page_tls_slots.size(); ++slot) { | ||
| 176 | if (!page_tls_slots.test(slot)) { | ||
| 177 | return std::make_tuple(page, slot, false); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | return std::make_tuple(0, 0, true); | ||
| 184 | } | ||
| 185 | |||
| 186 | VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { | ||
| 187 | auto [available_page, available_slot, needs_allocation] = FindFreeThreadLocalSlot(tls_slots); | ||
| 188 | |||
| 189 | if (needs_allocation) { | ||
| 190 | tls_slots.emplace_back(0); // The page is completely available at the start | ||
| 191 | available_page = tls_slots.size() - 1; | ||
| 192 | available_slot = 0; // Use the first slot in the new page | ||
| 193 | |||
| 194 | // Allocate some memory from the end of the linear heap for this region. | ||
| 195 | auto& tls_memory = thread.GetTLSMemory(); | ||
| 196 | tls_memory->insert(tls_memory->end(), Memory::PAGE_SIZE, 0); | ||
| 197 | |||
| 198 | vm_manager.RefreshMemoryBlockMappings(tls_memory.get()); | ||
| 199 | |||
| 200 | vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, | ||
| 201 | tls_memory, 0, Memory::PAGE_SIZE, MemoryState::ThreadLocal); | ||
| 202 | } | ||
| 203 | |||
| 204 | tls_slots[available_page].set(available_slot); | ||
| 205 | |||
| 206 | return Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + | ||
| 207 | available_slot * Memory::TLS_ENTRY_SIZE; | ||
| 208 | } | ||
| 209 | |||
| 210 | void Process::FreeTLSSlot(VAddr tls_address) { | ||
| 211 | const VAddr tls_base = tls_address - Memory::TLS_AREA_VADDR; | ||
| 212 | const VAddr tls_page = tls_base / Memory::PAGE_SIZE; | ||
| 213 | const VAddr tls_slot = (tls_base % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; | ||
| 214 | |||
| 215 | tls_slots[tls_page].reset(tls_slot); | ||
| 216 | } | ||
| 217 | |||
| 131 | void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { | 218 | void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { |
| 132 | const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, | 219 | const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, |
| 133 | MemoryState memory_state) { | 220 | MemoryState memory_state) { |