| /* |
| * |
| * Copyright (c) 2021 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| #include "loader_service.h" |
| |
| #include <fcntl.h> |
| #include <fidl/fuchsia.io/cpp/wire.h> |
| #include <fidl/fuchsia.opencl.loader/cpp/wire.h> |
| #include <lib/component/cpp/incoming/service_client.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/io.h> |
| #include <lib/fidl/cpp/wire/connect_service.h> |
| #include <lib/syslog/global.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <threads.h> |
| #include <zircon/status.h> |
| #include <zircon/syscalls.h> |
| |
| namespace opencl_loader { |
| |
| static fidl::WireSyncClient<fuchsia_opencl_loader::Loader> opencl_loader_svc; |
| |
| static zx_handle_t device_fs = ZX_HANDLE_INVALID; |
| |
| static int manifest_fs_fd = -1; |
| |
| void connect_to_opencl_loader_svc() { |
| auto svc = component::OpenServiceRoot(); |
| auto client_end = component::ConnectAt<fuchsia_opencl_loader::Loader>(*svc); |
| if (!client_end.is_ok()) { |
| FX_LOGF(ERROR, kTag, "connect_to_opencl_loader_svc: Failed to connect to loader service: %s", |
| client_end.status_string()); |
| return; |
| } |
| auto client = fidl::WireSyncClient(std::move(*client_end)); |
| auto feature_result = client->GetSupportedFeatures(); |
| fuchsia_opencl_loader::wire::Features features; |
| if (!feature_result.ok()) { |
| FX_LOGF(ERROR, kTag, |
| "connect_to_opencl_loader_svc: Failed to get supported features, error \"%s\".", |
| feature_result.error().lossy_description()); |
| return; |
| } |
| features = feature_result->features; |
| constexpr fuchsia_opencl_loader::wire::Features kMandatoryFeatures = |
| fuchsia_opencl_loader::wire::Features::kConnectToDeviceFs | |
| fuchsia_opencl_loader::wire::Features::kConnectToManifestFs | |
| fuchsia_opencl_loader::wire::Features::kGet; |
| if ((features & kMandatoryFeatures) != kMandatoryFeatures) { |
| FX_LOGF(ERROR, kTag, "connect_to_opencl_loader_svc: Missing mandatory feature 0x%x", |
| static_cast<uint32_t>(kMandatoryFeatures & ~features)); |
| return; |
| } |
| zx::channel device_fs_client; |
| { |
| zx::channel device_fs_server; |
| zx_status_t status = zx::channel::create(0, &device_fs_server, &device_fs_client); |
| if (status != ZX_OK) { |
| FX_LOGF(ERROR, kTag, "connect_to_opencl_loader_svc: Failed to create channel: %s", |
| zx_status_get_string(status)); |
| return; |
| } |
| auto result = client->ConnectToDeviceFs(std::move(device_fs_server)); |
| if (!result.ok()) { |
| FX_LOGF(ERROR, kTag, "connect_to_opencl_loader_svc: Failed to connect to device fs: %s", |
| result.status_string()); |
| return; |
| } |
| } |
| { |
| zx::channel manifest_fs_client; |
| zx::channel manifest_fs_server; |
| zx_status_t status = zx::channel::create(0, &manifest_fs_server, &manifest_fs_client); |
| if (status != ZX_OK) { |
| FX_LOGF(ERROR, kTag, "connect_to_opencl_loader_svc: Failed to create channel: %s", |
| zx_status_get_string(status)); |
| return; |
| } |
| // Wait for idle so clients will be sure that any existing ICDs will be completely available. |
| auto result = client->ConnectToManifestFs( |
| fuchsia_opencl_loader::wire::ConnectToManifestOptions::kWaitForIdle, |
| std::move(manifest_fs_server)); |
| if (!result.ok()) { |
| FX_LOGF(ERROR, kTag, "connect_to_opencl_loader_svc: Failed to connect to manifest fs: %s", |
| result.status_string()); |
| return; |
| } |
| status = fdio_fd_create(manifest_fs_client.release(), &manifest_fs_fd); |
| if (status != ZX_OK) { |
| FX_LOGF(ERROR, kTag, "connect_to_opencl_loader_svc: Failed to create manifest fs fd: %s", |
| zx_status_get_string(status)); |
| return; |
| } |
| } |
| opencl_loader_svc = std::move(client); |
| device_fs = device_fs_client.release(); |
| } |
| |
| static once_flag svc_connect_once_flag = ONCE_FLAG_INIT; |
| |
| fidl::WireSyncClient<fuchsia_opencl_loader::Loader>& get_opencl_loader_service() { |
| call_once(&svc_connect_once_flag, connect_to_opencl_loader_svc); |
| return opencl_loader_svc; |
| } |
| |
| zx_handle_t get_device_fs() { |
| call_once(&svc_connect_once_flag, connect_to_opencl_loader_svc); |
| return device_fs; |
| } |
| |
| int get_manifest_fs_fd(void) { |
| call_once(&svc_connect_once_flag, connect_to_opencl_loader_svc); |
| return manifest_fs_fd; |
| } |
| |
| } // namespace opencl_loader |