diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/core/hle/service/sockets/blocking_worker.h | 161 | ||||
| -rw-r--r-- | src/core/hle/service/sockets/bsd.cpp | 124 | ||||
| -rw-r--r-- | src/core/hle/service/sockets/bsd.h | 9 |
4 files changed, 45 insertions, 250 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 87712a3ce..01f3e9419 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -502,7 +502,6 @@ add_library(core STATIC | |||
| 502 | hle/service/sm/controller.h | 502 | hle/service/sm/controller.h |
| 503 | hle/service/sm/sm.cpp | 503 | hle/service/sm/sm.cpp |
| 504 | hle/service/sm/sm.h | 504 | hle/service/sm/sm.h |
| 505 | hle/service/sockets/blocking_worker.h | ||
| 506 | hle/service/sockets/bsd.cpp | 505 | hle/service/sockets/bsd.cpp |
| 507 | hle/service/sockets/bsd.h | 506 | hle/service/sockets/bsd.h |
| 508 | hle/service/sockets/ethc.cpp | 507 | hle/service/sockets/ethc.cpp |
diff --git a/src/core/hle/service/sockets/blocking_worker.h b/src/core/hle/service/sockets/blocking_worker.h deleted file mode 100644 index 2d53e52b6..000000000 --- a/src/core/hle/service/sockets/blocking_worker.h +++ /dev/null | |||
| @@ -1,161 +0,0 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | #include <memory> | ||
| 9 | #include <string> | ||
| 10 | #include <string_view> | ||
| 11 | #include <thread> | ||
| 12 | #include <variant> | ||
| 13 | #include <vector> | ||
| 14 | |||
| 15 | #include <fmt/format.h> | ||
| 16 | |||
| 17 | #include "common/assert.h" | ||
| 18 | #include "common/microprofile.h" | ||
| 19 | #include "common/thread.h" | ||
| 20 | #include "core/core.h" | ||
| 21 | #include "core/hle/kernel/hle_ipc.h" | ||
| 22 | #include "core/hle/kernel/kernel.h" | ||
| 23 | #include "core/hle/kernel/thread.h" | ||
| 24 | #include "core/hle/kernel/writable_event.h" | ||
| 25 | |||
| 26 | namespace Service::Sockets { | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Worker abstraction to execute blocking calls on host without blocking the guest thread | ||
| 30 | * | ||
| 31 | * @tparam Service Service where the work is executed | ||
| 32 | * @tparam Types Types of work to execute | ||
| 33 | */ | ||
| 34 | template <class Service, class... Types> | ||
| 35 | class BlockingWorker { | ||
| 36 | using This = BlockingWorker<Service, Types...>; | ||
| 37 | using WorkVariant = std::variant<std::monostate, Types...>; | ||
| 38 | |||
| 39 | public: | ||
| 40 | /// Create a new worker | ||
| 41 | static std::unique_ptr<This> Create(Core::System& system, Service* service, | ||
| 42 | std::string_view name) { | ||
| 43 | return std::unique_ptr<This>(new This(system, service, name)); | ||
| 44 | } | ||
| 45 | |||
| 46 | ~BlockingWorker() { | ||
| 47 | while (!is_available.load(std::memory_order_relaxed)) { | ||
| 48 | // Busy wait until work is finished | ||
| 49 | std::this_thread::yield(); | ||
| 50 | } | ||
| 51 | // Monostate means to exit the thread | ||
| 52 | work = std::monostate{}; | ||
| 53 | work_event.Set(); | ||
| 54 | thread.join(); | ||
| 55 | } | ||
| 56 | |||
| 57 | /** | ||
| 58 | * Try to capture the worker to send work after a success | ||
| 59 | * @returns True when the worker has been successfully captured | ||
| 60 | */ | ||
| 61 | bool TryCapture() { | ||
| 62 | bool expected = true; | ||
| 63 | return is_available.compare_exchange_weak(expected, false, std::memory_order_relaxed, | ||
| 64 | std::memory_order_relaxed); | ||
| 65 | } | ||
| 66 | |||
| 67 | /** | ||
| 68 | * Send work to this worker abstraction | ||
| 69 | * @see TryCapture must be called before attempting to call this function | ||
| 70 | */ | ||
| 71 | template <class Work> | ||
| 72 | void SendWork(Work new_work) { | ||
| 73 | ASSERT_MSG(!is_available, "Trying to send work on a worker that's not captured"); | ||
| 74 | work = std::move(new_work); | ||
| 75 | work_event.Set(); | ||
| 76 | } | ||
| 77 | |||
| 78 | /// Generate a callback for @see SleepClientThread | ||
| 79 | template <class Work> | ||
| 80 | auto Callback() { | ||
| 81 | return [this](std::shared_ptr<Kernel::Thread>, Kernel::HLERequestContext& ctx, | ||
| 82 | Kernel::ThreadWakeupReason reason) { | ||
| 83 | ASSERT(reason == Kernel::ThreadWakeupReason::Signal); | ||
| 84 | std::get<Work>(work).Response(ctx); | ||
| 85 | is_available.store(true); | ||
| 86 | }; | ||
| 87 | } | ||
| 88 | |||
| 89 | /// Get kernel event that will be signalled by the worker when the host operation finishes | ||
| 90 | std::shared_ptr<Kernel::WritableEvent> KernelEvent() const { | ||
| 91 | return kernel_event; | ||
| 92 | } | ||
| 93 | |||
| 94 | private: | ||
| 95 | explicit BlockingWorker(Core::System& system, Service* service, std::string_view name) { | ||
| 96 | auto pair = Kernel::WritableEvent::CreateEventPair(system.Kernel(), std::string(name)); | ||
| 97 | kernel_event = std::move(pair.writable); | ||
| 98 | thread = std::thread([this, &system, service, name] { Run(system, service, name); }); | ||
| 99 | } | ||
| 100 | |||
| 101 | void Run(Core::System& system, Service* service, std::string_view name) { | ||
| 102 | system.RegisterHostThread(); | ||
| 103 | |||
| 104 | const std::string thread_name = fmt::format("yuzu:{}", name); | ||
| 105 | MicroProfileOnThreadCreate(thread_name.c_str()); | ||
| 106 | Common::SetCurrentThreadName(thread_name.c_str()); | ||
| 107 | |||
| 108 | bool keep_running = true; | ||
| 109 | while (keep_running) { | ||
| 110 | work_event.Wait(); | ||
| 111 | |||
| 112 | const auto visit_fn = [service, &keep_running]<typename T>(T&& w) { | ||
| 113 | if constexpr (std::is_same_v<std::decay_t<T>, std::monostate>) { | ||
| 114 | keep_running = false; | ||
| 115 | } else { | ||
| 116 | w.Execute(service); | ||
| 117 | } | ||
| 118 | }; | ||
| 119 | std::visit(visit_fn, work); | ||
| 120 | |||
| 121 | kernel_event->Signal(); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | std::thread thread; | ||
| 126 | WorkVariant work; | ||
| 127 | Common::Event work_event; | ||
| 128 | std::shared_ptr<Kernel::WritableEvent> kernel_event; | ||
| 129 | std::atomic_bool is_available{true}; | ||
| 130 | }; | ||
| 131 | |||
| 132 | template <class Service, class... Types> | ||
| 133 | class BlockingWorkerPool { | ||
| 134 | using Worker = BlockingWorker<Service, Types...>; | ||
| 135 | |||
| 136 | public: | ||
| 137 | explicit BlockingWorkerPool(Core::System& system_, Service* service_) | ||
| 138 | : system{system_}, service{service_} {} | ||
| 139 | |||
| 140 | /// Returns a captured worker thread, creating new ones if necessary | ||
| 141 | Worker* CaptureWorker() { | ||
| 142 | for (auto& worker : workers) { | ||
| 143 | if (worker->TryCapture()) { | ||
| 144 | return worker.get(); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | auto new_worker = Worker::Create(system, service, fmt::format("BSD:{}", workers.size())); | ||
| 148 | [[maybe_unused]] const bool success = new_worker->TryCapture(); | ||
| 149 | ASSERT(success); | ||
| 150 | |||
| 151 | return workers.emplace_back(std::move(new_worker)).get(); | ||
| 152 | } | ||
| 153 | |||
| 154 | private: | ||
| 155 | Core::System& system; | ||
| 156 | Service* const service; | ||
| 157 | |||
| 158 | std::vector<std::unique_ptr<Worker>> workers; | ||
| 159 | }; | ||
| 160 | |||
| 161 | } // namespace Service::Sockets | ||
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 67b419503..2b824059d 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp | |||
| @@ -178,13 +178,12 @@ void BSD::Poll(Kernel::HLERequestContext& ctx) { | |||
| 178 | 178 | ||
| 179 | LOG_DEBUG(Service, "called. nfds={} timeout={}", nfds, timeout); | 179 | LOG_DEBUG(Service, "called. nfds={} timeout={}", nfds, timeout); |
| 180 | 180 | ||
| 181 | ExecuteWork(ctx, "BSD:Poll", timeout != 0, | 181 | ExecuteWork(ctx, PollWork{ |
| 182 | PollWork{ | 182 | .nfds = nfds, |
| 183 | .nfds = nfds, | 183 | .timeout = timeout, |
| 184 | .timeout = timeout, | 184 | .read_buffer = ctx.ReadBuffer(), |
| 185 | .read_buffer = ctx.ReadBuffer(), | 185 | .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()), |
| 186 | .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()), | 186 | }); |
| 187 | }); | ||
| 188 | } | 187 | } |
| 189 | 188 | ||
| 190 | void BSD::Accept(Kernel::HLERequestContext& ctx) { | 189 | void BSD::Accept(Kernel::HLERequestContext& ctx) { |
| @@ -193,11 +192,10 @@ void BSD::Accept(Kernel::HLERequestContext& ctx) { | |||
| 193 | 192 | ||
| 194 | LOG_DEBUG(Service, "called. fd={}", fd); | 193 | LOG_DEBUG(Service, "called. fd={}", fd); |
| 195 | 194 | ||
| 196 | ExecuteWork(ctx, "BSD:Accept", IsBlockingSocket(fd), | 195 | ExecuteWork(ctx, AcceptWork{ |
| 197 | AcceptWork{ | 196 | .fd = fd, |
| 198 | .fd = fd, | 197 | .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()), |
| 199 | .write_buffer = std::vector<u8>(ctx.GetWriteBufferSize()), | 198 | }); |
| 200 | }); | ||
| 201 | } | 199 | } |
| 202 | 200 | ||
| 203 | void BSD::Bind(Kernel::HLERequestContext& ctx) { | 201 | void BSD::Bind(Kernel::HLERequestContext& ctx) { |
| @@ -215,11 +213,10 @@ void BSD::Connect(Kernel::HLERequestContext& ctx) { | |||
| 215 | 213 | ||
| 216 | LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize()); | 214 | LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize()); |
| 217 | 215 | ||
| 218 | ExecuteWork(ctx, "BSD:Connect", IsBlockingSocket(fd), | 216 | ExecuteWork(ctx, ConnectWork{ |
| 219 | ConnectWork{ | 217 | .fd = fd, |
| 220 | .fd = fd, | 218 | .addr = ctx.ReadBuffer(), |
| 221 | .addr = ctx.ReadBuffer(), | 219 | }); |
| 222 | }); | ||
| 223 | } | 220 | } |
| 224 | 221 | ||
| 225 | void BSD::GetPeerName(Kernel::HLERequestContext& ctx) { | 222 | void BSD::GetPeerName(Kernel::HLERequestContext& ctx) { |
| @@ -327,12 +324,11 @@ void BSD::Recv(Kernel::HLERequestContext& ctx) { | |||
| 327 | 324 | ||
| 328 | LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetWriteBufferSize()); | 325 | LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetWriteBufferSize()); |
| 329 | 326 | ||
| 330 | ExecuteWork(ctx, "BSD:Recv", IsBlockingSocket(fd), | 327 | ExecuteWork(ctx, RecvWork{ |
| 331 | RecvWork{ | 328 | .fd = fd, |
| 332 | .fd = fd, | 329 | .flags = flags, |
| 333 | .flags = flags, | 330 | .message = std::vector<u8>(ctx.GetWriteBufferSize()), |
| 334 | .message = std::vector<u8>(ctx.GetWriteBufferSize()), | 331 | }); |
| 335 | }); | ||
| 336 | } | 332 | } |
| 337 | 333 | ||
| 338 | void BSD::RecvFrom(Kernel::HLERequestContext& ctx) { | 334 | void BSD::RecvFrom(Kernel::HLERequestContext& ctx) { |
| @@ -344,13 +340,12 @@ void BSD::RecvFrom(Kernel::HLERequestContext& ctx) { | |||
| 344 | LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={} addrlen={}", fd, flags, | 340 | LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={} addrlen={}", fd, flags, |
| 345 | ctx.GetWriteBufferSize(0), ctx.GetWriteBufferSize(1)); | 341 | ctx.GetWriteBufferSize(0), ctx.GetWriteBufferSize(1)); |
| 346 | 342 | ||
| 347 | ExecuteWork(ctx, "BSD:RecvFrom", IsBlockingSocket(fd), | 343 | ExecuteWork(ctx, RecvFromWork{ |
| 348 | RecvFromWork{ | 344 | .fd = fd, |
| 349 | .fd = fd, | 345 | .flags = flags, |
| 350 | .flags = flags, | 346 | .message = std::vector<u8>(ctx.GetWriteBufferSize(0)), |
| 351 | .message = std::vector<u8>(ctx.GetWriteBufferSize(0)), | 347 | .addr = std::vector<u8>(ctx.GetWriteBufferSize(1)), |
| 352 | .addr = std::vector<u8>(ctx.GetWriteBufferSize(1)), | 348 | }); |
| 353 | }); | ||
| 354 | } | 349 | } |
| 355 | 350 | ||
| 356 | void BSD::Send(Kernel::HLERequestContext& ctx) { | 351 | void BSD::Send(Kernel::HLERequestContext& ctx) { |
| @@ -361,12 +356,11 @@ void BSD::Send(Kernel::HLERequestContext& ctx) { | |||
| 361 | 356 | ||
| 362 | LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetReadBufferSize()); | 357 | LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetReadBufferSize()); |
| 363 | 358 | ||
| 364 | ExecuteWork(ctx, "BSD:Send", IsBlockingSocket(fd), | 359 | ExecuteWork(ctx, SendWork{ |
| 365 | SendWork{ | 360 | .fd = fd, |
| 366 | .fd = fd, | 361 | .flags = flags, |
| 367 | .flags = flags, | 362 | .message = ctx.ReadBuffer(), |
| 368 | .message = ctx.ReadBuffer(), | 363 | }); |
| 369 | }); | ||
| 370 | } | 364 | } |
| 371 | 365 | ||
| 372 | void BSD::SendTo(Kernel::HLERequestContext& ctx) { | 366 | void BSD::SendTo(Kernel::HLERequestContext& ctx) { |
| @@ -377,13 +371,12 @@ void BSD::SendTo(Kernel::HLERequestContext& ctx) { | |||
| 377 | LOG_DEBUG(Service, "called. fd={} flags=0x{} len={} addrlen={}", fd, flags, | 371 | LOG_DEBUG(Service, "called. fd={} flags=0x{} len={} addrlen={}", fd, flags, |
| 378 | ctx.GetReadBufferSize(0), ctx.GetReadBufferSize(1)); | 372 | ctx.GetReadBufferSize(0), ctx.GetReadBufferSize(1)); |
| 379 | 373 | ||
| 380 | ExecuteWork(ctx, "BSD:SendTo", IsBlockingSocket(fd), | 374 | ExecuteWork(ctx, SendToWork{ |
| 381 | SendToWork{ | 375 | .fd = fd, |
| 382 | .fd = fd, | 376 | .flags = flags, |
| 383 | .flags = flags, | 377 | .message = ctx.ReadBuffer(0), |
| 384 | .message = ctx.ReadBuffer(0), | 378 | .addr = ctx.ReadBuffer(1), |
| 385 | .addr = ctx.ReadBuffer(1), | 379 | }); |
| 386 | }); | ||
| 387 | } | 380 | } |
| 388 | 381 | ||
| 389 | void BSD::Write(Kernel::HLERequestContext& ctx) { | 382 | void BSD::Write(Kernel::HLERequestContext& ctx) { |
| @@ -392,12 +385,11 @@ void BSD::Write(Kernel::HLERequestContext& ctx) { | |||
| 392 | 385 | ||
| 393 | LOG_DEBUG(Service, "called. fd={} len={}", fd, ctx.GetReadBufferSize()); | 386 | LOG_DEBUG(Service, "called. fd={} len={}", fd, ctx.GetReadBufferSize()); |
| 394 | 387 | ||
| 395 | ExecuteWork(ctx, "BSD:Write", IsBlockingSocket(fd), | 388 | ExecuteWork(ctx, SendWork{ |
| 396 | SendWork{ | 389 | .fd = fd, |
| 397 | .fd = fd, | 390 | .flags = 0, |
| 398 | .flags = 0, | 391 | .message = ctx.ReadBuffer(), |
| 399 | .message = ctx.ReadBuffer(), | 392 | }); |
| 400 | }); | ||
| 401 | } | 393 | } |
| 402 | 394 | ||
| 403 | void BSD::Close(Kernel::HLERequestContext& ctx) { | 395 | void BSD::Close(Kernel::HLERequestContext& ctx) { |
| @@ -410,24 +402,9 @@ void BSD::Close(Kernel::HLERequestContext& ctx) { | |||
| 410 | } | 402 | } |
| 411 | 403 | ||
| 412 | template <typename Work> | 404 | template <typename Work> |
| 413 | void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, std::string_view sleep_reason, | 405 | void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, Work work) { |
| 414 | bool is_blocking, Work work) { | 406 | work.Execute(this); |
| 415 | if (!is_blocking) { | ||
| 416 | work.Execute(this); | ||
| 417 | work.Response(ctx); | ||
| 418 | return; | ||
| 419 | } | ||
| 420 | |||
| 421 | // Signal a dummy response to make IPC validation happy | ||
| 422 | // This will be overwritten by the SleepClientThread callback | ||
| 423 | work.Response(ctx); | 407 | work.Response(ctx); |
| 424 | |||
| 425 | auto worker = worker_pool.CaptureWorker(); | ||
| 426 | |||
| 427 | ctx.SleepClientThread(std::string(sleep_reason), std::numeric_limits<u64>::max(), | ||
| 428 | worker->Callback<Work>(), worker->KernelEvent()); | ||
| 429 | |||
| 430 | worker->SendWork(std::move(work)); | ||
| 431 | } | 408 | } |
| 432 | 409 | ||
| 433 | std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protocol) { | 410 | std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protocol) { |
| @@ -807,18 +784,6 @@ bool BSD::IsFileDescriptorValid(s32 fd) const noexcept { | |||
| 807 | return true; | 784 | return true; |
| 808 | } | 785 | } |
| 809 | 786 | ||
| 810 | bool BSD::IsBlockingSocket(s32 fd) const noexcept { | ||
| 811 | // Inform invalid sockets as non-blocking | ||
| 812 | // This way we avoid using a worker thread as it will fail without blocking host | ||
| 813 | if (fd > static_cast<s32>(MAX_FD) || fd < 0) { | ||
| 814 | return false; | ||
| 815 | } | ||
| 816 | if (!file_descriptors[fd]) { | ||
| 817 | return false; | ||
| 818 | } | ||
| 819 | return (file_descriptors[fd]->flags & FLAG_O_NONBLOCK) != 0; | ||
| 820 | } | ||
| 821 | |||
| 822 | void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept { | 787 | void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept { |
| 823 | IPC::ResponseBuilder rb{ctx, 4}; | 788 | IPC::ResponseBuilder rb{ctx, 4}; |
| 824 | 789 | ||
| @@ -827,8 +792,7 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co | |||
| 827 | rb.PushEnum(bsd_errno); | 792 | rb.PushEnum(bsd_errno); |
| 828 | } | 793 | } |
| 829 | 794 | ||
| 830 | BSD::BSD(Core::System& system_, const char* name) | 795 | BSD::BSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { |
| 831 | : ServiceFramework{system_, name}, worker_pool{system_, this} { | ||
| 832 | // clang-format off | 796 | // clang-format off |
| 833 | static const FunctionInfo functions[] = { | 797 | static const FunctionInfo functions[] = { |
| 834 | {0, &BSD::RegisterClient, "RegisterClient"}, | 798 | {0, &BSD::RegisterClient, "RegisterClient"}, |
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index f14713fc4..6da0bfeb2 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "core/hle/kernel/hle_ipc.h" | 12 | #include "core/hle/kernel/hle_ipc.h" |
| 13 | #include "core/hle/service/service.h" | 13 | #include "core/hle/service/service.h" |
| 14 | #include "core/hle/service/sockets/blocking_worker.h" | ||
| 15 | #include "core/hle/service/sockets/sockets.h" | 14 | #include "core/hle/service/sockets/sockets.h" |
| 16 | 15 | ||
| 17 | namespace Core { | 16 | namespace Core { |
| @@ -138,8 +137,7 @@ private: | |||
| 138 | void Close(Kernel::HLERequestContext& ctx); | 137 | void Close(Kernel::HLERequestContext& ctx); |
| 139 | 138 | ||
| 140 | template <typename Work> | 139 | template <typename Work> |
| 141 | void ExecuteWork(Kernel::HLERequestContext& ctx, std::string_view sleep_reason, | 140 | void ExecuteWork(Kernel::HLERequestContext& ctx, Work work); |
| 142 | bool is_blocking, Work work); | ||
| 143 | 141 | ||
| 144 | std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol); | 142 | std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol); |
| 145 | std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, | 143 | std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, |
| @@ -163,15 +161,10 @@ private: | |||
| 163 | 161 | ||
| 164 | s32 FindFreeFileDescriptorHandle() noexcept; | 162 | s32 FindFreeFileDescriptorHandle() noexcept; |
| 165 | bool IsFileDescriptorValid(s32 fd) const noexcept; | 163 | bool IsFileDescriptorValid(s32 fd) const noexcept; |
| 166 | bool IsBlockingSocket(s32 fd) const noexcept; | ||
| 167 | 164 | ||
| 168 | void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept; | 165 | void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept; |
| 169 | 166 | ||
| 170 | std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors; | 167 | std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors; |
| 171 | |||
| 172 | BlockingWorkerPool<BSD, PollWork, AcceptWork, ConnectWork, RecvWork, RecvFromWork, SendWork, | ||
| 173 | SendToWork> | ||
| 174 | worker_pool; | ||
| 175 | }; | 168 | }; |
| 176 | 169 | ||
| 177 | class BSDCFG final : public ServiceFramework<BSDCFG> { | 170 | class BSDCFG final : public ServiceFramework<BSDCFG> { |