Просмотр исходного кода

hle: service: bsd: Update to work with service threads, removing SleepClientThread.

bunnei 5 лет назад
Родитель
Сommit
87d6588cb5

+ 0 - 1
src/core/CMakeLists.txt

@@ -502,7 +502,6 @@ add_library(core STATIC
     hle/service/sm/controller.h
     hle/service/sm/sm.cpp
     hle/service/sm/sm.h
-    hle/service/sockets/blocking_worker.h
     hle/service/sockets/bsd.cpp
     hle/service/sockets/bsd.h
     hle/service/sockets/ethc.cpp

+ 0 - 161
src/core/hle/service/sockets/blocking_worker.h

@@ -1,161 +0,0 @@
-// Copyright 2020 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <atomic>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <thread>
-#include <variant>
-#include <vector>
-
-#include <fmt/format.h>
-
-#include "common/assert.h"
-#include "common/microprofile.h"
-#include "common/thread.h"
-#include "core/core.h"
-#include "core/hle/kernel/hle_ipc.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/thread.h"
-#include "core/hle/kernel/writable_event.h"
-
-namespace Service::Sockets {
-
-/**
- * Worker abstraction to execute blocking calls on host without blocking the guest thread
- *
- * @tparam Service  Service where the work is executed
- * @tparam Types Types of work to execute
- */
-template <class Service, class... Types>
-class BlockingWorker {
-    using This = BlockingWorker<Service, Types...>;
-    using WorkVariant = std::variant<std::monostate, Types...>;
-
-public:
-    /// Create a new worker
-    static std::unique_ptr<This> Create(Core::System& system, Service* service,
-                                        std::string_view name) {
-        return std::unique_ptr<This>(new This(system, service, name));
-    }
-
-    ~BlockingWorker() {
-        while (!is_available.load(std::memory_order_relaxed)) {
-            // Busy wait until work is finished
-            std::this_thread::yield();
-        }
-        // Monostate means to exit the thread
-        work = std::monostate{};
-        work_event.Set();
-        thread.join();
-    }
-
-    /**
-     * Try to capture the worker to send work after a success
-     * @returns True when the worker has been successfully captured
-     */
-    bool TryCapture() {
-        bool expected = true;
-        return is_available.compare_exchange_weak(expected, false, std::memory_order_relaxed,
-                                                  std::memory_order_relaxed);
-    }
-
-    /**
-     * Send work to this worker abstraction
-     * @see TryCapture must be called before attempting to call this function
-     */
-    template <class Work>
-    void SendWork(Work new_work) {
-        ASSERT_MSG(!is_available, "Trying to send work on a worker that's not captured");
-        work = std::move(new_work);
-        work_event.Set();
-    }
-
-    /// Generate a callback for @see SleepClientThread
-    template <class Work>
-    auto Callback() {
-        return [this](std::shared_ptr<Kernel::Thread>, Kernel::HLERequestContext& ctx,
-                      Kernel::ThreadWakeupReason reason) {
-            ASSERT(reason == Kernel::ThreadWakeupReason::Signal);
-            std::get<Work>(work).Response(ctx);
-            is_available.store(true);
-        };
-    }
-
-    /// Get kernel event that will be signalled by the worker when the host operation finishes
-    std::shared_ptr<Kernel::WritableEvent> KernelEvent() const {
-        return kernel_event;
-    }
-
-private:
-    explicit BlockingWorker(Core::System& system, Service* service, std::string_view name) {
-        auto pair = Kernel::WritableEvent::CreateEventPair(system.Kernel(), std::string(name));
-        kernel_event = std::move(pair.writable);
-        thread = std::thread([this, &system, service, name] { Run(system, service, name); });
-    }
-
-    void Run(Core::System& system, Service* service, std::string_view name) {
-        system.RegisterHostThread();
-
-        const std::string thread_name = fmt::format("yuzu:{}", name);
-        MicroProfileOnThreadCreate(thread_name.c_str());
-        Common::SetCurrentThreadName(thread_name.c_str());
-
-        bool keep_running = true;
-        while (keep_running) {
-            work_event.Wait();
-
-            const auto visit_fn = [service, &keep_running]<typename T>(T&& w) {
-                if constexpr (std::is_same_v<std::decay_t<T>, std::monostate>) {
-                    keep_running = false;
-                } else {
-                    w.Execute(service);
-                }
-            };
-            std::visit(visit_fn, work);
-
-            kernel_event->Signal();
-        }
-    }
-
-    std::thread thread;
-    WorkVariant work;
-    Common::Event work_event;
-    std::shared_ptr<Kernel::WritableEvent> kernel_event;
-    std::atomic_bool is_available{true};
-};
-
-template <class Service, class... Types>
-class BlockingWorkerPool {
-    using Worker = BlockingWorker<Service, Types...>;
-
-public:
-    explicit BlockingWorkerPool(Core::System& system_, Service* service_)
-        : system{system_}, service{service_} {}
-
-    /// Returns a captured worker thread, creating new ones if necessary
-    Worker* CaptureWorker() {
-        for (auto& worker : workers) {
-            if (worker->TryCapture()) {
-                return worker.get();
-            }
-        }
-        auto new_worker = Worker::Create(system, service, fmt::format("BSD:{}", workers.size()));
-        [[maybe_unused]] const bool success = new_worker->TryCapture();
-        ASSERT(success);
-
-        return workers.emplace_back(std::move(new_worker)).get();
-    }
-
-private:
-    Core::System& system;
-    Service* const service;
-
-    std::vector<std::unique_ptr<Worker>> workers;
-};
-
-} // namespace Service::Sockets

+ 44 - 80
src/core/hle/service/sockets/bsd.cpp

@@ -178,13 +178,12 @@ void BSD::Poll(Kernel::HLERequestContext& ctx) {
 
     LOG_DEBUG(Service, "called. nfds={} timeout={}", nfds, timeout);
 
-    ExecuteWork(ctx, "BSD:Poll", timeout != 0,
-                PollWork{
-                    .nfds = nfds,
-                    .timeout = timeout,
-                    .read_buffer = ctx.ReadBuffer(),
-                    .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
-                });
+    ExecuteWork(ctx, PollWork{
+                         .nfds = nfds,
+                         .timeout = timeout,
+                         .read_buffer = ctx.ReadBuffer(),
+                         .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
+                     });
 }
 
 void BSD::Accept(Kernel::HLERequestContext& ctx) {
@@ -193,11 +192,10 @@ void BSD::Accept(Kernel::HLERequestContext& ctx) {
 
     LOG_DEBUG(Service, "called. fd={}", fd);
 
-    ExecuteWork(ctx, "BSD:Accept", IsBlockingSocket(fd),
-                AcceptWork{
-                    .fd = fd,
-                    .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
-                });
+    ExecuteWork(ctx, AcceptWork{
+                         .fd = fd,
+                         .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()),
+                     });
 }
 
 void BSD::Bind(Kernel::HLERequestContext& ctx) {
@@ -215,11 +213,10 @@ void BSD::Connect(Kernel::HLERequestContext& ctx) {
 
     LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize());
 
-    ExecuteWork(ctx, "BSD:Connect", IsBlockingSocket(fd),
-                ConnectWork{
-                    .fd = fd,
-                    .addr = ctx.ReadBuffer(),
-                });
+    ExecuteWork(ctx, ConnectWork{
+                         .fd = fd,
+                         .addr = ctx.ReadBuffer(),
+                     });
 }
 
 void BSD::GetPeerName(Kernel::HLERequestContext& ctx) {
@@ -327,12 +324,11 @@ void BSD::Recv(Kernel::HLERequestContext& ctx) {
 
     LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetWriteBufferSize());
 
-    ExecuteWork(ctx, "BSD:Recv", IsBlockingSocket(fd),
-                RecvWork{
-                    .fd = fd,
-                    .flags = flags,
-                    .message = std::vector<u8>(ctx.GetWriteBufferSize()),
-                });
+    ExecuteWork(ctx, RecvWork{
+                         .fd = fd,
+                         .flags = flags,
+                         .message = std::vector<u8>(ctx.GetWriteBufferSize()),
+                     });
 }
 
 void BSD::RecvFrom(Kernel::HLERequestContext& ctx) {
@@ -344,13 +340,12 @@ void BSD::RecvFrom(Kernel::HLERequestContext& ctx) {
     LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={} addrlen={}", fd, flags,
               ctx.GetWriteBufferSize(0), ctx.GetWriteBufferSize(1));
 
-    ExecuteWork(ctx, "BSD:RecvFrom", IsBlockingSocket(fd),
-                RecvFromWork{
-                    .fd = fd,
-                    .flags = flags,
-                    .message = std::vector<u8>(ctx.GetWriteBufferSize(0)),
-                    .addr = std::vector<u8>(ctx.GetWriteBufferSize(1)),
-                });
+    ExecuteWork(ctx, RecvFromWork{
+                         .fd = fd,
+                         .flags = flags,
+                         .message = std::vector<u8>(ctx.GetWriteBufferSize(0)),
+                         .addr = std::vector<u8>(ctx.GetWriteBufferSize(1)),
+                     });
 }
 
 void BSD::Send(Kernel::HLERequestContext& ctx) {
@@ -361,12 +356,11 @@ void BSD::Send(Kernel::HLERequestContext& ctx) {
 
     LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetReadBufferSize());
 
-    ExecuteWork(ctx, "BSD:Send", IsBlockingSocket(fd),
-                SendWork{
-                    .fd = fd,
-                    .flags = flags,
-                    .message = ctx.ReadBuffer(),
-                });
+    ExecuteWork(ctx, SendWork{
+                         .fd = fd,
+                         .flags = flags,
+                         .message = ctx.ReadBuffer(),
+                     });
 }
 
 void BSD::SendTo(Kernel::HLERequestContext& ctx) {
@@ -377,13 +371,12 @@ void BSD::SendTo(Kernel::HLERequestContext& ctx) {
     LOG_DEBUG(Service, "called. fd={} flags=0x{} len={} addrlen={}", fd, flags,
               ctx.GetReadBufferSize(0), ctx.GetReadBufferSize(1));
 
-    ExecuteWork(ctx, "BSD:SendTo", IsBlockingSocket(fd),
-                SendToWork{
-                    .fd = fd,
-                    .flags = flags,
-                    .message = ctx.ReadBuffer(0),
-                    .addr = ctx.ReadBuffer(1),
-                });
+    ExecuteWork(ctx, SendToWork{
+                         .fd = fd,
+                         .flags = flags,
+                         .message = ctx.ReadBuffer(0),
+                         .addr = ctx.ReadBuffer(1),
+                     });
 }
 
 void BSD::Write(Kernel::HLERequestContext& ctx) {
@@ -392,12 +385,11 @@ void BSD::Write(Kernel::HLERequestContext& ctx) {
 
     LOG_DEBUG(Service, "called. fd={} len={}", fd, ctx.GetReadBufferSize());
 
-    ExecuteWork(ctx, "BSD:Write", IsBlockingSocket(fd),
-                SendWork{
-                    .fd = fd,
-                    .flags = 0,
-                    .message = ctx.ReadBuffer(),
-                });
+    ExecuteWork(ctx, SendWork{
+                         .fd = fd,
+                         .flags = 0,
+                         .message = ctx.ReadBuffer(),
+                     });
 }
 
 void BSD::Close(Kernel::HLERequestContext& ctx) {
@@ -410,24 +402,9 @@ void BSD::Close(Kernel::HLERequestContext& ctx) {
 }
 
 template <typename Work>
-void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, std::string_view sleep_reason,
-                      bool is_blocking, Work work) {
-    if (!is_blocking) {
-        work.Execute(this);
-        work.Response(ctx);
-        return;
-    }
-
-    // Signal a dummy response to make IPC validation happy
-    // This will be overwritten by the SleepClientThread callback
+void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, Work work) {
+    work.Execute(this);
     work.Response(ctx);
-
-    auto worker = worker_pool.CaptureWorker();
-
-    ctx.SleepClientThread(std::string(sleep_reason), std::numeric_limits<u64>::max(),
-                          worker->Callback<Work>(), worker->KernelEvent());
-
-    worker->SendWork(std::move(work));
 }
 
 std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protocol) {
@@ -807,18 +784,6 @@ bool BSD::IsFileDescriptorValid(s32 fd) const noexcept {
     return true;
 }
 
-bool BSD::IsBlockingSocket(s32 fd) const noexcept {
-    // Inform invalid sockets as non-blocking
-    // This way we avoid using a worker thread as it will fail without blocking host
-    if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
-        return false;
-    }
-    if (!file_descriptors[fd]) {
-        return false;
-    }
-    return (file_descriptors[fd]->flags & FLAG_O_NONBLOCK) != 0;
-}
-
 void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept {
     IPC::ResponseBuilder rb{ctx, 4};
 
@@ -827,8 +792,7 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co
     rb.PushEnum(bsd_errno);
 }
 
-BSD::BSD(Core::System& system_, const char* name)
-    : ServiceFramework{system_, name}, worker_pool{system_, this} {
+BSD::BSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, &BSD::RegisterClient, "RegisterClient"},

+ 1 - 8
src/core/hle/service/sockets/bsd.h

@@ -11,7 +11,6 @@
 #include "common/common_types.h"
 #include "core/hle/kernel/hle_ipc.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sockets/blocking_worker.h"
 #include "core/hle/service/sockets/sockets.h"
 
 namespace Core {
@@ -138,8 +137,7 @@ private:
     void Close(Kernel::HLERequestContext& ctx);
 
     template <typename Work>
-    void ExecuteWork(Kernel::HLERequestContext& ctx, std::string_view sleep_reason,
-                     bool is_blocking, Work work);
+    void ExecuteWork(Kernel::HLERequestContext& ctx, Work work);
 
     std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol);
     std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer,
@@ -163,15 +161,10 @@ private:
 
     s32 FindFreeFileDescriptorHandle() noexcept;
     bool IsFileDescriptorValid(s32 fd) const noexcept;
-    bool IsBlockingSocket(s32 fd) const noexcept;
 
     void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept;
 
     std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors;
-
-    BlockingWorkerPool<BSD, PollWork, AcceptWork, ConnectWork, RecvWork, RecvFromWork, SendWork,
-                       SendToWork>
-        worker_pool;
 };
 
 class BSDCFG final : public ServiceFramework<BSDCFG> {