Skip to content

Commit ad855e1

Browse files
LukeBoyertensorflower-gardener
authored andcommitted
Pull generic dynamic loading utils into core api. This will need to be reused for loading plugin .so from driver.
PiperOrigin-RevId: 682739754
1 parent 981e6d9 commit ad855e1

File tree

6 files changed

+93
-109
lines changed

6 files changed

+93
-109
lines changed

tensorflow/lite/experimental/lrt/core/BUILD

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ cc_library(
122122
],
123123
)
124124

125+
cc_library(
126+
name = "dynamic_loading",
127+
srcs = ["dynamic_loading.cc"],
128+
hdrs = ["dynamic_loading.h"],
129+
linkopts = ["-ldl"],
130+
deps = ["@com_google_absl//absl/strings:string_view"],
131+
)
132+
125133
cc_library(
126134
name = "tensor_buffer",
127135
srcs = [

tensorflow/lite/experimental/lrt/qnn_sdk/load_sdk.cc renamed to tensorflow/lite/experimental/lrt/core/dynamic_loading.cc

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "tensorflow/lite/experimental/lrt/qnn_sdk/load_sdk.h"
15+
#include "tensorflow/lite/experimental/lrt/core/dynamic_loading.h"
1616

1717
#include <dlfcn.h>
1818
#include <link.h>
@@ -22,29 +22,39 @@
2222

2323
#include "absl/strings/string_view.h"
2424

25-
namespace qnn::load {
25+
namespace lrt {
2626

27-
void DumpDlInfo(void* handle) {
28-
std::cerr << "--- Dyn Load Info ---\n";
27+
void* OpenLib(absl::string_view so_path) {
28+
void* lib_handle =
29+
::dlopen(so_path.data(), RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
30+
if (lib_handle == nullptr) {
31+
std::cerr << "Failed to load so at path: " << so_path
32+
<< " with err: " << ::dlerror() << "\n";
33+
}
34+
return lib_handle;
35+
}
36+
37+
void DumpLibInfo(void* lib_handle) {
38+
std::cerr << "--- Lib Info ---\n";
2939

3040
Lmid_t dl_ns_idx;
31-
if (0 != ::dlinfo(handle, RTLD_DI_LMID, &dl_ns_idx)) {
41+
if (0 != ::dlinfo(lib_handle, RTLD_DI_LMID, &dl_ns_idx)) {
3242
return;
3343
}
3444

3545
std::string dl_origin;
3646
dl_origin.resize(512);
37-
if (0 != ::dlinfo(handle, RTLD_DI_ORIGIN, dl_origin.data())) {
47+
if (0 != ::dlinfo(lib_handle, RTLD_DI_ORIGIN, dl_origin.data())) {
3848
return;
3949
}
4050

4151
link_map* lm;
42-
if (0 != ::dlinfo(handle, RTLD_DI_LINKMAP, &lm)) {
52+
if (0 != ::dlinfo(lib_handle, RTLD_DI_LINKMAP, &lm)) {
4353
return;
4454
}
4555

46-
std::cerr << "DL namespace: " << dl_ns_idx << "\n";
47-
std::cerr << "DL origin: " << dl_origin << "\n";
56+
std::cerr << "Lib Namespace: " << dl_ns_idx << "\n";
57+
std::cerr << "Lib Origin: " << dl_origin << "\n";
4858

4959
std::cerr << "loaded objects:\n";
5060

@@ -56,23 +66,12 @@ void DumpDlInfo(void* handle) {
5666
forward = forward->l_next;
5767
}
5868

59-
std::cerr << "*** " << lm->l_name << "\n";
69+
std::cerr << "***" << lm->l_name << "\n";
6070

6171
while (backward != nullptr) {
6272
std::cerr << " " << backward->l_name << "\n";
6373
backward = backward->l_prev;
6474
}
6575
}
6676

67-
void* LoadSO(absl::string_view so_path) {
68-
// TODO: Figure out why deepbind is actually needed (sigsegv w/o).
69-
void* lib_handle =
70-
::dlopen(so_path.data(), RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
71-
if (lib_handle == nullptr) {
72-
std::cerr << "Failed to load so at path: " << so_path
73-
<< " with err: " << ::dlerror() << "\n";
74-
}
75-
return lib_handle;
76-
}
77-
78-
} // namespace qnn::load
77+
} // namespace lrt
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2024 Google LLC.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef TENSORFLOW_LITE_EXPERIMENTAL_LRT_CORE_DYNAMIC_LOADING_H_
16+
#define TENSORFLOW_LITE_EXPERIMENTAL_LRT_CORE_DYNAMIC_LOADING_H_
17+
18+
#include <dlfcn.h>
19+
#include <stdlib.h>
20+
21+
#include <iostream>
22+
23+
#include "absl/strings/string_view.h"
24+
25+
namespace lrt {
26+
27+
// Loads shared library at given path, returning handle on success
28+
// and nullptr on failure.
29+
void* OpenLib(absl::string_view so_path);
30+
31+
// Dumps loading details of given lib handle.
32+
void DumpLibInfo(void* lib_handle);
33+
34+
// Resolves a named symbol from given lib handle of type Sym. Returns
35+
// nullptr on failure.
36+
template <class Sym>
37+
inline static Sym ResolveLibSymbol(void* lib_handle,
38+
absl::string_view sym_name) {
39+
Sym ptr = (Sym)::dlsym(lib_handle, sym_name.data());
40+
if (ptr == nullptr) {
41+
std::cerr << "Failed to resolve symbol: " << sym_name << " with err "
42+
<< ::dlerror() << "\n";
43+
}
44+
return ptr;
45+
}
46+
47+
} // namespace lrt
48+
49+
#endif // TENSORFLOW_LITE_EXPERIMENTAL_LRT_CORE_DYNAMIC_LOADING_H_

tensorflow/lite/experimental/lrt/qnn_sdk/BUILD

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,6 @@ package(
1919
default_visibility = ["//tensorflow/lite/experimental/lrt:__subpackages__"],
2020
)
2121

22-
ungrte_cc_library_with_qnn(
23-
name = "load_sdk",
24-
srcs = ["load_sdk.cc"],
25-
hdrs = ["load_sdk.h"],
26-
deps = [
27-
"@com_google_absl//absl/strings:string_view",
28-
# copybara:uncomment "//third_party/qairt:qnn_lib_headers",
29-
],
30-
)
31-
3222
ungrte_cc_library_with_qnn(
3323
name = "log",
3424
srcs = ["log.cc"],
@@ -43,12 +33,12 @@ ungrte_cc_library_with_qnn(
4333
srcs = ["qnn_manager.cc"],
4434
hdrs = ["qnn_manager.h"],
4535
deps = [
46-
":load_sdk",
4736
":log",
4837
"@com_google_absl//absl/strings:string_view",
4938
"@com_google_absl//absl/types:span",
5039
# copybara:uncomment "//third_party/qairt:qnn_lib_headers",
5140
"//tensorflow/lite/experimental/lrt/core:api_internal",
41+
"//tensorflow/lite/experimental/lrt/core:dynamic_loading",
5242
],
5343
)
5444

tensorflow/lite/experimental/lrt/qnn_sdk/load_sdk.h

Lines changed: 0 additions & 68 deletions
This file was deleted.

tensorflow/lite/experimental/lrt/qnn_sdk/qnn_manager.cc

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,25 @@
2525
#include "third_party/qairt/include/QNN/QnnTypes.h"
2626
#include "tensorflow/lite/experimental/lrt/c/lite_rt_common.h"
2727
#include "tensorflow/lite/experimental/lrt/cc/lite_rt_support.h"
28-
#include "tensorflow/lite/experimental/lrt/qnn_sdk/load_sdk.h"
28+
#include "tensorflow/lite/experimental/lrt/core/dynamic_loading.h"
2929
#include "tensorflow/lite/experimental/lrt/qnn_sdk/log.h"
3030

31-
using ::qnn::load::QnnInterfaceGetProvidersFn_t;
32-
3331
namespace qnn {
3432

3533
namespace {
3634

35+
// This is one of two qnns symbol that needs resolution. It is used to populate
36+
// pointers to related available qnn functions.
37+
constexpr char kLibQnnGetProvidersSymbol[] = "QnnInterface_getProviders";
38+
39+
// Type definition for the QnnInterface_getProviders symbol.
40+
typedef Qnn_ErrorHandle_t (*QnnInterfaceGetProvidersFn_t)(
41+
const QnnInterface_t*** provider_list, uint32_t* num_providers);
42+
3743
absl::Span<const QnnInterface_t*> LoadProvidersFromLib(void* lib_so) {
38-
load::QnnInterfaceGetProvidersFn_t get_providers = nullptr;
39-
get_providers = load::ResolveQnnSymbol<QnnInterfaceGetProvidersFn_t>(
40-
lib_so, load::kLibQnnGetProvidersSymbol);
44+
QnnInterfaceGetProvidersFn_t get_providers = nullptr;
45+
get_providers = lrt::ResolveLibSymbol<QnnInterfaceGetProvidersFn_t>(
46+
lib_so, kLibQnnGetProvidersSymbol);
4147
if (get_providers == nullptr) {
4248
std::cerr << "Failed to resolve get providers symbol\n";
4349
return {};
@@ -56,7 +62,7 @@ absl::Span<const QnnInterface_t*> LoadProvidersFromLib(void* lib_so) {
5662
} // namespace
5763

5864
LrtStatus QnnManager::LoadLibSO(absl::string_view path) {
59-
lib_so_ = load::LoadSO(path);
65+
lib_so_ = lrt::OpenLib(path);
6066
if (lib_so_ == nullptr) {
6167
return kLrtStatusDynamicLoadErr;
6268
}
@@ -67,7 +73,7 @@ void QnnManager::DumpLibSODetails() const {
6773
if (lib_so_ == nullptr) {
6874
return;
6975
}
70-
load::DumpDlInfo(lib_so_);
76+
lrt::DumpLibInfo(lib_so_);
7177
}
7278

7379
// TODO: Repace QnnManager::Funcs with indirection access operator.

0 commit comments

Comments
 (0)