| /* |
| * |
| * 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 <fidl/fuchsia.io/cpp/wire.h> |
| #include <fidl/fuchsia.opencl.loader/cpp/wire.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/io.h> |
| #include <lib/fidl/llcpp/connect_service.h> |
| #include <lib/service/llcpp/service.h> |
| #include <lib/syslog/global.h> |
| #include <stdio.h> |
| #include <threads.h> |
| #include <zircon/status.h> |
| #include <zircon/syscalls.h> |
| |
| static fidl::WireSyncClient<fuchsia_opencl_loader::Loader> opencl_loader_svc; |
| |
| static zx_handle_t device_fs = ZX_HANDLE_INVALID; |
| |
| constexpr const char* kTag = "opencl"; |
| |
| void connect_to_opencl_loader_svc() { |
| auto svc = service::OpenServiceRoot(); |
| auto client_end = service::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::BindSyncClient(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\". Retrying.", |
| feature_result.error().lossy_description()); |
| // If GetSupportedFeatures isn't available the connection will be closed. |
| // If that happens, reconnect and assume a default set of features. |
| auto client_end = service::ConnectAt<fuchsia_opencl_loader::Loader>(*svc); |
| if (!client_end.is_ok()) { |
| FX_LOGF(ERROR, NULL, |
| "connect_to_opencl_loader_svc: Failed to reconnect to loader service: %s", |
| client_end.status_string()); |
| return; |
| } |
| client = fidl::BindSyncClient(std::move(*client_end)); |
| features = fuchsia_opencl_loader::wire::Features::kGet; |
| } else { |
| features = feature_result->features; |
| } |
| zx::channel device_fs_client; |
| if (features & fuchsia_opencl_loader::wire::Features::kConnectToDeviceFs) { |
| 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; |
| } |
| } |
| |
| 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; |
| } |