Skip to content

Commit 60929cf

Browse files
authored
Introduce PAL function table (#10675)
Summary: This is part 1 of the implementation of the PAL changes described in #10432. This PR introduces a struct (`pal_table`) to hold function pointers to the PAL function implementations. There is a singleton instance of this struct, which is initialized with the weak/strong et_pal_ functions - maintaining backwards compatibility with the existing override mechanism. I've then added wrapper functions for the PAL into the executorch::runtime namespace which dispatch through the function table. It is intended that callers use these functions instead of the "raw" et_pal_ methods in order to correctly dispatch through the function table. In the following PR, I update ET callers to do this. Differential Revision: D74121895
1 parent 36a3207 commit 60929cf

File tree

16 files changed

+645
-88
lines changed

16 files changed

+645
-88
lines changed

.github/workflows/pull.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ jobs:
371371
size=${arr[4]}
372372
# threshold=48120 on devserver with gcc11.4
373373
# todo(lfq): update once binary size is below 50kb.
374-
threshold="55504"
374+
threshold="55584"
375375
if [[ "$size" -le "$threshold" ]]; then
376376
echo "Success $size <= $threshold"
377377
else
@@ -406,7 +406,7 @@ jobs:
406406
output=$(ls -la cmake-out/test/size_test)
407407
arr=($output)
408408
size=${arr[4]}
409-
threshold="51656"
409+
threshold="51728"
410410
if [[ "$size" -le "$threshold" ]]; then
411411
echo "Success $size <= $threshold"
412412
else

backends/xnnpack/runtime/profiling/XNNProfiler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Error XNNProfiler::start(EventTracer* event_tracer) {
6262
state_ = XNNProfilerState::Running;
6363

6464
// Log the start of execution timestamp.
65-
start_time_ = et_pal_current_ticks();
65+
start_time_ = runtime::pal_current_ticks();
6666

6767
return Error::Ok;
6868
}
@@ -187,7 +187,7 @@ void XNNProfiler::log_operator_timings() {
187187

188188
void XNNProfiler::submit_trace() {
189189
// Retrieve the system tick rate (ratio between ticks and nanoseconds).
190-
auto tick_ns_conv_multiplier = et_pal_ticks_to_ns_multiplier();
190+
auto tick_ns_conv_multiplier = runtime::pal_ticks_to_ns_multiplier();
191191

192192
ET_CHECK(op_timings_.size() == op_count_);
193193
size_t name_len = 0;

devtools/etdump/etdump_flatcc.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ EventTracerEntry ETDumpGen::start_profiling(
224224
prof_entry.chain_id = chain_id;
225225
prof_entry.debug_handle = debug_handle;
226226
}
227-
prof_entry.start_time = et_pal_current_ticks();
227+
prof_entry.start_time = runtime::pal_current_ticks();
228228
return prof_entry;
229229
}
230230

@@ -246,15 +246,15 @@ EventTracerEntry ETDumpGen::start_profiling_delegate(
246246
prof_entry.event_id = delegate_debug_index == kUnsetDelegateDebugIntId
247247
? create_string_entry(name)
248248
: delegate_debug_index;
249-
prof_entry.start_time = et_pal_current_ticks();
249+
prof_entry.start_time = runtime::pal_current_ticks();
250250
return prof_entry;
251251
}
252252

253253
void ETDumpGen::end_profiling_delegate(
254254
EventTracerEntry event_tracer_entry,
255255
const void* metadata,
256256
size_t metadata_len) {
257-
et_timestamp_t end_time = et_pal_current_ticks();
257+
et_timestamp_t end_time = runtime::pal_current_ticks();
258258
check_ready_to_add_events();
259259

260260
// Start building the ProfileEvent entry.
@@ -469,7 +469,7 @@ Result<bool> ETDumpGen::log_intermediate_output_delegate_helper(
469469
}
470470

471471
void ETDumpGen::end_profiling(EventTracerEntry prof_entry) {
472-
et_timestamp_t end_time = et_pal_current_ticks();
472+
et_timestamp_t end_time = runtime::pal_current_ticks();
473473
ET_CHECK_MSG(
474474
prof_entry.delegate_event_id_type == DelegateDebugIdType::kNone,
475475
"Delegate events must use end_profiling_delegate to mark the end of a delegate profiling event.");

examples/portable/executor_runner/executor_runner.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,11 @@ int main(int argc, char** argv) {
269269
(uint32_t)inputs.error());
270270
ET_LOG(Debug, "Inputs prepared.");
271271

272-
const et_timestamp_t before_execute = et_pal_current_ticks();
272+
const et_timestamp_t before_execute =
273+
executorch::runtime::pal_current_ticks();
273274
Error status = method->execute();
274-
const et_timestamp_t after_execute = et_pal_current_ticks();
275+
const et_timestamp_t after_execute =
276+
executorch::runtime::pal_current_ticks();
275277
time_spent_executing += after_execute - before_execute;
276278
ET_CHECK_MSG(
277279
status == Error::Ok,

runtime/executor/platform_memory_allocator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class PlatformMemoryAllocator final : public MemoryAllocator {
4848

4949
// Allocate enough memory for the node, the data and the alignment bump.
5050
size_t alloc_size = sizeof(AllocationNode) + size + alignment;
51-
void* node_memory = et_pal_allocate(alloc_size);
51+
void* node_memory = runtime::pal_allocate(alloc_size);
5252

5353
// If allocation failed, log message and return nullptr.
5454
if (node_memory == nullptr) {
@@ -87,7 +87,7 @@ class PlatformMemoryAllocator final : public MemoryAllocator {
8787
AllocationNode* current = head_;
8888
while (current != nullptr) {
8989
AllocationNode* next = current->next;
90-
et_pal_free(current);
90+
runtime::pal_free(current);
9191
current = next;
9292
}
9393
head_ = nullptr;

runtime/platform/abort.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace runtime {
1717
* up, and set an abnormal exit status (platform-defined).
1818
*/
1919
ET_NORETURN void runtime_abort() {
20-
et_pal_abort();
20+
pal_abort();
2121
}
2222

2323
} // namespace runtime

runtime/platform/log.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace internal {
2323
* @retval Monotonically non-decreasing timestamp in system ticks.
2424
*/
2525
et_timestamp_t get_log_timestamp() {
26-
return et_pal_current_ticks();
26+
return pal_current_ticks();
2727
}
2828

2929
// Double-check that the log levels are ordered from lowest to highest severity.
@@ -96,7 +96,7 @@ void vlogf(
9696
? kLevelToPal[size_t(level)]
9797
: et_pal_log_level_t::kUnknown;
9898

99-
et_pal_emit_log_message(
99+
pal_emit_log_message(
100100
timestamp, pal_level, filename, function, line, buf, len);
101101

102102
#endif // ET_LOG_ENABLED

runtime/platform/platform.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#include <executorch/runtime/platform/log.h>
10+
#include <executorch/runtime/platform/platform.h>
11+
#include <cstdlib>
12+
13+
namespace executorch::runtime {
14+
15+
namespace {
16+
/**
17+
* The singleton instance of the PAL function table.
18+
*/
19+
PalImpl pal_impl = {
20+
et_pal_init,
21+
et_pal_abort,
22+
et_pal_current_ticks,
23+
et_pal_ticks_to_ns_multiplier,
24+
et_pal_emit_log_message,
25+
et_pal_allocate,
26+
et_pal_free,
27+
__FILE__};
28+
29+
/**
30+
* Tracks whether the PAL has been overridden. This is used to warn when
31+
* multiple callers override the PAL.
32+
*/
33+
bool is_pal_overridden = false;
34+
} // namespace
35+
36+
PalImpl PalImpl::create(
37+
pal_emit_log_message_method emit_log_message,
38+
const char* source_filename) {
39+
return PalImpl::create(
40+
nullptr, // init
41+
nullptr, // abort
42+
nullptr, // current_ticks
43+
nullptr, // ticks_to_ns_multiplier
44+
emit_log_message,
45+
nullptr, // allocate
46+
nullptr, // free
47+
source_filename);
48+
}
49+
50+
PalImpl PalImpl::create(
51+
pal_init_method init,
52+
pal_abort_method abort,
53+
pal_current_ticks_method current_ticks,
54+
pal_ticks_to_ns_multiplier_method ticks_to_ns_multiplier,
55+
pal_emit_log_message_method emit_log_message,
56+
pal_allocate_method allocate,
57+
pal_free_method free,
58+
const char* source_filename) {
59+
return PalImpl{
60+
init,
61+
abort,
62+
current_ticks,
63+
ticks_to_ns_multiplier,
64+
emit_log_message,
65+
allocate,
66+
free,
67+
source_filename};
68+
}
69+
70+
/**
71+
* Override the PAL functions with user implementations. Any null entries in the
72+
* table are unchanged and will keep the default implementation.
73+
*/
74+
bool register_pal(PalImpl impl) {
75+
if (is_pal_overridden) {
76+
ET_LOG(
77+
Error,
78+
"register_pal() called multiple times. Subsequent calls will override the previous implementation. Previous implementation was registered from %s.",
79+
impl.source_filename != nullptr ? impl.source_filename : "unknown");
80+
}
81+
is_pal_overridden = true;
82+
83+
if (impl.abort != nullptr) {
84+
pal_impl.abort = impl.abort;
85+
}
86+
87+
if (impl.current_ticks != nullptr) {
88+
pal_impl.current_ticks = impl.current_ticks;
89+
}
90+
91+
if (impl.ticks_to_ns_multiplier != nullptr) {
92+
pal_impl.ticks_to_ns_multiplier = impl.ticks_to_ns_multiplier;
93+
}
94+
95+
if (impl.emit_log_message != nullptr) {
96+
pal_impl.emit_log_message = impl.emit_log_message;
97+
}
98+
99+
if (impl.allocate != nullptr) {
100+
pal_impl.allocate = impl.allocate;
101+
}
102+
103+
if (impl.free != nullptr) {
104+
pal_impl.free = impl.free;
105+
}
106+
107+
if (impl.init != nullptr) {
108+
pal_impl.init = impl.init;
109+
if (pal_impl.init != nullptr) {
110+
pal_impl.init();
111+
}
112+
}
113+
114+
return true;
115+
}
116+
117+
const PalImpl* get_pal_impl() {
118+
return &pal_impl;
119+
}
120+
121+
void pal_init() {
122+
pal_impl.init();
123+
}
124+
125+
ET_NORETURN void pal_abort() {
126+
pal_impl.abort();
127+
// This should be unreachable, but in case the PAL implementation doesn't
128+
// abort, force it here.
129+
std::abort();
130+
}
131+
132+
et_timestamp_t pal_current_ticks() {
133+
return pal_impl.current_ticks();
134+
}
135+
136+
et_tick_ratio_t pal_ticks_to_ns_multiplier() {
137+
return pal_impl.ticks_to_ns_multiplier();
138+
}
139+
140+
void pal_emit_log_message(
141+
et_timestamp_t timestamp,
142+
et_pal_log_level_t level,
143+
const char* filename,
144+
const char* function,
145+
size_t line,
146+
const char* message,
147+
size_t length) {
148+
pal_impl.emit_log_message(
149+
timestamp, level, filename, function, line, message, length);
150+
}
151+
152+
void* pal_allocate(size_t size) {
153+
return pal_impl.allocate(size);
154+
}
155+
156+
void pal_free(void* ptr) {
157+
pal_impl.free(ptr);
158+
}
159+
160+
} // namespace executorch::runtime

0 commit comments

Comments
 (0)