blob: 32c3aeaf016b13301481b3a74df32976afe7026f [file] [log] [blame]
/*
*
* 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