diff options
| author | 2017-06-09 00:51:18 -0700 | |
|---|---|---|
| committer | 2017-06-11 13:10:20 -0700 | |
| commit | 21436f5ef7b833fd29871a815aa4e69197f4f730 (patch) | |
| tree | de7e8820682361e30edcb5b7e7e6015a8fa20928 /src/core | |
| parent | IPC: Add basic HLERequestContext support to RequestParser/Builder (diff) | |
| download | yuzu-21436f5ef7b833fd29871a815aa4e69197f4f730.tar.gz yuzu-21436f5ef7b833fd29871a815aa4e69197f4f730.tar.xz yuzu-21436f5ef7b833fd29871a815aa4e69197f4f730.zip | |
IPC: Add Pop/PushObjects methods to RequestParser/Builder
These use the context functions to create and look-up handles for the
user.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/ipc_helpers.h | 113 |
1 files changed, 103 insertions, 10 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index a3abc102e..5f370bc3b 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -4,6 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | #include <tuple> | ||
| 9 | #include <type_traits> | ||
| 10 | #include <utility> | ||
| 7 | #include "core/hle/ipc.h" | 11 | #include "core/hle/ipc.h" |
| 8 | #include "core/hle/kernel/handle_table.h" | 12 | #include "core/hle/kernel/handle_table.h" |
| 9 | #include "core/hle/kernel/hle_ipc.h" | 13 | #include "core/hle/kernel/hle_ipc.h" |
| @@ -105,6 +109,9 @@ public: | |||
| 105 | template <typename... H> | 109 | template <typename... H> |
| 106 | void PushMoveHandles(H... handles); | 110 | void PushMoveHandles(H... handles); |
| 107 | 111 | ||
| 112 | template <typename... O> | ||
| 113 | void PushObjects(Kernel::SharedPtr<O>... pointers); | ||
| 114 | |||
| 108 | void PushCurrentPIDHandle(); | 115 | void PushCurrentPIDHandle(); |
| 109 | 116 | ||
| 110 | void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id); | 117 | void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id); |
| @@ -170,6 +177,11 @@ inline void RequestBuilder::PushMoveHandles(H... handles) { | |||
| 170 | Push(static_cast<Kernel::Handle>(handles)...); | 177 | Push(static_cast<Kernel::Handle>(handles)...); |
| 171 | } | 178 | } |
| 172 | 179 | ||
| 180 | template <typename... O> | ||
| 181 | inline void RequestBuilder::PushObjects(Kernel::SharedPtr<O>... pointers) { | ||
| 182 | PushMoveHandles(context->AddOutgoingHandle(std::move(pointers))...); | ||
| 183 | } | ||
| 184 | |||
| 173 | inline void RequestBuilder::PushCurrentPIDHandle() { | 185 | inline void RequestBuilder::PushCurrentPIDHandle() { |
| 174 | Push(CallingPidDesc()); | 186 | Push(CallingPidDesc()); |
| 175 | Push(u32(0)); | 187 | Push(u32(0)); |
| @@ -229,10 +241,52 @@ public: | |||
| 229 | template <typename First, typename... Other> | 241 | template <typename First, typename... Other> |
| 230 | void Pop(First& first_value, Other&... other_values); | 242 | void Pop(First& first_value, Other&... other_values); |
| 231 | 243 | ||
| 244 | /// Equivalent to calling `PopHandles<1>()[0]`. | ||
| 232 | Kernel::Handle PopHandle(); | 245 | Kernel::Handle PopHandle(); |
| 233 | 246 | ||
| 247 | /** | ||
| 248 | * Pops a descriptor containing `N` handles. The handles are returned as an array. The | ||
| 249 | * descriptor must contain exactly `N` handles, it is not permitted to, for example, call | ||
| 250 | * PopHandles<1>() twice to read a multi-handle descriptor with 2 handles, or to make a single | ||
| 251 | * PopHandles<2>() call to read 2 single-handle descriptors. | ||
| 252 | */ | ||
| 253 | template <unsigned int N> | ||
| 254 | std::array<Kernel::Handle, N> PopHandles(); | ||
| 255 | |||
| 256 | /// Convenience wrapper around PopHandles() which assigns the handles to the passed references. | ||
| 234 | template <typename... H> | 257 | template <typename... H> |
| 235 | void PopHandles(H&... handles); | 258 | void PopHandles(H&... handles) { |
| 259 | std::tie(handles...) = PopHandles<sizeof...(H)>(); | ||
| 260 | } | ||
| 261 | |||
| 262 | /// Equivalent to calling `PopGenericObjects<1>()[0]`. | ||
| 263 | Kernel::SharedPtr<Kernel::Object> PopGenericObject(); | ||
| 264 | |||
| 265 | /// Equivalent to calling `std::get<0>(PopObjects<T>())`. | ||
| 266 | template <typename T> | ||
| 267 | Kernel::SharedPtr<T> PopObject(); | ||
| 268 | |||
| 269 | /** | ||
| 270 | * Pop a descriptor containing `N` handles and resolves them to Kernel::Object pointers. If a | ||
| 271 | * handle is invalid, null is returned for that object instead. The same caveats from | ||
| 272 | * PopHandles() apply regarding `N` matching the number of handles in the descriptor. | ||
| 273 | */ | ||
| 274 | template <unsigned int N> | ||
| 275 | std::array<Kernel::SharedPtr<Kernel::Object>, N> PopGenericObjects(); | ||
| 276 | |||
| 277 | /** | ||
| 278 | * Resolves handles to Kernel::Objects as in PopGenericsObjects(), but then also casts them to | ||
| 279 | * the passed `T` types, while verifying that the cast is valid. If the type of an object does | ||
| 280 | * not match, null is returned instead. | ||
| 281 | */ | ||
| 282 | template <typename... T> | ||
| 283 | std::tuple<Kernel::SharedPtr<T>...> PopObjects(); | ||
| 284 | |||
| 285 | /// Convenience wrapper around PopObjects() which assigns the handles to the passed references. | ||
| 286 | template <typename... T> | ||
| 287 | void PopObjects(Kernel::SharedPtr<T>&... pointers) { | ||
| 288 | std::tie(pointers...) = PopObjects<T...>(); | ||
| 289 | } | ||
| 236 | 290 | ||
| 237 | /** | 291 | /** |
| 238 | * @brief Pops the static buffer vaddr | 292 | * @brief Pops the static buffer vaddr |
| @@ -344,15 +398,54 @@ inline Kernel::Handle RequestParser::PopHandle() { | |||
| 344 | return Pop<Kernel::Handle>(); | 398 | return Pop<Kernel::Handle>(); |
| 345 | } | 399 | } |
| 346 | 400 | ||
| 347 | template <typename... H> | 401 | template <unsigned int N> |
| 348 | void RequestParser::PopHandles(H&... handles) { | 402 | std::array<Kernel::Handle, N> RequestParser::PopHandles() { |
| 349 | const u32 handle_descriptor = Pop<u32>(); | 403 | u32 handle_descriptor = Pop<u32>(); |
| 350 | const int handles_number = sizeof...(H); | 404 | ASSERT_MSG(IsHandleDescriptor(handle_descriptor), |
| 351 | DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor), | 405 | "Tried to pop handle(s) but the descriptor is not a handle descriptor"); |
| 352 | "Tried to pop handle(s) but the descriptor is not a handle descriptor"); | 406 | ASSERT_MSG(N == HandleNumberFromDesc(handle_descriptor), |
| 353 | DEBUG_ASSERT_MSG(handles_number == HandleNumberFromDesc(handle_descriptor), | 407 | "Number of handles doesn't match the descriptor"); |
| 354 | "Number of handles doesn't match the descriptor"); | 408 | |
| 355 | Pop(static_cast<Kernel::Handle&>(handles)...); | 409 | std::array<Kernel::Handle, N> handles{}; |
| 410 | for (Kernel::Handle& handle : handles) { | ||
| 411 | handle = Pop<Kernel::Handle>(); | ||
| 412 | } | ||
| 413 | return handles; | ||
| 414 | } | ||
| 415 | |||
| 416 | inline Kernel::SharedPtr<Kernel::Object> RequestParser::PopGenericObject() { | ||
| 417 | Kernel::Handle handle = PopHandle(); | ||
| 418 | return context->GetIncomingHandle(handle); | ||
| 419 | } | ||
| 420 | |||
| 421 | template <typename T> | ||
| 422 | Kernel::SharedPtr<T> RequestParser::PopObject() { | ||
| 423 | return Kernel::DynamicObjectCast<T>(PopGenericObject()); | ||
| 424 | } | ||
| 425 | |||
| 426 | template <unsigned int N> | ||
| 427 | inline std::array<Kernel::SharedPtr<Kernel::Object>, N> RequestParser::PopGenericObjects() { | ||
| 428 | std::array<Kernel::Handle, N> handles = PopHandles<N>(); | ||
| 429 | std::array<Kernel::SharedPtr<Kernel::Object>, N> pointers; | ||
| 430 | for (int i = 0; i < N; ++i) { | ||
| 431 | pointers[i] = context->GetIncomingHandle(handles[i]); | ||
| 432 | } | ||
| 433 | return pointers; | ||
| 434 | } | ||
| 435 | |||
| 436 | namespace detail { | ||
| 437 | template <typename... T, size_t... I> | ||
| 438 | std::tuple<Kernel::SharedPtr<T>...> PopObjectsHelper( | ||
| 439 | std::array<Kernel::SharedPtr<Kernel::Object>, sizeof...(T)>&& pointers, | ||
| 440 | std::index_sequence<I...>) { | ||
| 441 | return std::make_tuple(Kernel::DynamicObjectCast<T>(std::move(pointers[I]))...); | ||
| 442 | } | ||
| 443 | } // namespace detail | ||
| 444 | |||
| 445 | template <typename... T> | ||
| 446 | inline std::tuple<Kernel::SharedPtr<T>...> RequestParser::PopObjects() { | ||
| 447 | return detail::PopObjectsHelper<T...>(PopGenericObjects<sizeof...(T)>(), | ||
| 448 | std::index_sequence_for<T...>{}); | ||
| 356 | } | 449 | } |
| 357 | 450 | ||
| 358 | inline VAddr RequestParser::PopStaticBuffer(size_t* data_size, bool useStaticBuffersToGetVaddr) { | 451 | inline VAddr RequestParser::PopStaticBuffer(size_t* data_size, bool useStaticBuffersToGetVaddr) { |