Compare commits

...

90 Commits

Author SHA1 Message Date
Subv
46572d027d Kernel: Implemented mutex priority inheritance.
Verified with a hwtest and implemented based on reverse engineering.

Thread A's priority will get bumped to the highest priority among all the threads that are waiting for a mutex that A holds.
Once A releases the mutex and ownership is transferred to B, A's priority will return to normal and B's priority will be bumped.
2018-04-23 11:23:44 -05:00
Subv
a70ed9c8ae Kernel: Use 0x2C as default main thread priority for homebrew and lone NRO/NSOs 2018-04-20 21:04:35 -05:00
Subv
013778aa21 Qt: Update the WaitTree widget to show info about the current mutex of each thread. 2018-04-20 21:04:34 -05:00
Subv
be155f4d9d Kernel: Remove unused ConditionVariable class. 2018-04-20 21:04:33 -05:00
Subv
5fdfbfe25a Kernel: Remove old and unused Mutex code. 2018-04-20 21:04:32 -05:00
Subv
b18ccf9399 Kernel: Properly implemented svcWaitProcessWideKey and svcSignalProcessWideKey
They work in tandem with guest code to provide synchronization primitives along with svcArbitrateLock/Unlock
2018-04-20 21:04:27 -05:00
Subv
e81a2080eb Kernel: Corrected the implementation of svcArbitrateLock and svcArbitrateUnlock.
Switch mutexes are no longer kernel objects, they are managed in userland and only use the kernel to handle the contention case.
Mutex addresses store a special flag value (0x40000000) to notify the guest code that there are still some threads waiting for the mutex to be released. This flag is updated when a thread calls ArbitrateUnlock.

TODO:
* Fix svcWaitProcessWideKey
* Fix svcSignalProcessWideKey
* Remove the Mutex class.
2018-04-20 21:04:25 -05:00
bunnei
326b044c19 Merge pull request #367 from lioncash/clamp
math_util: Remove the Clamp() function
2018-04-20 14:18:03 -04:00
bunnei
87f89ac82d Merge pull request #361 from lioncash/common
common_types: Minor changes
2018-04-20 10:27:17 -04:00
Lioncash
fae2dd0344 math_util: Remove the Clamp() function
C++17 adds clamp() to the standard library, so we can remove ours in
favor of it.
2018-04-20 10:14:13 -04:00
bunnei
a904d70afe Merge pull request #368 from lioncash/dynarmic
externals: Update dynarmic to HEAD
2018-04-20 09:48:15 -04:00
bunnei
b11f6f90e7 Merge pull request #360 from lioncash/namespaces
service: Use nested namespace specifiers where applicable
2018-04-20 09:44:40 -04:00
bunnei
4d96997447 Merge pull request #364 from lioncash/thread-local
common/thread: Remove unnecessary feature checking for thread_local
2018-04-20 09:43:52 -04:00
bunnei
b5c204ac6f Merge pull request #362 from lioncash/snprintf
common_funcs: Remove check for VS versions that we don't even support
2018-04-20 09:43:30 -04:00
bunnei
701dd649e6 Merge pull request #363 from lioncash/array-size
common_funcs: Remove ARRAY_SIZE macro
2018-04-20 09:43:02 -04:00
bunnei
79c1ed80e9 Merge pull request #366 from lioncash/vec
vector_math: Remove AsArray() and Write() functions from Vec[2,3,4]
2018-04-20 09:42:41 -04:00
bunnei
cb267093bb Merge pull request #365 from lioncash/codeblock
common: Remove code_block.h
2018-04-20 09:42:15 -04:00
Lioncash
b2febaff2f externals: Update dynarmic to HEAD 2018-04-20 09:02:18 -04:00
Lioncash
956e200f12 vector_math: Remove AsArray() and Write() functions from Vec[2,3,4]
These are all unused and the Write() ones should arguably not even be in the interface. There are better ways to provide this if we ever need it (like iterators).
2018-04-19 22:58:24 -04:00
Lioncash
0eba5911f2 common: Remove code_block.h
We use dynarmic, so this is unued. Anything else we need will likely use Xbyak, so
this header isn't necessary any more.
2018-04-19 22:47:02 -04:00
Lioncash
b134e6afcf common/thread: Remove unnecessary feature checking for thread_local
Every compiler we require already supports it.
2018-04-19 22:41:18 -04:00
Lioncash
d9e316e353 common_funcs: Remove ARRAY_SIZE macro
C++17 has non-member size() which we can just call where necessary.
2018-04-19 22:36:52 -04:00
Lioncash
902fc61ef8 common_funcs: Remove check for VS versions that we don't even support
We don't support any VS versions that don't already have snprintf in the
standard library implementation.
2018-04-19 22:28:56 -04:00
Lioncash
16ffecd8fb common_types: Convert typedefs to using aliases
May as well while we're making changes to this file.
2018-04-19 22:26:35 -04:00
Lioncash
e8e5041955 common_types: Remove unnecessary check for whether or not__func__ is defined
VS has supported this for quite a while.
2018-04-19 22:25:19 -04:00
Lioncash
ccca5e7c28 service: Use nested namespace specifiers where applicable
Tidies up namespace declarations
2018-04-19 22:20:28 -04:00
bunnei
2c8afe1140 Merge pull request #357 from lioncash/guard
renderer_opengl: Add missing header guards
2018-04-19 22:17:25 -04:00
bunnei
2ef04f69b2 Merge pull request #358 from lioncash/explicit
disk_filesystem: Minor changes
2018-04-19 22:16:55 -04:00
bunnei
14bf88a777 Merge pull request #359 from lioncash/redundant
vi: Remove redundant initializers in the constructors
2018-04-19 22:16:17 -04:00
Lioncash
3990da488b vi: Remove redundant initializers in the constructors 2018-04-19 21:34:36 -04:00
Lioncash
80982748c8 disk_filesystem: Remove unused total_entries_in_directory member from Disk_Directory 2018-04-19 21:28:56 -04:00
Lioncash
e61a4dd485 disk_filesystem: Remove redundant initializer in Disk_Directory's constructor 2018-04-19 21:28:07 -04:00
Lioncash
b05f8ea5b5 disk_filesystem: Make constructors explicit where applicable 2018-04-19 21:27:43 -04:00
Lioncash
3841ec4200 renderer_opengl: Add missing header guards 2018-04-19 21:13:59 -04:00
bunnei
17ad56c1dc Merge pull request #356 from lioncash/shader
glsl_shader_decompiler: Minor API changes to ShaderWriter
2018-04-19 21:09:25 -04:00
bunnei
f633b0c875 Merge pull request #355 from Subv/shader_instr
ShaderGen: Fixed TEXS overriding its own texcoords and implemented fmul32i
2018-04-19 21:09:02 -04:00
Lioncash
e3b6f6c016 glsl_shader_decompiler: Use std::string_view instead of std::string for AddLine()
This function doesn't need to take ownership of the string data being
given to it, considering all we do is append the characters to the
internal string instance.

Instead, use a string view to simply reference the string data without
any potential heap allocation.

Now anything that is a raw const char* won't need to be converted to a
std::string before appending.
2018-04-19 20:12:58 -04:00
Lioncash
412b31ad72 glsl_shader_decompiler: Add AddNewLine() function to ShaderWriter
Avoids constructing a std::string just to append a newline character
2018-04-19 20:09:27 -04:00
Lioncash
aa26baa3db glsl_shader_decompiler: Add char overload for ShaderWriter's AddLine()
Avoids constructing a std::string just to append a character.
2018-04-19 20:04:09 -04:00
Lioncash
4ef392906b glsl_shader_decompiler: Append indentation without constructing a separate std::string
The interface of std::string already lets us append N copies of a
character to an existing string.
2018-04-19 19:59:25 -04:00
James Rowe
3f49210234 Merge pull request #348 from jlachniet/patch-1
Technically, yuzu can boot commercial games
2018-04-19 14:07:17 -06:00
Subv
fe84842137 ShaderGen: Implemented the fmul32i shader instruction. 2018-04-19 13:46:32 -05:00
Subv
5367935d35 ShaderGen: Fixed a case where the TEXS instruction would use the same registers for the input and the output.
It will now save the coords before writing the outputs in a subscope.
2018-04-19 13:33:17 -05:00
N00byKing
8a47e7e493 Implement Pull #3528 from citra: use nvidia graphics automatically on laptops with optimus (with AMD support) (#271)
* Port 3528: use nvidia graphics automatically on laptops with optimus

* Force dedicated AMD Card for switchable Graphics

* Ran clang-format
2018-04-19 12:22:26 -06:00
James Rowe
e90a12f80c Merge pull request #352 from bunnei/fix-microprofile
nvflinger: Call MicroProfileFlip on NVFlinger::Compose.
2018-04-19 12:18:47 -06:00
bunnei
d019bb16f6 Merge pull request #353 from Subv/compressed_formats
GPU: Add support for the DXT23 and DXT45 compressed texture formats.
2018-04-19 09:02:19 -04:00
Subv
057170928c GPU: Add support for the DXT23 and DXT45 compressed texture formats. 2018-04-18 20:48:53 -05:00
bunnei
de18592179 nvflinger: Call MicroProfileFlip on NVFlinger::Compose. 2018-04-18 20:28:50 -04:00
bunnei
60e6e8953e Merge pull request #351 from Subv/tex_formats
GPU: Implemented the B5G6R5 format.
2018-04-18 20:20:51 -04:00
Subv
2985056340 GPU: Implemented the B5G6R5 format. 2018-04-18 18:16:45 -05:00
bunnei
ce4f159b1c gl_shader_gen: Support vertical/horizontal viewport flipping. (#347)
* gl_shader_gen: Support vertical/horizontal viewport flipping.

* fixup! gl_shader_gen: Support vertical/horizontal viewport flipping.
2018-04-18 16:42:40 -04:00
bunnei
6a999cf800 Merge pull request #350 from Subv/tex_components
GPU: Fixed the incorrect component order in ABGR8 textures.
2018-04-18 15:36:00 -04:00
Subv
43d98ca8fe GLCache: Added boilerplate code to make supporting configurable texture component types.
For now only the UNORM type is supported.
2018-04-18 14:17:28 -05:00
Subv
5b3fab6766 GLCache: Unify texture and framebuffer formats when converting to OpenGL. 2018-04-18 14:17:28 -05:00
Subv
b2c1672e10 GPU: Texture format 8 and framebuffer format 0xD5 are actually ABGR8. 2018-04-18 14:17:27 -05:00
bunnei
d3f9ea90e7 Merge pull request #349 from Subv/texturing
GPU: Support non-tiled textures and configurable block height.
2018-04-18 14:46:10 -04:00
Subv
48d4efbd69 GPU: Pitch textures are now supported, don't assert when encountering them. 2018-04-18 12:52:53 -05:00
Subv
a3e82e8e1f GLCache: Take into account the texture's block height when caching and unswizzling. 2018-04-18 12:52:53 -05:00
Subv
ac09b5a2e9 GLCache: Added a function to convert cached PixelFormats back to texture formats.
TODO: The way we handle cached formats must change, framebuffer and texture formats are too different to keep them in the same place.
2018-04-18 12:52:52 -05:00
Subv
6b63aaa5b4 GPU: Allow using a configurable block height when unswizzling textures. 2018-04-18 12:52:51 -05:00
Subv
db5f2bfa7e GPU/TIC: Added the pitch and block height fields to the TIC structure. 2018-04-18 11:38:39 -05:00
jlachniet
f600f6eebd Technically, yuzu can boot commercial games
Clarifies the yuzu cannot play commercial games to any reasonable extent, rather than not at all.
2018-04-18 09:18:41 -04:00
bunnei
c93ea96366 Merge pull request #346 from bunnei/misc-gpu-improvements
Misc gpu improvements
2018-04-17 22:17:07 -04:00
bunnei
71b4a3b9f6 Merge pull request #344 from bunnei/shader-decompiler-p2
Shader decompiler changes part 2
2018-04-17 22:10:53 -04:00
bunnei
9dc0d13ba5 Merge pull request #345 from bunnei/blending
renderer_opengl: Implement BlendEquation and BlendFunc.
2018-04-17 21:45:36 -04:00
bunnei
7222d9a4c3 gl_rasterizer_cache: Add missing LOG statements. 2018-04-17 21:44:36 -04:00
bunnei
9df8e924fb texture: Add missing formats. 2018-04-17 21:41:36 -04:00
bunnei
3ed8a1cac7 gpu: Add several framebuffer formats to RenderTargetFormat. 2018-04-17 21:40:38 -04:00
bunnei
4a8eb6745e maxwell3d: Allow Texture2DNoMipmap as Texture2D. 2018-04-17 21:39:15 -04:00
bunnei
531c25386e shader_bytecode: Make ctor's constexpr and explicit. 2018-04-17 21:27:07 -04:00
bunnei
174cba5c58 renderer_opengl: Implement BlendEquation and BlendFunc. 2018-04-17 18:11:48 -04:00
bunnei
e59126809c bit_field: Remove is_pod check, add is_trivially_copyable_v. 2018-04-17 18:00:18 -04:00
bunnei
1f6fe062ca gl_shader_decompiler: Fix warnings with MarkAsUsed. 2018-04-17 16:36:44 -04:00
bunnei
ed542a7309 gl_shader_decompiler: Cleanup logging, updating to NGLOG_*. 2018-04-17 16:36:44 -04:00
bunnei
ef2d5ab0c1 gl_shader_decompiler: Implement several MUFU subops and abs_d. 2018-04-17 16:36:43 -04:00
bunnei
59f4ff4659 gl_shader_decompiler: Fix swizzle in GetRegister. 2018-04-17 16:36:42 -04:00
bunnei
5a28dce9eb gl_shader_decompiler: Implement FMUL/FADD/FFMA immediate instructions. 2018-04-17 16:36:42 -04:00
bunnei
8d4899d6ea gl_shader_decompiler: Allow vertex position to be used in fragment shader. 2018-04-17 16:36:40 -04:00
bunnei
95144cc39c gl_shader_decompiler: Implement IPA instruction. 2018-04-17 16:36:39 -04:00
bunnei
8b4443c966 gl_shader_decompiler: Add support for TEXS instruction. 2018-04-17 16:36:38 -04:00
bunnei
5ba71369ac gl_shader_decompiler: Use fragment output color for GPR 0-3. 2018-04-17 15:25:54 -04:00
bunnei
5d529698c9 gl_shader_decompiler: Partially implement MUFU. 2018-04-17 15:25:54 -04:00
bunnei
5b9bcbf438 Merge pull request #341 from shinyquagsire23/pfs-hfs-impl
file_sys: Add HFS/PFS helper component
2018-04-17 14:39:20 -04:00
bunnei
2b082e2710 Merge pull request #343 from Subv/tex_wrap_4
GPU: Implement some wrap modes
2018-04-17 12:25:24 -04:00
Hexagon12
e52a87b98a Various service name fixes - part 2 (rebased) (#322)
* Updated ACC with more service names

* Updated SVC with more service names

* Updated set with more service names

* Updated sockets with more service names

* Updated SPL with more service names

* Updated time with more service names

* Updated vi with more service names
2018-04-17 11:37:43 -04:00
bunnei
0905dc1ff4 Merge pull request #342 from bunnei/indexed-verts
Implement indexed mode rendering
2018-04-17 11:34:22 -04:00
Subv
636ad34707 MaxwellToGL: Implemented tex wrap mode 1 (Wrap, GL_REPEAT). 2018-04-17 10:17:18 -05:00
Subv
7fc516cc1a MaxwellToGL: Added a TODO and partial implementation of maxwell wrap mode 4 (Clamp, GL_CLAMP).
This clamp mode was removed from OpenGL as of 3.1, we can emulate it by using GL_CLAMP_TO_BORDER to get the border color of the texture, and then manually sampling the edge to mix them in the fragment shader.
2018-04-17 10:16:50 -05:00
bunnei
77bdc49343 gl_rendering: Use NGLOG* for changed code. 2018-04-16 21:23:28 -04:00
bunnei
1a1af3fda3 gl_rasterizer: Implement indexed vertex mode. 2018-04-16 21:10:15 -04:00
184 changed files with 1585 additions and 1541 deletions

View File

@@ -7,7 +7,7 @@ yuzu is an experimental open-source emulator for the Nintendo Switch from the cr
It is written in C++ with portability in mind, with builds actively maintained for Windows, Linux and macOS. The emulator is currently only useful for homebrew development and research purposes.
yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu does not run any commercial Switch games. yuzu can boot some games, to varying degrees of success, but does not implement any of the necessary GPU features to render 3D graphics.
yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu cannot play any commercial games without major problems. yuzu can boot some games, to varying degrees of success, but does not implement any of the necessary GPU features to render 3D graphics.
yuzu is licensed under the GPLv2 (or any later version). Refer to the license.txt file included.

View File

@@ -34,7 +34,6 @@ add_library(common STATIC
chunk_file.h
cityhash.cpp
cityhash.h
code_block.h
color.h
common_funcs.h
common_paths.h

View File

@@ -192,11 +192,6 @@ private:
static_assert(position < 8 * sizeof(T), "Invalid position");
static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
static_assert(bits > 0, "Invalid number of bits");
static_assert(std::is_pod<T>::value, "Invalid base type");
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField");
};
#pragma pack()
#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
static_assert(std::is_trivially_copyable<BitField<0, 1, unsigned>>::value,
"BitField must be trivially copyable");
#endif

View File

@@ -1,85 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <cstddef>
#include "common/common_types.h"
#include "common/memory_util.h"
// Everything that needs to generate code should inherit from this.
// You get memory management for free, plus, you can use all emitter functions without
// having to prefix them with gen-> or something similar.
// Example implementation:
// class JIT : public CodeBlock<ARMXEmitter> {}
template <class T>
class CodeBlock : public T, NonCopyable {
private:
// A privately used function to set the executable RAM space to something invalid.
// For debugging usefulness it should be used to set the RAM to a host specific breakpoint
// instruction
virtual void PoisonMemory() = 0;
protected:
u8* region;
size_t region_size;
public:
CodeBlock() : region(nullptr), region_size(0) {}
virtual ~CodeBlock() {
if (region)
FreeCodeSpace();
}
// Call this before you generate any code.
void AllocCodeSpace(int size) {
region_size = size;
region = (u8*)AllocateExecutableMemory(region_size);
T::SetCodePtr(region);
}
// Always clear code space with breakpoints, so that if someone accidentally executes
// uninitialized, it just breaks into the debugger.
void ClearCodeSpace() {
PoisonMemory();
ResetCodePtr();
}
// Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
void FreeCodeSpace() {
#ifdef __SYMBIAN32__
ResetExecutableMemory(region);
#else
FreeMemoryPages(region, region_size);
#endif
region = nullptr;
region_size = 0;
}
bool IsInSpace(const u8* ptr) {
return (ptr >= region) && (ptr < (region + region_size));
}
// Cannot currently be undone. Will write protect the entire code region.
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
void WriteProtect() {
WriteProtectMemory(region, region_size, true);
}
void ResetCodePtr() {
T::SetCodePtr(region);
}
size_t GetSpaceLeft() const {
return region_size - (T::GetCodePtr() - region);
}
u8* GetBasePtr() {
return region;
}
size_t GetOffset(const u8* ptr) const {
return ptr - region;
}
};

View File

@@ -9,8 +9,6 @@
#endif
#include "common/common_types.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
/// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
#define CONCAT2(x, y) DO_CONCAT2(x, y)
#define DO_CONCAT2(x, y) x##y
@@ -74,11 +72,6 @@ inline u64 _rotr64(u64 x, unsigned int shift) {
#else // _MSC_VER
#if (_MSC_VER < 1900)
// Function Cross-Compatibility
#define snprintf _snprintf
#endif
// Locale Cross-Compatibility
#define locale_t _locale_t

View File

@@ -27,29 +27,23 @@
#include <array>
#include <cstdint>
#ifdef _MSC_VER
#ifndef __func__
#define __func__ __FUNCTION__
#endif
#endif
using u8 = std::uint8_t; ///< 8-bit unsigned byte
using u16 = std::uint16_t; ///< 16-bit unsigned short
using u32 = std::uint32_t; ///< 32-bit unsigned word
using u64 = std::uint64_t; ///< 64-bit unsigned int
typedef std::uint8_t u8; ///< 8-bit unsigned byte
typedef std::uint16_t u16; ///< 16-bit unsigned short
typedef std::uint32_t u32; ///< 32-bit unsigned word
typedef std::uint64_t u64; ///< 64-bit unsigned int
using s8 = std::int8_t; ///< 8-bit signed byte
using s16 = std::int16_t; ///< 16-bit signed short
using s32 = std::int32_t; ///< 32-bit signed word
using s64 = std::int64_t; ///< 64-bit signed int
typedef std::int8_t s8; ///< 8-bit signed byte
typedef std::int16_t s16; ///< 16-bit signed short
typedef std::int32_t s32; ///< 32-bit signed word
typedef std::int64_t s64; ///< 64-bit signed int
typedef float f32; ///< 32-bit floating point
typedef double f64; ///< 64-bit floating point
using f32 = float; ///< 32-bit floating point
using f64 = double; ///< 64-bit floating point
// TODO: It would be nice to eventually replace these with strong types that prevent accidental
// conversion between each other.
typedef u64 VAddr; ///< Represents a pointer in the userspace virtual address space.
typedef u64 PAddr; ///< Represents a pointer in the ARM11 physical address space.
using VAddr = u64; ///< Represents a pointer in the userspace virtual address space.
using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space.
using u128 = std::array<std::uint64_t, 2>;
static_assert(sizeof(u128) == 16, "u128 must be 128 bits wide");

View File

@@ -17,11 +17,6 @@ inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start
return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1));
}
template <typename T>
inline T Clamp(const T val, const T& min, const T& max) {
return std::max(min, std::min(max, val));
}
template <class T>
struct Rectangle {
T left;

View File

@@ -11,25 +11,6 @@
#include <thread>
#include "common/common_types.h"
// Support for C++11's thread_local keyword was surprisingly spotty in compilers until very
// recently. Fortunately, thread local variables have been well supported for compilers for a while,
// but with semantics supporting only POD types, so we can use a few defines to get some amount of
// backwards compat support.
// WARNING: This only works correctly with POD types.
#if defined(__clang__)
#if !__has_feature(cxx_thread_local)
#define thread_local __thread
#endif
#elif defined(__GNUC__)
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#define thread_local __thread
#endif
#elif defined(_MSC_VER)
#if _MSC_VER < 1900
#define thread_local __declspec(thread)
#endif
#endif
namespace Common {
int CurrentThreadId();

View File

@@ -55,10 +55,6 @@ public:
T x;
T y;
T* AsArray() {
return &x;
}
Vec2() = default;
Vec2(const T& _x, const T& _y) : x(_x), y(_y) {}
@@ -71,11 +67,6 @@ public:
return Vec2<T>(f, f);
}
void Write(T a[2]) {
a[0] = x;
a[1] = y;
}
Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
return MakeVec(x + other.x, y + other.y);
}
@@ -205,10 +196,6 @@ public:
T y;
T z;
T* AsArray() {
return &x;
}
Vec3() = default;
Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
@@ -225,12 +212,6 @@ public:
return MakeVec(f, f, f);
}
void Write(T a[3]) {
a[0] = x;
a[1] = y;
a[2] = z;
}
Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
return MakeVec(x + other.x, y + other.y, z + other.z);
}
@@ -416,10 +397,6 @@ public:
T z;
T w;
T* AsArray() {
return &x;
}
Vec4() = default;
Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {}
@@ -436,13 +413,6 @@ public:
return Vec4<T>(f, f, f, f);
}
void Write(T a[4]) {
a[0] = x;
a[1] = y;
a[2] = z;
a[3] = w;
}
Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
return MakeVec(x + other.x, y + other.y, z + other.z, w + other.w);
}

View File

@@ -42,8 +42,6 @@ add_library(core STATIC
hle/kernel/client_port.h
hle/kernel/client_session.cpp
hle/kernel/client_session.h
hle/kernel/condition_variable.cpp
hle/kernel/condition_variable.h
hle/kernel/errors.h
hle/kernel/event.cpp
hle/kernel/event.h

View File

@@ -183,7 +183,7 @@ bool Disk_Storage::SetSize(const u64 size) const {
return true;
}
Disk_Directory::Disk_Directory(const std::string& path) : directory() {
Disk_Directory::Disk_Directory(const std::string& path) {
unsigned size = FileUtil::ScanDirectoryTree(path, directory);
directory.size = size;
directory.isDirectory = true;

View File

@@ -43,7 +43,7 @@ protected:
class Disk_Storage : public StorageBackend {
public:
Disk_Storage(std::shared_ptr<FileUtil::IOFile> file) : file(std::move(file)) {}
explicit Disk_Storage(std::shared_ptr<FileUtil::IOFile> file) : file(std::move(file)) {}
ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override;
ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
@@ -60,7 +60,7 @@ private:
class Disk_Directory : public DirectoryBackend {
public:
Disk_Directory(const std::string& path);
explicit Disk_Directory(const std::string& path);
~Disk_Directory() override {
Close();
@@ -74,7 +74,6 @@ public:
}
protected:
u32 total_entries_in_directory;
FileUtil::FSTEntry directory;
// We need to remember the last entry we returned, so a subsequent call to Read will continue

View File

@@ -1,64 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object_address_table.h"
#include "core/hle/kernel/thread.h"
namespace Kernel {
ConditionVariable::ConditionVariable() {}
ConditionVariable::~ConditionVariable() {}
ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr,
std::string name) {
SharedPtr<ConditionVariable> condition_variable(new ConditionVariable);
condition_variable->name = std::move(name);
condition_variable->guest_addr = guest_addr;
condition_variable->mutex_addr = 0;
// Condition variables are referenced by guest address, so track this in the kernel
g_object_address_table.Insert(guest_addr, condition_variable);
return MakeResult<SharedPtr<ConditionVariable>>(std::move(condition_variable));
}
bool ConditionVariable::ShouldWait(Thread* thread) const {
return GetAvailableCount() <= 0;
}
void ConditionVariable::Acquire(Thread* thread) {
if (GetAvailableCount() <= 0)
return;
SetAvailableCount(GetAvailableCount() - 1);
}
ResultCode ConditionVariable::Release(s32 target) {
if (target == -1) {
// When -1, wake up all waiting threads
SetAvailableCount(static_cast<s32>(GetWaitingThreads().size()));
WakeupAllWaitingThreads();
} else {
// Otherwise, wake up just a single thread
SetAvailableCount(target);
WakeupWaitingThread(GetHighestPriorityReadyThread());
}
return RESULT_SUCCESS;
}
s32 ConditionVariable::GetAvailableCount() const {
return Memory::Read32(guest_addr);
}
void ConditionVariable::SetAvailableCount(s32 value) const {
Memory::Write32(guest_addr, value);
}
} // namespace Kernel

View File

@@ -1,63 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <queue>
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
namespace Kernel {
class ConditionVariable final : public WaitObject {
public:
/**
* Creates a condition variable.
* @param guest_addr Address of the object tracking the condition variable in guest memory. If
* specified, this condition variable will update the guest object when its state changes.
* @param name Optional name of condition variable.
* @return The created condition variable.
*/
static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr,
std::string name = "Unknown");
std::string GetTypeName() const override {
return "ConditionVariable";
}
std::string GetName() const override {
return name;
}
static const HandleType HANDLE_TYPE = HandleType::ConditionVariable;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
s32 GetAvailableCount() const;
void SetAvailableCount(s32 value) const;
std::string name; ///< Name of condition variable (optional)
VAddr guest_addr; ///< Address of the guest condition variable value
VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this condition
///< variable, used for implementing events
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
/**
* Releases a slot from a condition variable.
* @param target The number of threads to wakeup, -1 is all.
* @return ResultCode indicating if the operation succeeded.
*/
ResultCode Release(s32 target);
private:
ConditionVariable();
~ConditionVariable() override;
};
} // namespace Kernel

View File

@@ -20,6 +20,7 @@ enum {
MaxConnectionsReached = 52,
// Confirmed Switch OS error codes
MisalignedAddress = 102,
InvalidHandle = 114,
Timeout = 117,
SynchronizationCanceled = 118,

View File

@@ -18,12 +18,10 @@ using Handle = u32;
enum class HandleType : u32 {
Unknown,
Event,
Mutex,
SharedMemory,
Thread,
Process,
AddressArbiter,
ConditionVariable,
Timer,
ResourceLimit,
CodeSet,
@@ -63,9 +61,7 @@ public:
bool IsWaitable() const {
switch (GetHandleType()) {
case HandleType::Event:
case HandleType::Mutex:
case HandleType::Thread:
case HandleType::ConditionVariable:
case HandleType::Timer:
case HandleType::ServerPort:
case HandleType::ServerSession:

View File

@@ -7,6 +7,7 @@
#include <boost/range/algorithm_ext/erase.hpp>
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/mutex.h"
@@ -15,124 +16,120 @@
namespace Kernel {
void ReleaseThreadMutexes(Thread* thread) {
for (auto& mtx : thread->held_mutexes) {
mtx->SetHasWaiters(false);
mtx->SetHoldingThread(nullptr);
mtx->WakeupAllWaitingThreads();
}
thread->held_mutexes.clear();
}
/// Returns the number of threads that are waiting for a mutex, and the highest priority one among
/// those.
static std::pair<SharedPtr<Thread>, u32> GetHighestPriorityMutexWaitingThread(
SharedPtr<Thread> current_thread, VAddr mutex_addr) {
Mutex::Mutex() {}
Mutex::~Mutex() {}
SharedPtr<Thread> highest_priority_thread;
u32 num_waiters = 0;
SharedPtr<Mutex> Mutex::Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr,
std::string name) {
SharedPtr<Mutex> mutex(new Mutex);
for (auto& thread : current_thread->wait_mutex_threads) {
if (thread->mutex_wait_address != mutex_addr)
continue;
mutex->guest_addr = guest_addr;
mutex->name = std::move(name);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
// If mutex was initialized with a holding thread, acquire it by the holding thread
if (holding_thread) {
mutex->Acquire(holding_thread.get());
++num_waiters;
if (highest_priority_thread == nullptr ||
thread->GetPriority() < highest_priority_thread->GetPriority()) {
highest_priority_thread = thread;
}
}
// Mutexes are referenced by guest address, so track this in the kernel
g_object_address_table.Insert(guest_addr, mutex);
return mutex;
return {highest_priority_thread, num_waiters};
}
bool Mutex::ShouldWait(Thread* thread) const {
auto holding_thread = GetHoldingThread();
return holding_thread != nullptr && thread != holding_thread;
/// Update the mutex owner field of all threads waiting on the mutex to point to the new owner.
static void TransferMutexOwnership(VAddr mutex_addr, SharedPtr<Thread> current_thread,
SharedPtr<Thread> new_owner) {
auto threads = current_thread->wait_mutex_threads;
for (auto& thread : threads) {
if (thread->mutex_wait_address != mutex_addr)
continue;
ASSERT(thread->lock_owner == current_thread);
current_thread->RemoveMutexWaiter(thread);
if (new_owner != thread)
new_owner->AddMutexWaiter(thread);
}
}
void Mutex::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle,
Handle requesting_thread_handle) {
// The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
}
priority = thread->current_priority;
thread->held_mutexes.insert(this);
SetHoldingThread(thread);
thread->UpdatePriority();
Core::System::GetInstance().PrepareReschedule();
}
SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
ResultCode Mutex::Release(Thread* thread) {
auto holding_thread = GetHoldingThread();
ASSERT(holding_thread);
// TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another
// thread.
ASSERT(requesting_thread == GetCurrentThread());
// We can only release the mutex if it's held by the calling thread.
ASSERT(thread == holding_thread);
u32 addr_value = Memory::Read32(address);
// If the mutex isn't being held, just return success.
if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) {
return RESULT_SUCCESS;
}
if (holding_thread == nullptr)
return ERR_INVALID_HANDLE;
// Wait until the mutex is released
GetCurrentThread()->mutex_wait_address = address;
GetCurrentThread()->wait_handle = requesting_thread_handle;
GetCurrentThread()->status = THREADSTATUS_WAIT_MUTEX;
GetCurrentThread()->wakeup_callback = nullptr;
// Update the lock holder thread's priority to prevent priority inversion.
holding_thread->AddMutexWaiter(GetCurrentThread());
holding_thread->held_mutexes.erase(this);
holding_thread->UpdatePriority();
SetHoldingThread(nullptr);
SetHasWaiters(!GetWaitingThreads().empty());
WakeupAllWaitingThreads();
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
void Mutex::AddWaitingThread(SharedPtr<Thread> thread) {
WaitObject::AddWaitingThread(thread);
thread->pending_mutexes.insert(this);
SetHasWaiters(true);
UpdatePriority();
}
void Mutex::RemoveWaitingThread(Thread* thread) {
WaitObject::RemoveWaitingThread(thread);
thread->pending_mutexes.erase(this);
if (!GetHasWaiters())
SetHasWaiters(!GetWaitingThreads().empty());
UpdatePriority();
}
void Mutex::UpdatePriority() {
if (!GetHoldingThread())
return;
u32 best_priority = THREADPRIO_LOWEST;
for (auto& waiter : GetWaitingThreads()) {
if (waiter->current_priority < best_priority)
best_priority = waiter->current_priority;
ResultCode Mutex::Release(VAddr address) {
// The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
}
if (best_priority != priority) {
priority = best_priority;
GetHoldingThread()->UpdatePriority();
auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address);
// There are no more threads waiting for the mutex, release it completely.
if (thread == nullptr) {
ASSERT(GetCurrentThread()->wait_mutex_threads.empty());
Memory::Write32(address, 0);
return RESULT_SUCCESS;
}
}
Handle Mutex::GetOwnerHandle() const {
GuestState guest_state{Memory::Read32(guest_addr)};
return guest_state.holding_thread_handle;
}
// Transfer the ownership of the mutex from the previous owner to the new one.
TransferMutexOwnership(address, GetCurrentThread(), thread);
SharedPtr<Thread> Mutex::GetHoldingThread() const {
GuestState guest_state{Memory::Read32(guest_addr)};
return g_handle_table.Get<Thread>(guest_state.holding_thread_handle);
}
u32 mutex_value = thread->wait_handle;
void Mutex::SetHoldingThread(SharedPtr<Thread> thread) {
GuestState guest_state{Memory::Read32(guest_addr)};
guest_state.holding_thread_handle.Assign(thread ? thread->guest_handle : 0);
Memory::Write32(guest_addr, guest_state.raw);
}
if (num_waiters >= 2) {
// Notify the guest that there are still some threads waiting for the mutex
mutex_value |= Mutex::MutexHasWaitersFlag;
}
bool Mutex::GetHasWaiters() const {
GuestState guest_state{Memory::Read32(guest_addr)};
return guest_state.has_waiters != 0;
}
// Grant the mutex to the next waiting thread and resume it.
Memory::Write32(address, mutex_value);
void Mutex::SetHasWaiters(bool has_waiters) {
GuestState guest_state{Memory::Read32(guest_addr)};
guest_state.has_waiters.Assign(has_waiters ? 1 : 0);
Memory::Write32(guest_addr, guest_state.raw);
}
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
thread->lock_owner = nullptr;
thread->condvar_wait_address = 0;
thread->mutex_wait_address = 0;
thread->wait_handle = 0;
return RESULT_SUCCESS;
}
} // namespace Kernel

View File

@@ -15,87 +15,23 @@ namespace Kernel {
class Thread;
class Mutex final : public WaitObject {
class Mutex final {
public:
/**
* Creates a mutex.
* @param holding_thread Specifies a thread already holding the mutex. If not nullptr, this
* thread will acquire the mutex.
* @param guest_addr Address of the object tracking the mutex in guest memory. If specified,
* this mutex will update the guest object when its state changes.
* @param name Optional name of mutex
* @return Pointer to new Mutex object
*/
static SharedPtr<Mutex> Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr = 0,
std::string name = "Unknown");
/// Flag that indicates that a mutex still has threads waiting for it.
static constexpr u32 MutexHasWaitersFlag = 0x40000000;
/// Mask of the bits in a mutex address value that contain the mutex owner.
static constexpr u32 MutexOwnerMask = 0xBFFFFFFF;
std::string GetTypeName() const override {
return "Mutex";
}
std::string GetName() const override {
return name;
}
/// Attempts to acquire a mutex at the specified address.
static ResultCode TryAcquire(VAddr address, Handle holding_thread_handle,
Handle requesting_thread_handle);
static const HandleType HANDLE_TYPE = HandleType::Mutex;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
VAddr guest_addr; ///< Address of the guest mutex value
/**
* Elevate the mutex priority to the best priority
* among the priorities of all its waiting threads.
*/
void UpdatePriority();
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
void AddWaitingThread(SharedPtr<Thread> thread) override;
void RemoveWaitingThread(Thread* thread) override;
/**
* Attempts to release the mutex from the specified thread.
* @param thread Thread that wants to release the mutex.
* @returns The result code of the operation.
*/
ResultCode Release(Thread* thread);
/// Gets the handle to the holding process stored in the guest state.
Handle GetOwnerHandle() const;
/// Gets the Thread pointed to by the owner handle
SharedPtr<Thread> GetHoldingThread() const;
/// Sets the holding process handle in the guest state.
void SetHoldingThread(SharedPtr<Thread> thread);
/// Returns the has_waiters bit in the guest state.
bool GetHasWaiters() const;
/// Sets the has_waiters bit in the guest state.
void SetHasWaiters(bool has_waiters);
/// Releases the mutex at the specified address.
static ResultCode Release(VAddr address);
private:
Mutex();
~Mutex() override;
/// Object in guest memory used to track the mutex state
union GuestState {
u32_le raw;
/// Handle of the thread that currently holds the mutex, 0 if available
BitField<0, 30, u32_le> holding_thread_handle;
/// 1 when there are threads waiting for this mutex, otherwise 0
BitField<30, 1, u32_le> has_waiters;
};
static_assert(sizeof(GuestState) == 4, "GuestState size is incorrect");
Mutex() = default;
~Mutex() = default;
};
/**
* Releases all the mutexes held by the specified thread
* @param thread Thread that is holding the mutexes
*/
void ReleaseThreadMutexes(Thread* thread);
} // namespace Kernel

View File

@@ -4,6 +4,7 @@
#include <algorithm>
#include <cinttypes>
#include <iterator>
#include "common/logging/log.h"
#include "common/microprofile.h"
@@ -12,7 +13,6 @@
#include "core/core_timing.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/mutex.h"
@@ -261,32 +261,14 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
"requesting_current_thread_handle=0x%08X",
holding_thread_handle, mutex_addr, requesting_thread_handle);
SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
ASSERT(requesting_thread);
ASSERT(requesting_thread == GetCurrentThread());
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
if (!mutex) {
// Create a new mutex for the specified address if one does not already exist
mutex = Mutex::Create(holding_thread, mutex_addr);
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
}
ASSERT(holding_thread == mutex->GetHoldingThread());
return WaitSynchronization1(mutex, requesting_thread.get());
return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle);
}
/// Unlock a mutex
static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr);
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
ASSERT(mutex);
return mutex->Release(GetCurrentThread());
return Mutex::Release(mutex_addr);
}
/// Break program execution
@@ -411,11 +393,6 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
}
thread->SetPriority(priority);
thread->UpdatePriority();
// Update the mutexes that this thread is waiting for
for (auto& mutex : thread->pending_mutexes)
mutex->UpdatePriority();
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
@@ -633,77 +610,20 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
ASSERT(thread);
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
if (!mutex) {
// Create a new mutex for the specified address if one does not already exist
mutex = Mutex::Create(thread, mutex_addr);
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
}
CASCADE_CODE(Mutex::Release(mutex_addr));
SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist
condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
}
SharedPtr<Thread> current_thread = GetCurrentThread();
current_thread->condvar_wait_address = condition_variable_addr;
current_thread->mutex_wait_address = mutex_addr;
current_thread->wait_handle = thread_handle;
current_thread->status = THREADSTATUS_WAIT_MUTEX;
current_thread->wakeup_callback = nullptr;
if (condition_variable->mutex_addr) {
// Previously created the ConditionVariable using WaitProcessWideKeyAtomic, verify
// everything is correct
ASSERT(condition_variable->mutex_addr == mutex_addr);
} else {
// Previously created the ConditionVariable using SignalProcessWideKey, set the mutex
// associated with it
condition_variable->mutex_addr = mutex_addr;
}
current_thread->WakeAfterDelay(nano_seconds);
if (mutex->GetOwnerHandle()) {
// Release the mutex if the current thread is holding it
mutex->Release(thread.get());
}
auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason,
SharedPtr<Thread> thread,
SharedPtr<WaitObject> object, size_t index) {
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
if (reason == ThreadWakeupReason::Timeout) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
return true;
}
ASSERT(reason == ThreadWakeupReason::Signal);
// Now try to acquire the mutex and don't resume if it's not available.
if (!mutex->ShouldWait(thread.get())) {
mutex->Acquire(thread.get());
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
return true;
}
if (nano_seconds == 0) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
return true;
}
thread->wait_objects = {mutex};
mutex->AddWaitingThread(thread);
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
// Create an event to wake the thread up after the
// specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = DefaultThreadWakeupCallback;
Core::System::GetInstance().PrepareReschedule();
return false;
};
CASCADE_CODE(
WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback));
// Note: Deliberately don't attempt to inherit the lock owner's priority.
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
@@ -712,24 +632,53 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x",
condition_variable_addr, target);
// Wakeup all or one thread - Any other value is unimplemented
ASSERT(target == -1 || target == 1);
u32 processed = 0;
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist
condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
}
for (auto& thread : thread_list) {
if (thread->condvar_wait_address != condition_variable_addr)
continue;
CASCADE_CODE(condition_variable->Release(target));
// Only process up to 'target' threads, unless 'target' is -1, in which case process
// them all.
if (target != -1 && processed >= target)
break;
if (condition_variable->mutex_addr) {
// If a mutex was created for this condition_variable, wait the current thread on it
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(condition_variable->mutex_addr);
return WaitSynchronization1(mutex, GetCurrentThread());
// If the mutex is not yet acquired, acquire it.
u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
if (mutex_val == 0) {
// We were able to acquire the mutex, resume this thread.
Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
auto lock_owner = thread->lock_owner;
if (lock_owner)
lock_owner->RemoveMutexWaiter(thread);
thread->lock_owner = nullptr;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
} else {
// Couldn't acquire the mutex, block the thread.
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->status != THREADSTATUS_RUNNING);
thread->status = THREADSTATUS_WAIT_MUTEX;
thread->wakeup_callback = nullptr;
// Signal that the mutex now has a waiting thread.
Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
owner->AddMutexWaiter(thread);
Core::System::GetInstance().PrepareReschedule();
}
++processed;
}
return RESULT_SUCCESS;
@@ -861,14 +810,14 @@ static const FunctionDef SVC_Table[] = {
{0x2B, nullptr, "FlushDataCache"},
{0x2C, nullptr, "MapPhysicalMemory"},
{0x2D, nullptr, "UnmapPhysicalMemory"},
{0x2E, nullptr, "Unknown"},
{0x2E, nullptr, "GetNextThreadInfo"},
{0x2F, nullptr, "GetLastThreadInfo"},
{0x30, nullptr, "GetResourceLimitLimitValue"},
{0x31, nullptr, "GetResourceLimitCurrentValue"},
{0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
{0x34, nullptr, "Unknown"},
{0x35, nullptr, "Unknown"},
{0x34, nullptr, "WaitForAddress"},
{0x35, nullptr, "SignalToAddress"},
{0x36, nullptr, "Unknown"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
@@ -876,7 +825,7 @@ static const FunctionDef SVC_Table[] = {
{0x3A, nullptr, "Unknown"},
{0x3B, nullptr, "Unknown"},
{0x3C, nullptr, "DumpInfo"},
{0x3D, nullptr, "Unknown"},
{0x3D, nullptr, "DumpInfoNew"},
{0x3E, nullptr, "Unknown"},
{0x3F, nullptr, "Unknown"},
{0x40, nullptr, "CreateSession"},
@@ -887,9 +836,9 @@ static const FunctionDef SVC_Table[] = {
{0x45, nullptr, "CreateEvent"},
{0x46, nullptr, "Unknown"},
{0x47, nullptr, "Unknown"},
{0x48, nullptr, "Unknown"},
{0x49, nullptr, "Unknown"},
{0x4A, nullptr, "Unknown"},
{0x48, nullptr, "AllocateUnsafeMemory"},
{0x49, nullptr, "FreeUnsafeMemory"},
{0x4A, nullptr, "SetUnsafeAllocationLimit"},
{0x4B, nullptr, "CreateJitMemory"},
{0x4C, nullptr, "MapJitMemory"},
{0x4D, nullptr, "SleepSystem"},
@@ -926,7 +875,7 @@ static const FunctionDef SVC_Table[] = {
{0x6C, nullptr, "SetHardwareBreakPoint"},
{0x6D, nullptr, "GetDebugThreadParam"},
{0x6E, nullptr, "Unknown"},
{0x6F, nullptr, "Unknown"},
{0x6F, nullptr, "GetMemoryInfo"},
{0x70, nullptr, "CreatePort"},
{0x71, nullptr, "ManageNamedPort"},
{0x72, nullptr, "ConnectToPort"},
@@ -946,7 +895,7 @@ static const FunctionDef SVC_Table[] = {
};
static const FunctionDef* GetSVCInfo(u32 func_num) {
if (func_num >= ARRAY_SIZE(SVC_Table)) {
if (func_num >= std::size(SVC_Table)) {
LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num);
return nullptr;
}

View File

@@ -77,9 +77,6 @@ void Thread::Stop() {
}
wait_objects.clear();
// Release all the mutexes that this thread holds
ReleaseThreadMutexes(this);
// Mark the TLS slot in the thread's page as free.
u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
u64 tls_slot =
@@ -126,6 +123,19 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
}
if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
thread->wait_handle) {
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
auto lock_owner = thread->lock_owner;
// Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
// and don't have a lock owner.
ASSERT(lock_owner == nullptr);
}
if (resume)
thread->ResumeFromWait();
}
@@ -151,6 +161,7 @@ void Thread::ResumeFromWait() {
case THREADSTATUS_WAIT_HLE_EVENT:
case THREADSTATUS_WAIT_SLEEP:
case THREADSTATUS_WAIT_IPC:
case THREADSTATUS_WAIT_MUTEX:
break;
case THREADSTATUS_READY:
@@ -256,7 +267,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->last_running_ticks = CoreTiming::GetTicks();
thread->processor_id = processor_id;
thread->wait_objects.clear();
thread->wait_address = 0;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
thread->name = std::move(name);
thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
thread->owner_process = owner_process;
@@ -317,17 +330,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
void Thread::SetPriority(u32 priority) {
ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
"Invalid priority value.");
Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority);
nominal_priority = current_priority = priority;
}
void Thread::UpdatePriority() {
u32 best_priority = nominal_priority;
for (auto& mutex : held_mutexes) {
if (mutex->priority < best_priority)
best_priority = mutex->priority;
}
BoostPriority(best_priority);
nominal_priority = priority;
UpdatePriority();
}
void Thread::BoostPriority(u32 priority) {
@@ -377,6 +381,38 @@ VAddr Thread::GetCommandBufferAddress() const {
return GetTLSAddress() + CommandHeaderOffset;
}
void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
thread->lock_owner = this;
wait_mutex_threads.emplace_back(std::move(thread));
UpdatePriority();
}
void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
boost::remove_erase(wait_mutex_threads, thread);
thread->lock_owner = nullptr;
UpdatePriority();
}
void Thread::UpdatePriority() {
// Find the highest priority among all the threads that are waiting for this thread's lock
u32 new_priority = nominal_priority;
for (const auto& thread : wait_mutex_threads) {
if (thread->nominal_priority < new_priority)
new_priority = thread->nominal_priority;
}
if (new_priority == current_priority)
return;
Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
current_priority = new_priority;
// Recursively update the priority of the thread that depends on the priority of this one.
if (lock_owner)
lock_owner->UpdatePriority();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/**

View File

@@ -18,7 +18,7 @@
enum ThreadPriority : u32 {
THREADPRIO_HIGHEST = 0, ///< Highest thread priority
THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps
THREADPRIO_DEFAULT = 44, ///< Default thread priority for userland apps
THREADPRIO_LOWEST = 63, ///< Lowest thread priority
};
@@ -43,6 +43,7 @@ enum ThreadStatus {
THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request
THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true
THREADSTATUS_WAIT_MUTEX, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc
THREADSTATUS_DORMANT, ///< Created but not yet made ready
THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
};
@@ -54,7 +55,6 @@ enum class ThreadWakeupReason {
namespace Kernel {
class Mutex;
class Process;
class Thread final : public WaitObject {
@@ -103,18 +103,21 @@ public:
*/
void SetPriority(u32 priority);
/**
* Boost's a thread's priority to the best priority among the thread's held mutexes.
* This prevents priority inversion via priority inheritance.
*/
void UpdatePriority();
/**
* Temporarily boosts the thread's priority until the next time it is scheduled
* @param priority The new priority
*/
void BoostPriority(u32 priority);
/// Adds a thread to the list of threads that are waiting for a lock held by this thread.
void AddMutexWaiter(SharedPtr<Thread> thread);
/// Removes a thread from the list of threads that are waiting for a lock held by this thread.
void RemoveMutexWaiter(SharedPtr<Thread> thread);
/// Recalculates the current priority taking into account priority inheritance.
void UpdatePriority();
/**
* Gets the thread's thread ID
* @return The thread's ID
@@ -205,19 +208,22 @@ public:
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
/// Mutexes currently held by this thread, which will be released when it exits.
boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
/// Mutexes that this thread is currently waiting for.
boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes;
SharedPtr<Process> owner_process; ///< Process that owns this thread
/// Objects that the thread is waiting on, in the same order as they were
// passed to WaitSynchronization1/N.
std::vector<SharedPtr<WaitObject>> wait_objects;
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
/// List of threads that are waiting for a mutex that is held by this thread.
std::vector<SharedPtr<Thread>> wait_mutex_threads;
/// Thread that owns the lock that this thread is waiting for.
SharedPtr<Thread> lock_owner;
// If waiting on a ConditionVariable, this is the ConditionVariable address
VAddr condvar_wait_address;
VAddr mutex_wait_address; ///< If waiting on a Mutex, this is the mutex address
Handle wait_handle; ///< The handle used to wait for the mutex.
std::string name;

View File

@@ -10,8 +10,7 @@
#include "core/hle/service/acc/acc_u0.h"
#include "core/hle/service/acc/acc_u1.h"
namespace Service {
namespace Account {
namespace Service::Account {
// TODO: RE this structure
struct UserData {
@@ -38,7 +37,10 @@ class IProfile final : public ServiceFramework<IProfile> {
public:
IProfile() : ServiceFramework("IProfile") {
static const FunctionInfo functions[] = {
{0, nullptr, "Get"},
{1, &IProfile::GetBase, "GetBase"},
{10, nullptr, "GetImageSize"},
{11, nullptr, "LoadImage"},
};
RegisterHandlers(functions);
}
@@ -59,6 +61,11 @@ public:
static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
{2, nullptr, "EnsureIdTokenCacheAsync"},
{3, nullptr, "LoadIdTokenCache"},
{130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "StoreOpenContext"},
};
RegisterHandlers(functions);
}
@@ -140,5 +147,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<ACC_U1>(module)->InstallAsService(service_manager);
}
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Account {
namespace Service::Account {
class Module final {
public:
@@ -31,5 +30,4 @@ public:
/// Registers all ACC services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/acc/acc_aa.h"
namespace Service {
namespace Account {
namespace Service::Account {
ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:aa") {
static const FunctionInfo functions[] = {
@@ -18,5 +17,4 @@ ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/acc/acc.h"
namespace Service {
namespace Account {
namespace Service::Account {
class ACC_AA final : public Module::Interface {
public:
explicit ACC_AA(std::shared_ptr<Module> module);
};
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/acc/acc_su.h"
namespace Service {
namespace Account {
namespace Service::Account {
ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") {
static const FunctionInfo functions[] = {
@@ -51,5 +50,4 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/acc/acc_u0.h"
namespace Service {
namespace Account {
namespace Service::Account {
ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") {
static const FunctionInfo functions[] = {
@@ -31,5 +30,4 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/acc/acc.h"
namespace Service {
namespace Account {
namespace Service::Account {
class ACC_U0 final : public Module::Interface {
public:
explicit ACC_U0(std::shared_ptr<Module> module);
};
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/acc/acc_u1.h"
namespace Service {
namespace Account {
namespace Service::Account {
ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") {
static const FunctionInfo functions[] = {
@@ -38,5 +37,4 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/acc/acc.h"
namespace Service {
namespace Account {
namespace Service::Account {
class ACC_U1 final : public Module::Interface {
public:
explicit ACC_U1(std::shared_ptr<Module> module);
};
} // namespace Account
} // namespace Service
} // namespace Service::Account

View File

@@ -14,8 +14,7 @@
#include "core/hle/service/nvflinger/nvflinger.h"
#include "core/settings.h"
namespace Service {
namespace AM {
namespace Service::AM {
IWindowController::IWindowController() : ServiceFramework("IWindowController") {
static const FunctionInfo functions[] = {
@@ -571,5 +570,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager,
std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
}
} // namespace AM
} // namespace Service
} // namespace Service::AM

View File

@@ -8,8 +8,7 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/nvflinger/nvflinger.h"
namespace Service {
namespace AM {
namespace Service::AM {
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
public:
@@ -109,5 +108,4 @@ AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
RegisterHandlers(functions);
}
} // namespace AM
} // namespace Service
} // namespace Service::AM

View File

@@ -8,8 +8,7 @@
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/nvflinger/nvflinger.h"
namespace Service {
namespace AM {
namespace Service::AM {
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
public:
@@ -104,5 +103,4 @@ AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
RegisterHandlers(functions);
}
} // namespace AM
} // namespace Service
} // namespace Service::AM

View File

@@ -6,8 +6,7 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/aoc/aoc_u.h"
namespace Service {
namespace AOC {
namespace Service::AOC {
AOC_U::AOC_U() : ServiceFramework("aoc:u") {
static const FunctionInfo functions[] = {
@@ -42,5 +41,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<AOC_U>()->InstallAsService(service_manager);
}
} // namespace AOC
} // namespace Service
} // namespace Service::AOC

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace AOC {
namespace Service::AOC {
class AOC_U final : public ServiceFramework<AOC_U> {
public:
@@ -22,5 +21,4 @@ private:
/// Registers all AOC services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace AOC
} // namespace Service
} // namespace Service::AOC

View File

@@ -7,8 +7,7 @@
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/apm/interface.h"
namespace Service {
namespace APM {
namespace Service::APM {
void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module_ = std::make_shared<Module>();
@@ -16,5 +15,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
}
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace APM {
namespace Service::APM {
enum class PerformanceMode : u8 {
Handheld = 0,
@@ -23,5 +22,4 @@ public:
/// Registers all AM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -7,8 +7,7 @@
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/apm/interface.h"
namespace Service {
namespace APM {
namespace Service::APM {
class ISession final : public ServiceFramework<ISession> {
public:
@@ -62,5 +61,4 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
rb.PushIpcInterface<ISession>();
}
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace APM {
namespace Service::APM {
class APM final : public ServiceFramework<APM> {
public:
@@ -23,5 +22,4 @@ private:
/// Registers all AM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace APM
} // namespace Service
} // namespace Service::APM

View File

@@ -7,8 +7,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audin_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
class IAudioIn final : public ServiceFramework<IAudioIn> {
public:
@@ -44,5 +43,4 @@ AudInU::AudInU() : ServiceFramework("audin:u") {
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class AudInU final : public ServiceFramework<AudInU> {
public:
@@ -19,5 +18,4 @@ public:
~AudInU() = default;
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -9,8 +9,7 @@
#include "core/hle/service/audio/audren_u.h"
#include "core/hle/service/audio/codecctl.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<AudOutU>()->InstallAsService(service_manager);
@@ -20,5 +19,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<CodecCtl>()->InstallAsService(service_manager);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -6,11 +6,9 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
/// Registers all Audio services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audout_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
/// Switch sample rate frequency
constexpr u32 sample_rate{48000};
@@ -204,5 +203,4 @@ AudOutU::AudOutU() : ServiceFramework("audout:u") {
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class IAudioOut;
@@ -37,5 +36,4 @@ private:
};
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -7,8 +7,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audrec_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> {
public:
@@ -36,5 +35,4 @@ AudRecU::AudRecU() : ServiceFramework("audrec:u") {
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class AudRecU final : public ServiceFramework<AudRecU> {
public:
@@ -19,5 +18,4 @@ public:
~AudRecU() = default;
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -9,8 +9,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audren_u.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
/// TODO(bunnei): Find a proper value for the audio_ticks
constexpr u64 audio_ticks{static_cast<u64>(BASE_CLOCK_RATE / 200)};
@@ -272,5 +271,4 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class AudRenU final : public ServiceFramework<AudRenU> {
public:
@@ -24,5 +23,4 @@ private:
void GetAudioDevice(Kernel::HLERequestContext& ctx);
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -7,8 +7,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/codecctl.h"
namespace Service {
namespace Audio {
namespace Service::Audio {
CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
static const FunctionInfo functions[] = {
@@ -29,5 +28,4 @@ CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
RegisterHandlers(functions);
}
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -10,8 +10,7 @@ namespace Kernel {
class HLERequestContext;
}
namespace Service {
namespace Audio {
namespace Service::Audio {
class CodecCtl final : public ServiceFramework<CodecCtl> {
public:
@@ -19,5 +18,4 @@ public:
~CodecCtl() = default;
};
} // namespace Audio
} // namespace Service
} // namespace Service::Audio

View File

@@ -8,8 +8,7 @@
#include "core/hle/service/fatal/fatal_p.h"
#include "core/hle/service/fatal/fatal_u.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
@@ -34,5 +33,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Fatal_U>(module)->InstallAsService(service_manager);
}
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
class Module final {
public:
@@ -25,5 +24,4 @@ public:
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -4,11 +4,9 @@
#include "core/hle/service/fatal/fatal_p.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
Fatal_P::Fatal_P(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "fatal:p") {}
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/fatal/fatal.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
class Fatal_P final : public Module::Interface {
public:
explicit Fatal_P(std::shared_ptr<Module> module);
};
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/fatal/fatal_u.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(m
RegisterHandlers(functions);
}
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/fatal/fatal.h"
namespace Service {
namespace Fatal {
namespace Service::Fatal {
class Fatal_U final : public Module::Interface {
public:
explicit Fatal_U(std::shared_ptr<Module> module);
};
} // namespace Fatal
} // namespace Service
} // namespace Service::Fatal

View File

@@ -10,8 +10,7 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
namespace Service {
namespace FileSystem {
namespace Service::FileSystem {
/**
* Map of registered file systems, identified by type. Once an file system is registered here, it
@@ -75,5 +74,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<FSP_SRV>()->InstallAsService(service_manager);
}
} // namespace FileSystem
} // namespace Service
} // namespace Service::FileSystem

View File

@@ -14,8 +14,7 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
namespace Service {
namespace FileSystem {
namespace Service::FileSystem {
class IStorage final : public ServiceFramework<IStorage> {
public:
@@ -573,5 +572,4 @@ void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
OpenDataStorageByCurrentProcess(ctx);
}
} // namespace FileSystem
} // namespace Service
} // namespace Service::FileSystem

View File

@@ -11,8 +11,7 @@ namespace FileSys {
class FileSystemBackend;
}
namespace Service {
namespace FileSystem {
namespace Service::FileSystem {
class FSP_SRV final : public ServiceFramework<FSP_SRV> {
public:
@@ -33,5 +32,4 @@ private:
std::unique_ptr<FileSys::FileSystemBackend> romfs;
};
} // namespace FileSystem
} // namespace Service
} // namespace Service::FileSystem

View File

@@ -8,8 +8,7 @@
#include "core/hle/service/friend/friend_a.h"
#include "core/hle/service/friend/friend_u.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
@@ -26,5 +25,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Friend_U>(module)->InstallAsService(service_manager);
}
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
class Module final {
public:
@@ -25,5 +24,4 @@ public:
/// Registers all Friend services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/friend/friend_a.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
Friend_A::Friend_A(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "friend:a") {
@@ -16,5 +15,4 @@ Friend_A::Friend_A(std::shared_ptr<Module> module)
RegisterHandlers(functions);
}
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/friend/friend.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
class Friend_A final : public Module::Interface {
public:
explicit Friend_A(std::shared_ptr<Module> module);
};
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/friend/friend_u.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
Friend_U::Friend_U(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "friend:u") {
@@ -16,5 +15,4 @@ Friend_U::Friend_U(std::shared_ptr<Module> module)
RegisterHandlers(functions);
}
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/friend/friend.h"
namespace Service {
namespace Friend {
namespace Service::Friend {
class Friend_U final : public Module::Interface {
public:
explicit Friend_U(std::shared_ptr<Module> module);
};
} // namespace Friend
} // namespace Service
} // namespace Service::Friend

View File

@@ -14,8 +14,7 @@
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/service.h"
namespace Service {
namespace HID {
namespace Service::HID {
// Updating period for each HID device.
// TODO(shinyquagsire23): These need better values.
@@ -434,5 +433,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Hid>()->InstallAsService(service_manager);
}
} // namespace HID
} // namespace Service
} // namespace Service::HID

View File

@@ -7,8 +7,7 @@
#include "core/hle/service/service.h"
#include "core/settings.h"
namespace Service {
namespace HID {
namespace Service::HID {
// Begin enums and output structs
@@ -337,5 +336,4 @@ void ReloadInputDevices();
/// Registers all HID services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace HID
} // namespace Service
} // namespace Service::HID

View File

@@ -9,8 +9,7 @@
#include "core/hle/kernel/client_session.h"
#include "core/hle/service/lm/lm.h"
namespace Service {
namespace LM {
namespace Service::LM {
class Logger final : public ServiceFramework<Logger> {
public:
@@ -189,5 +188,4 @@ LM::LM() : ServiceFramework("lm") {
RegisterHandlers(functions);
}
} // namespace LM
} // namespace Service
} // namespace Service::LM

View File

@@ -8,8 +8,7 @@
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/service.h"
namespace Service {
namespace LM {
namespace Service::LM {
class LM final : public ServiceFramework<LM> {
public:
@@ -23,5 +22,4 @@ private:
/// Registers all LM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace LM
} // namespace Service
} // namespace Service::LM

View File

@@ -7,8 +7,7 @@
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
@@ -24,5 +23,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<NFP_User>(module)->InstallAsService(service_manager);
}
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
class Module final {
public:
@@ -24,5 +23,4 @@ public:
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nfp/nfp_user.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
NFP_User::NFP_User(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "nfp:user") {
@@ -15,5 +14,4 @@ NFP_User::NFP_User(std::shared_ptr<Module> module)
RegisterHandlers(functions);
}
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nfp/nfp.h"
namespace Service {
namespace NFP {
namespace Service::NFP {
class NFP_User final : public Module::Interface {
public:
explicit NFP_User(std::shared_ptr<Module> module);
};
} // namespace NFP
} // namespace Service
} // namespace Service::NFP

View File

@@ -9,8 +9,7 @@
#include "core/hle/service/nifm/nifm_s.h"
#include "core/hle/service/nifm/nifm_u.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class IScanRequest final : public ServiceFramework<IScanRequest> {
public:
@@ -208,5 +207,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<NIFM_U>(module)->InstallAsService(service_manager);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,8 +6,7 @@
#include "core/hle/service/service.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class Module final {
public:
@@ -25,5 +24,4 @@ public:
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nifm/nifm_a.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:a") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nifm/nifm.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class NIFM_A final : public Module::Interface {
public:
explicit NIFM_A(std::shared_ptr<Module> module);
};
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nifm/nifm_s.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:s") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nifm/nifm.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class NIFM_S final : public Module::Interface {
public:
explicit NIFM_S(std::shared_ptr<Module> module);
};
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -4,8 +4,7 @@
#include "core/hle/service/nifm/nifm_u.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:u") {
static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
RegisterHandlers(functions);
}
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -6,13 +6,11 @@
#include "core/hle/service/nifm/nifm.h"
namespace Service {
namespace NIFM {
namespace Service::NIFM {
class NIFM_U final : public Module::Interface {
public:
explicit NIFM_U(std::shared_ptr<Module> module);
};
} // namespace NIFM
} // namespace Service
} // namespace Service::NIFM

View File

@@ -5,12 +5,10 @@
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/pl_u.h"
namespace Service {
namespace NS {
namespace Service::NS {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<PL_U>()->InstallAsService(service_manager);
}
} // namespace NS
} // namespace Service
} // namespace Service::NS

View File

@@ -6,11 +6,9 @@
#include "core/hle/service/service.h"
namespace Service {
namespace NS {
namespace Service::NS {
/// Registers all NS services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace NS
} // namespace Service
} // namespace Service::NS

View File

@@ -8,8 +8,7 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/ns/pl_u.h"
namespace Service {
namespace NS {
namespace Service::NS {
struct FontRegion {
u32 offset;
@@ -117,5 +116,4 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
rb.PushCopyObjects(shared_font_mem);
}
} // namespace NS
} // namespace Service
} // namespace Service::NS

View File

@@ -8,8 +8,7 @@
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/service.h"
namespace Service {
namespace NS {
namespace Service::NS {
class PL_U final : public ServiceFramework<PL_U> {
public:
@@ -30,5 +29,4 @@ private:
std::shared_ptr<std::vector<u8>> shared_font;
};
} // namespace NS
} // namespace Service
} // namespace Service::NS

View File

@@ -9,9 +9,7 @@
#include "common/common_types.h"
#include "common/swap.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
/// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to
/// implement the ioctl interface.
@@ -38,6 +36,4 @@ public:
virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) = 0;
};
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -10,9 +10,7 @@
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
UNIMPLEMENTED();
@@ -35,6 +33,4 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
VideoCore::g_renderer->SwapBuffers(framebuffer);
}
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -10,9 +10,7 @@
#include "core/hle/service/nvdrv/devices/nvdevice.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
class nvmap;
@@ -31,6 +29,4 @@ private:
std::shared_ptr<nvmap> nvmap_dev;
};
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -9,9 +9,7 @@
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -115,6 +113,4 @@ u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& o
return 0;
}
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -11,9 +11,7 @@
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
class nvmap;
@@ -100,6 +98,4 @@ private:
std::shared_ptr<nvmap> nvmap_dev;
};
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -6,9 +6,7 @@
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -59,6 +57,4 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -11,9 +11,7 @@
#include "common/common_types.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
class nvhost_ctrl final : public nvdevice {
public:
@@ -55,6 +53,4 @@ private:
u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -7,9 +7,7 @@
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -122,6 +120,4 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -9,9 +9,7 @@
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
class nvhost_ctrl_gpu final : public nvdevice {
public:
@@ -125,6 +123,5 @@ private:
u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -9,9 +9,7 @@
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -142,6 +140,4 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
return 0;
}
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -10,9 +10,7 @@
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
class nvmap;
constexpr u32 NVGPU_IOCTL_MAGIC('H');
@@ -139,6 +137,4 @@ private:
std::shared_ptr<nvmap> nvmap_dev;
};
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -9,9 +9,7 @@
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
VAddr nvmap::GetObjectAddress(u32 handle) const {
auto object = GetObject(handle);
@@ -144,6 +142,4 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
return 0;
}
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

View File

@@ -12,9 +12,7 @@
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace Devices {
namespace Service::Nvidia::Devices {
class nvmap final : public nvdevice {
public:
@@ -111,6 +109,4 @@ private:
u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Devices
} // namespace Nvidia
} // namespace Service
} // namespace Service::Nvidia::Devices

Some files were not shown because too many files have changed in this diff Show More