mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
test/svc: add test for thread create
This commit is contained in:
parent
21b7884653
commit
1d39e06f32
3 changed files with 109 additions and 1 deletions
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. */
|
/* 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 {
|
auto GetSystemTickForPinnedThread = []() ALWAYS_INLINE_LAMBDA -> ::ams::svc::Tick {
|
||||||
s64 v;
|
s64 v;
|
||||||
|
|
Loading…
Reference in a new issue