mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-30 18:34:38 +01:00
test/svc: add test for thread create
This commit is contained in:
parent
21b7884653
commit
1d39e06f32
43
tests/TestSvc/source/test_thread_creation.arch.arm64.s
Normal file
43
tests/TestSvc/source/test_thread_creation.arch.arm64.s
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ams::test::TestThreadCreateRegistersOnFunctionEntry(void *ctx) */
|
||||
.section .text._ZN3ams4test40TestThreadCreateRegistersOnFunctionEntryEPv, "ax", %progbits
|
||||
.global _ZN3ams4test40TestThreadCreateRegistersOnFunctionEntryEPv
|
||||
.type _ZN3ams4test40TestThreadCreateRegistersOnFunctionEntryEPv, %function
|
||||
_ZN3ams4test40TestThreadCreateRegistersOnFunctionEntryEPv:
|
||||
/* Save all registers to our context. */
|
||||
stp x0, x1, [x0, #0x00]
|
||||
stp x2, x3, [x0, #0x10]
|
||||
stp x4, x5, [x0, #0x20]
|
||||
stp x6, x7, [x0, #0x30]
|
||||
stp x8, x9, [x0, #0x40]
|
||||
stp x10, x11, [x0, #0x50]
|
||||
stp x12, x13, [x0, #0x60]
|
||||
stp x14, x15, [x0, #0x70]
|
||||
stp x16, x17, [x0, #0x80]
|
||||
stp x18, x19, [x0, #0x90]
|
||||
stp x20, x21, [x0, #0xA0]
|
||||
stp x22, x23, [x0, #0xB0]
|
||||
stp x24, x25, [x0, #0xC0]
|
||||
stp x26, x27, [x0, #0xD0]
|
||||
stp x28, x29, [x0, #0xE0]
|
||||
|
||||
mov x1, sp
|
||||
stp x30, x1, [x0, #0xF0]
|
||||
|
||||
/* Exit the thread. */
|
||||
svc 0xa
|
65
tests/TestSvc/source/test_thread_creation.cpp
Normal file
65
tests/TestSvc/source/test_thread_creation.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "util_common.hpp"
|
||||
#include "util_scoped_heap.hpp"
|
||||
|
||||
namespace ams::test {
|
||||
|
||||
void TestThreadCreateRegistersOnFunctionEntry(void *ctx);
|
||||
|
||||
DOCTEST_TEST_CASE( "Creating a thread results in fixed register contents." ) {
|
||||
/* Create heap. */
|
||||
ScopedHeap heap(os::MemoryPageSize);
|
||||
|
||||
/* Create register buffer. */
|
||||
u64 thread_registers[32];
|
||||
std::memset(thread_registers, 0xCC, sizeof(thread_registers));
|
||||
|
||||
/* Create thread. */
|
||||
svc::Handle thread_handle;
|
||||
DOCTEST_CHECK(R_SUCCEEDED(svc::CreateThread(std::addressof(thread_handle), reinterpret_cast<uintptr_t>(&TestThreadCreateRegistersOnFunctionEntry), reinterpret_cast<uintptr_t>(thread_registers), heap.GetAddress() + os::MemoryPageSize, HighestTestPriority, NumCores - 1)));
|
||||
|
||||
/* Start thread. */
|
||||
DOCTEST_CHECK(R_SUCCEEDED(svc::StartThread(thread_handle)));
|
||||
|
||||
/* Wait for thread to exit. */
|
||||
s32 dummy;
|
||||
DOCTEST_CHECK(R_SUCCEEDED(svc::WaitSynchronization(std::addressof(dummy), std::addressof(thread_handle), 1, -1)));
|
||||
|
||||
/* Close thread handle. */
|
||||
DOCTEST_CHECK(R_SUCCEEDED(svc::CloseHandle(thread_handle)));
|
||||
|
||||
/* Check thread initial registers. */
|
||||
for (size_t i = 0; i < util::size(thread_registers); ++i) {
|
||||
if (i == 0) {
|
||||
/* X0 is argument. */
|
||||
DOCTEST_CHECK(thread_registers[i] == reinterpret_cast<uintptr_t>(thread_registers));
|
||||
} else if (i == 18) {
|
||||
/* X18 is an odd cfi value. */
|
||||
DOCTEST_CHECK(thread_registers[i] != 0);
|
||||
DOCTEST_CHECK((thread_registers[i] & 0x1) != 0);
|
||||
} else if (i == 31) {
|
||||
/* SP is user-provided sp. */
|
||||
DOCTEST_CHECK(thread_registers[i] == (heap.GetAddress() + os::MemoryPageSize));
|
||||
} else {
|
||||
/* All other registers are zero. */
|
||||
DOCTEST_CHECK(thread_registers[i] == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -46,7 +46,7 @@ namespace ams::test {
|
||||
|
||||
/* Wait long enough that we can be confident preemption will occur, and therefore our interrupt flag will be set. */
|
||||
{
|
||||
constexpr auto MinimumTicksToGuaranteeInterruptFlag = ::ams::svc::Tick(PreemptionTimeSpan) + 1;
|
||||
constexpr auto MinimumTicksToGuaranteeInterruptFlag = ::ams::svc::Tick(PreemptionTimeSpan) + ::ams::svc::Tick(PreemptionTimeSpan) + 2;
|
||||
|
||||
auto GetSystemTickForPinnedThread = []() ALWAYS_INLINE_LAMBDA -> ::ams::svc::Tick {
|
||||
s64 v;
|
||||
|
Loading…
Reference in New Issue
Block a user