| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "zircon_platform_connection.h" |
| |
| #include <optional> |
| |
| #include "magma_common_defs.h" |
| #include "zircon_platform_status.h" |
| |
| namespace { |
| std::optional<magma::PlatformObject::Type> GetObjectType(fuchsia_gpu_magma::ObjectType fidl_type) { |
| switch (fidl_type) { |
| case fuchsia_gpu_magma::ObjectType::kBuffer: |
| return magma::PlatformObject::Type::BUFFER; |
| case fuchsia_gpu_magma::ObjectType::kEvent: |
| return magma::PlatformObject::Type::SEMAPHORE; |
| default: |
| return std::nullopt; |
| } |
| } |
| |
| std::optional<int> GetBufferOp(fuchsia_gpu_magma::BufferOp fidl_type) { |
| switch (fidl_type) { |
| case fuchsia_gpu_magma::wire::BufferOp::kPopulateTables: |
| return MAGMA_BUFFER_RANGE_OP_POPULATE_TABLES; |
| case fuchsia_gpu_magma::wire::BufferOp::kDepopulateTables: |
| return MAGMA_BUFFER_RANGE_OP_DEPOPULATE_TABLES; |
| default: |
| return std::nullopt; |
| } |
| } |
| |
| } // namespace |
| |
| namespace magma { |
| |
| class ZirconPlatformPerfCountPool : public PlatformPerfCountPool { |
| public: |
| ZirconPlatformPerfCountPool(uint64_t id, zx::channel channel) |
| : pool_id_(id), server_end_(std::move(channel)) {} |
| |
| uint64_t pool_id() override { return pool_id_; } |
| |
| // Sends a OnPerformanceCounterReadCompleted. May be called from any thread. |
| magma::Status SendPerformanceCounterCompletion(uint32_t trigger_id, uint64_t buffer_id, |
| uint32_t buffer_offset, uint64_t time, |
| uint32_t result_flags) override { |
| fidl::Arena allocator; |
| auto builder = fuchsia_gpu_magma::wire:: |
| PerformanceCounterEventsOnPerformanceCounterReadCompletedRequest::Builder(allocator); |
| builder.trigger_id(trigger_id) |
| .buffer_id(buffer_id) |
| .buffer_offset(buffer_offset) |
| .timestamp(time) |
| .flags(fuchsia_gpu_magma::wire::ResultFlags::TruncatingUnknown(result_flags)); |
| |
| fidl::Status result = |
| fidl::WireSendEvent(server_end_)->OnPerformanceCounterReadCompleted(builder.Build()); |
| switch (result.status()) { |
| case ZX_OK: |
| return MAGMA_STATUS_OK; |
| case ZX_ERR_PEER_CLOSED: |
| return MAGMA_STATUS_CONNECTION_LOST; |
| case ZX_ERR_TIMED_OUT: |
| return MAGMA_STATUS_TIMED_OUT; |
| default: |
| return MAGMA_STATUS_INTERNAL_ERROR; |
| } |
| } |
| |
| private: |
| uint64_t pool_id_; |
| fidl::ServerEnd<fuchsia_gpu_magma::PerformanceCounterEvents> server_end_; |
| }; |
| |
| void ZirconPlatformConnection::SetError(fidl::CompleterBase* completer, magma_status_t error) { |
| if (!error_) { |
| error_ = DRET_MSG(error, "ZirconPlatformConnection encountered dispatcher error"); |
| if (completer) { |
| completer->Close(magma::ToZxStatus(error)); |
| } else { |
| server_binding_->Close(magma::ToZxStatus(error)); |
| } |
| async_loop()->Quit(); |
| } |
| } |
| |
| bool ZirconPlatformConnection::Bind(zx::channel server_endpoint) { |
| fidl::OnUnboundFn<ZirconPlatformConnection> unbind_callback = |
| [](ZirconPlatformConnection* self, fidl::UnbindInfo unbind_info, |
| fidl::ServerEnd<fuchsia_gpu_magma::Primary> server_channel) { |
| // |kDispatcherError| indicates the async loop itself is shutting down, |
| // which could only happen when |interface| is being destructed. |
| // Therefore, we must avoid using the same object. |
| if (unbind_info.reason() == fidl::Reason::kDispatcherError) |
| return; |
| |
| self->server_binding_ = cpp17::nullopt; |
| self->async_loop()->Quit(); |
| }; |
| |
| // Note: the async loop should not be started until we assign |server_binding_|. |
| server_binding_ = |
| fidl::BindServer(async_loop()->dispatcher(), |
| fidl::ServerEnd<fuchsia_gpu_magma::Primary>(std::move(server_endpoint)), |
| this, std::move(unbind_callback)); |
| return true; |
| } |
| |
| bool ZirconPlatformConnection::HandleRequest() { |
| zx_status_t status = async_loop_.Run(zx::time::infinite(), true /* once */); |
| if (status != ZX_OK) |
| return false; |
| return true; |
| } |
| |
| bool ZirconPlatformConnection::BeginShutdownWait() { |
| zx_status_t status = async_begin_wait(async_loop()->dispatcher(), &async_wait_shutdown_); |
| if (status != ZX_OK) |
| return DRETF(false, "Couldn't begin wait on shutdown: %s", zx_status_get_string(status)); |
| return true; |
| } |
| |
| void ZirconPlatformConnection::AsyncWaitHandler(async_dispatcher_t* dispatcher, AsyncWait* wait, |
| zx_status_t status, |
| const zx_packet_signal_t* signal) { |
| if (status != ZX_OK) |
| return; |
| |
| bool quit = false; |
| if (wait == &async_wait_shutdown_) { |
| DASSERT(signal->observed == ZX_EVENT_SIGNALED); |
| quit = true; |
| DLOG("got shutdown event"); |
| } else { |
| DASSERT(false); |
| } |
| |
| if (quit) { |
| server_binding_->Close(ZX_ERR_CANCELED); |
| async_loop()->Quit(); |
| } |
| } |
| |
| struct AsyncHandleWait : public async_wait { |
| AsyncHandleWait(msd_connection_handle_wait_complete_t completer, void* completer_context, |
| zx_handle_t object) { |
| this->state = ASYNC_STATE_INIT; |
| this->handler = Handler; |
| this->object = object; |
| this->trigger = ZX_EVENT_SIGNALED; |
| this->options = 0; |
| this->completer = completer; |
| this->completer_context = completer_context; |
| } |
| |
| static void Handler(async_dispatcher_t* dispatcher, async_wait_t* async_wait, zx_status_t status, |
| const zx_packet_signal_t* signal) { |
| auto wait = static_cast<AsyncHandleWait*>(async_wait); |
| |
| wait->completer(wait->completer_context, magma::FromZxStatus(status).get(), wait->object); |
| |
| delete wait; |
| } |
| |
| msd_connection_handle_wait_complete_t completer; |
| void* completer_context; |
| }; |
| |
| bool ZirconPlatformConnection::AsyncTaskHandler(async_dispatcher_t* dispatcher, AsyncTask* task, |
| zx_status_t status) { |
| switch (static_cast<MSD_CONNECTION_NOTIFICATION_TYPE>(task->notification.type)) { |
| case MSD_CONNECTION_NOTIFICATION_CHANNEL_SEND: { |
| zx_status_t status = zx_channel_write(server_notification_endpoint_.get(), 0, |
| task->notification.u.channel_send.data, |
| task->notification.u.channel_send.size, nullptr, 0); |
| if (status != ZX_OK) |
| return DRETF(false, "Failed writing to channel: %s", zx_status_get_string(status)); |
| return true; |
| } |
| |
| case MSD_CONNECTION_NOTIFICATION_CONTEXT_KILLED: |
| // Setting the error will close the connection. |
| SetError(nullptr, MAGMA_STATUS_CONTEXT_KILLED); |
| return true; |
| |
| case MSD_CONNECTION_NOTIFICATION_PERFORMANCE_COUNTERS_READ_COMPLETED: |
| // Should be handled in MagmaSystemConnection. |
| break; |
| |
| case MSD_CONNECTION_NOTIFICATION_HANDLE_WAIT: { |
| DASSERT(task->notification.u.handle_wait.handle != ZX_HANDLE_INVALID); |
| |
| auto wait_ptr = std::make_unique<AsyncHandleWait>( |
| task->notification.u.handle_wait.completer, task->notification.u.handle_wait.wait_context, |
| task->notification.u.handle_wait.handle); |
| |
| zx_status_t status = async_begin_wait(async_loop()->dispatcher(), wait_ptr.get()); |
| if (status != ZX_OK) |
| return DRETF(false, "async_begin_wait failed: %s", zx_status_get_string(status)); |
| |
| task->notification.u.handle_wait.starter(task->notification.u.handle_wait.wait_context, |
| wait_ptr.release()); |
| return true; |
| } |
| |
| case MSD_CONNECTION_NOTIFICATION_HANDLE_WAIT_CANCEL: { |
| auto wait_ptr = |
| reinterpret_cast<AsyncHandleWait*>(task->notification.u.handle_wait_cancel.cancel_token); |
| DASSERT(wait_ptr); |
| |
| zx_status_t status = async_cancel_wait(async_loop()->dispatcher(), wait_ptr); |
| if (status != ZX_OK) |
| return DRETF(false, "async_cancel_wait failed: %s", zx_status_get_string(status)); |
| |
| // Call back to ensure cleanup |
| AsyncHandleWait::Handler(async_loop()->dispatcher(), wait_ptr, ZX_ERR_CANCELED, nullptr); |
| return true; |
| } |
| } |
| return DRETF(false, "Unhandled notification type: %lu", task->notification.type); |
| } |
| |
| void ZirconPlatformConnection::EnableFlowControl(EnableFlowControlRequestView request, |
| EnableFlowControlCompleter::Sync& completer) { |
| flow_control_enabled_ = true; |
| } |
| |
| void ZirconPlatformConnection::FlowControl(uint64_t size) { |
| if (!flow_control_enabled_) |
| return; |
| |
| messages_consumed_ += 1; |
| bytes_imported_ += size; |
| |
| if (messages_consumed_ >= kMaxInflightMessages / 2) { |
| fidl::Status result = |
| fidl::WireSendEvent(server_binding_.value())->OnNotifyMessagesConsumed(messages_consumed_); |
| if (result.ok()) { |
| messages_consumed_ = 0; |
| } else if (!result.is_canceled() && !result.is_peer_closed()) { |
| DMESSAGE("SendOnNotifyMessagesConsumedEvent failed: %s", result.FormatDescription().c_str()); |
| } |
| } |
| |
| if (bytes_imported_ >= kMaxInflightBytes / 2) { |
| fidl::Status result = |
| fidl::WireSendEvent(server_binding_.value())->OnNotifyMemoryImported(bytes_imported_); |
| if (result.ok()) { |
| bytes_imported_ = 0; |
| } else if (!result.is_canceled() && !result.is_peer_closed()) { |
| DMESSAGE("SendOnNotifyMemoryImportedEvent failed: %s", result.FormatDescription().c_str()); |
| } |
| } |
| } |
| |
| void ZirconPlatformConnection::ImportObject(ImportObjectRequestView request, |
| ImportObjectCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: ImportObject"); |
| |
| auto object_type = GetObjectType(request->object_type); |
| if (!object_type) { |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| return; |
| } |
| |
| uint64_t size = 0; |
| |
| if (object_type == magma::PlatformObject::BUFFER) { |
| zx::unowned_vmo vmo(request->object.get()); |
| zx_status_t status = vmo->get_size(&size); |
| if (status != ZX_OK) { |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| return; |
| } |
| } |
| |
| uint64_t id; |
| if (!magma::PlatformObject::IdFromHandle(request->object.get(), &id)) { |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| return; |
| } |
| |
| FlowControl(size); |
| |
| if (!delegate_->ImportObject(request->object.release(), *object_type, id)) |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| } |
| |
| void ZirconPlatformConnection::ImportObject2(ImportObject2RequestView request, |
| ImportObject2Completer::Sync& completer) { |
| DLOG("ZirconPlatformConnection: ImportObject2"); |
| |
| auto object_type = GetObjectType(request->object_type); |
| if (!object_type) { |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| return; |
| } |
| |
| uint64_t size = 0; |
| |
| if (object_type == magma::PlatformObject::BUFFER) { |
| zx::unowned_vmo vmo(request->object.get()); |
| zx_status_t status = vmo->get_size(&size); |
| if (status != ZX_OK) { |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| return; |
| } |
| } |
| FlowControl(size); |
| |
| if (!delegate_->ImportObject(request->object.release(), *object_type, request->object_id)) |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| } |
| |
| void ZirconPlatformConnection::ReleaseObject(ReleaseObjectRequestView request, |
| ReleaseObjectCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: ReleaseObject"); |
| FlowControl(); |
| |
| auto object_type = GetObjectType(request->object_type); |
| if (!object_type) { |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| return; |
| } |
| |
| if (!delegate_->ReleaseObject(request->object_id, *object_type)) |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| } |
| |
| void ZirconPlatformConnection::CreateContext(CreateContextRequestView request, |
| CreateContextCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: CreateContext"); |
| FlowControl(); |
| |
| magma::Status status = delegate_->CreateContext(request->context_id); |
| if (!status.ok()) |
| SetError(&completer, status.get()); |
| } |
| |
| void ZirconPlatformConnection::DestroyContext(DestroyContextRequestView request, |
| DestroyContextCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: DestroyContext"); |
| FlowControl(); |
| |
| magma::Status status = delegate_->DestroyContext(request->context_id); |
| if (!status.ok()) |
| SetError(&completer, status.get()); |
| } |
| |
| // DEPRECATED - TODO(fxb/86670) remove |
| void ZirconPlatformConnection::ExecuteCommandBufferWithResources2( |
| ExecuteCommandBufferWithResources2RequestView request, |
| ExecuteCommandBufferWithResources2Completer::Sync& completer) { |
| FlowControl(); |
| |
| auto command_buffer = std::make_unique<magma_command_buffer>(); |
| |
| *command_buffer = { |
| .resource_count = static_cast<uint32_t>(request->resources.count()), |
| .batch_buffer_resource_index = request->command_buffer.resource_index, |
| .batch_start_offset = request->command_buffer.start_offset, |
| .wait_semaphore_count = static_cast<uint32_t>(request->wait_semaphores.count()), |
| .signal_semaphore_count = static_cast<uint32_t>(request->signal_semaphores.count()), |
| .flags = static_cast<uint64_t>(request->command_buffer.flags), |
| }; |
| |
| std::vector<magma_exec_resource> resources; |
| resources.reserve(request->resources.count()); |
| |
| for (auto& buffer_range : request->resources) { |
| resources.push_back({ |
| buffer_range.buffer_id, |
| buffer_range.offset, |
| buffer_range.size, |
| }); |
| } |
| |
| // Merge semaphores into one vector |
| std::vector<uint64_t> semaphores; |
| semaphores.reserve(request->wait_semaphores.count() + request->signal_semaphores.count()); |
| |
| for (uint64_t semaphore_id : request->wait_semaphores) { |
| semaphores.push_back(semaphore_id); |
| } |
| for (uint64_t semaphore_id : request->signal_semaphores) { |
| semaphores.push_back(semaphore_id); |
| } |
| |
| magma::Status status = delegate_->ExecuteCommandBufferWithResources( |
| request->context_id, std::move(command_buffer), std::move(resources), std::move(semaphores)); |
| |
| if (!status) |
| SetError(&completer, status.get()); |
| } |
| |
| void ZirconPlatformConnection::ExecuteCommand(ExecuteCommandRequestView request, |
| ExecuteCommandCompleter::Sync& completer) { |
| FlowControl(); |
| |
| // TODO(fxbug.dev/92606) - support > 1 command buffer |
| if (request->command_buffers.count() > 1) { |
| SetError(&completer, MAGMA_STATUS_UNIMPLEMENTED); |
| return; |
| } |
| |
| auto command_buffer = std::make_unique<magma_command_buffer>(); |
| |
| *command_buffer = { |
| .resource_count = static_cast<uint32_t>(request->resources.count()), |
| .batch_buffer_resource_index = request->command_buffers[0].resource_index, |
| .batch_start_offset = request->command_buffers[0].start_offset, |
| .wait_semaphore_count = static_cast<uint32_t>(request->wait_semaphores.count()), |
| .signal_semaphore_count = static_cast<uint32_t>(request->signal_semaphores.count()), |
| .flags = static_cast<uint64_t>(request->flags), |
| }; |
| |
| std::vector<magma_exec_resource> resources; |
| resources.reserve(request->resources.count()); |
| |
| for (auto& buffer_range : request->resources) { |
| resources.push_back({ |
| buffer_range.buffer_id, |
| buffer_range.offset, |
| buffer_range.size, |
| }); |
| } |
| |
| // Merge semaphores into one vector |
| std::vector<uint64_t> semaphores; |
| semaphores.reserve(request->wait_semaphores.count() + request->signal_semaphores.count()); |
| |
| for (uint64_t semaphore_id : request->wait_semaphores) { |
| semaphores.push_back(semaphore_id); |
| } |
| for (uint64_t semaphore_id : request->signal_semaphores) { |
| semaphores.push_back(semaphore_id); |
| } |
| |
| magma::Status status = delegate_->ExecuteCommandBufferWithResources( |
| request->context_id, std::move(command_buffer), std::move(resources), std::move(semaphores)); |
| |
| if (!status) |
| SetError(&completer, status.get()); |
| } |
| |
| void ZirconPlatformConnection::ExecuteImmediateCommands( |
| ExecuteImmediateCommandsRequestView request, |
| ExecuteImmediateCommandsCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: ExecuteImmediateCommands"); |
| FlowControl(); |
| |
| magma::Status status = delegate_->ExecuteImmediateCommands( |
| request->context_id, request->command_data.count(), request->command_data.mutable_data(), |
| request->semaphores.count(), request->semaphores.mutable_data()); |
| if (!status) |
| SetError(&completer, status.get()); |
| } |
| |
| void ZirconPlatformConnection::Flush(FlushRequestView request, FlushCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: Flush"); |
| completer.Reply(); |
| } |
| |
| void ZirconPlatformConnection::MapBufferGpu(MapBufferGpuRequestView request, |
| MapBufferGpuCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: MapBufferGpuFIDL"); |
| FlowControl(); |
| |
| magma::Status status = |
| delegate_->MapBufferGpu(request->buffer_id, request->gpu_va, request->page_offset, |
| request->page_count, static_cast<uint64_t>(request->flags)); |
| if (!status.ok()) |
| SetError(&completer, status.get()); |
| } |
| |
| void ZirconPlatformConnection::UnmapBufferGpu(UnmapBufferGpuRequestView request, |
| UnmapBufferGpuCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection: UnmapBufferGpuFIDL"); |
| FlowControl(); |
| |
| magma::Status status = delegate_->UnmapBufferGpu(request->buffer_id, request->gpu_va); |
| if (!status.ok()) |
| SetError(&completer, status.get()); |
| } |
| |
| void ZirconPlatformConnection::BufferRangeOp(BufferRangeOpRequestView request, |
| BufferRangeOpCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection:::BufferOp"); |
| FlowControl(); |
| |
| std::optional<int> buffer_op = GetBufferOp(request->op); |
| if (!buffer_op) { |
| SetError(&completer, MAGMA_STATUS_INVALID_ARGS); |
| return; |
| } |
| |
| magma::Status status = |
| delegate_->BufferRangeOp(request->buffer_id, *buffer_op, request->offset, request->length); |
| |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| void ZirconPlatformConnection::EnablePerformanceCounterAccess( |
| EnablePerformanceCounterAccessRequestView request, |
| EnablePerformanceCounterAccessCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection:::EnablePerformanceCounterAccess"); |
| FlowControl(); |
| |
| magma::Status status = delegate_->EnablePerformanceCounterAccess( |
| magma::PlatformHandle::Create(request->access_token.release())); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| void ZirconPlatformConnection::IsPerformanceCounterAccessAllowed( |
| IsPerformanceCounterAccessAllowedRequestView request, |
| IsPerformanceCounterAccessAllowedCompleter::Sync& completer) { |
| DLOG("ZirconPlatformConnection:::IsPerformanceCounterAccessAllowed"); |
| completer.Reply(delegate_->IsPerformanceCounterAccessAllowed()); |
| } |
| |
| void ZirconPlatformConnection::EnablePerformanceCounters( |
| EnablePerformanceCountersRequestView request, |
| EnablePerformanceCountersCompleter::Sync& completer) { |
| FlowControl(); |
| magma::Status status = |
| delegate_->EnablePerformanceCounters(request->counters.data(), request->counters.count()); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| void ZirconPlatformConnection::CreatePerformanceCounterBufferPool( |
| CreatePerformanceCounterBufferPoolRequestView request, |
| CreatePerformanceCounterBufferPoolCompleter::Sync& completer) { |
| FlowControl(); |
| auto pool = std::make_unique<ZirconPlatformPerfCountPool>(request->pool_id, |
| request->event_channel.TakeChannel()); |
| magma::Status status = delegate_->CreatePerformanceCounterBufferPool(std::move(pool)); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| void ZirconPlatformConnection::ReleasePerformanceCounterBufferPool( |
| ReleasePerformanceCounterBufferPoolRequestView request, |
| ReleasePerformanceCounterBufferPoolCompleter::Sync& completer) { |
| FlowControl(); |
| magma::Status status = delegate_->ReleasePerformanceCounterBufferPool(request->pool_id); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| void ZirconPlatformConnection::AddPerformanceCounterBufferOffsetsToPool( |
| AddPerformanceCounterBufferOffsetsToPoolRequestView request, |
| AddPerformanceCounterBufferOffsetsToPoolCompleter::Sync& completer) { |
| FlowControl(); |
| for (auto& offset : request->offsets) { |
| magma::Status status = delegate_->AddPerformanceCounterBufferOffsetToPool( |
| request->pool_id, offset.buffer_id, offset.offset, offset.size); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| } |
| |
| void ZirconPlatformConnection::RemovePerformanceCounterBufferFromPool( |
| RemovePerformanceCounterBufferFromPoolRequestView request, |
| RemovePerformanceCounterBufferFromPoolCompleter::Sync& completer) { |
| FlowControl(); |
| magma::Status status = |
| delegate_->RemovePerformanceCounterBufferFromPool(request->pool_id, request->buffer_id); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| void ZirconPlatformConnection::DumpPerformanceCounters( |
| DumpPerformanceCountersRequestView request, DumpPerformanceCountersCompleter::Sync& completer) { |
| FlowControl(); |
| magma::Status status = delegate_->DumpPerformanceCounters(request->pool_id, request->trigger_id); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| void ZirconPlatformConnection::ClearPerformanceCounters( |
| ClearPerformanceCountersRequestView request, |
| ClearPerformanceCountersCompleter::Sync& completer) { |
| FlowControl(); |
| magma::Status status = |
| delegate_->ClearPerformanceCounters(request->counters.data(), request->counters.count()); |
| if (!status) { |
| SetError(&completer, status.get()); |
| } |
| } |
| |
| std::shared_ptr<PlatformConnection> PlatformConnection::Create( |
| std::unique_ptr<PlatformConnection::Delegate> delegate, msd_client_id_t client_id, |
| std::unique_ptr<magma::PlatformHandle> thread_profile, |
| std::unique_ptr<magma::PlatformHandle> server_endpoint, |
| std::unique_ptr<magma::PlatformHandle> server_notification_endpoint) { |
| if (!delegate) |
| return DRETP(nullptr, "attempting to create PlatformConnection with null delegate"); |
| |
| auto shutdown_event = magma::PlatformEvent::Create(); |
| if (!shutdown_event) |
| return DRETP(nullptr, "Failed to create shutdown event"); |
| |
| auto connection = std::make_shared<ZirconPlatformConnection>( |
| std::move(delegate), client_id, zx::channel(server_notification_endpoint->release()), |
| std::shared_ptr<magma::PlatformEvent>(std::move(shutdown_event)), std::move(thread_profile)); |
| |
| if (!connection->Bind(zx::channel(server_endpoint->release()))) |
| return DRETP(nullptr, "Bind failed"); |
| |
| if (!connection->BeginShutdownWait()) |
| return DRETP(nullptr, "Failed to begin shutdown wait"); |
| |
| return connection; |
| } |
| |
| } // namespace magma |