xref: /aosp_15_r20/external/executorch/runtime/platform/default/posix.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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 /**
10  * @file
11  * Fallback PAL implementations for POSIX-compatible systems.
12  *
13  * Note that this assumes that the platform defines the symbols used in this
14  * file (like fprintf()), because this file will still be built even if the
15  * functions are later overridden. When building for a platform that does not
16  * provide the necessary symbols, clients can use Minimal.cpp instead, but they
17  * will need to override all of the functions.
18  */
19 
20 // This cpp file will provide weak implementations of the symbols declared in
21 // Platform.h. Client users can strongly define any or all of the functions to
22 // override them.
23 #define ET_INTERNAL_PLATFORM_WEAKNESS ET_WEAK
24 #include <executorch/runtime/platform/platform.h>
25 
26 #include <chrono>
27 #include <cinttypes>
28 #include <cstdio>
29 #include <cstdlib>
30 
31 #include <executorch/runtime/platform/compiler.h>
32 
33 // The FILE* to write logs to.
34 #define ET_LOG_OUTPUT_FILE stderr
35 
36 /**
37  * On debug builds, ensure that `et_pal_init` has been called before
38  * other PAL functions which depend on initialization.
39  */
40 #ifdef NDEBUG
41 
42 /**
43  * Assert that the PAL has been initialized.
44  */
45 #define _ASSERT_PAL_INITIALIZED() ((void)0)
46 
47 #else // NDEBUG
48 
49 /**
50  * Assert that the PAL has been initialized.
51  */
52 #define _ASSERT_PAL_INITIALIZED()                                   \
53   do {                                                              \
54     if (!initialized) {                                             \
55       fprintf(                                                      \
56           ET_LOG_OUTPUT_FILE,                                       \
57           "ExecuTorch PAL must be initialized before call to %s()", \
58           ET_FUNCTION);                                             \
59       fflush(ET_LOG_OUTPUT_FILE);                                   \
60       et_pal_abort();                                               \
61     }                                                               \
62   } while (0)
63 
64 #endif // NDEBUG
65 
66 /// Start time of the system (used to zero the system timestamp).
67 static std::chrono::time_point<std::chrono::steady_clock> systemStartTime;
68 
69 /// Flag set to true if the PAL has been successfully initialized.
70 static bool initialized = false;
71 
72 /**
73  * Initialize the platform abstraction layer.
74  *
75  * This function should be called before any other function provided by the PAL
76  * to initialize any global state. Typically overridden by PAL implementer.
77  */
et_pal_init(void)78 void et_pal_init(void) {
79   if (initialized) {
80     return;
81   }
82 
83   systemStartTime = std::chrono::steady_clock::now();
84   initialized = true;
85 }
86 
87 /**
88  * Immediately abort execution, setting the device into an error state, if
89  * available.
90  */
et_pal_abort(void)91 ET_NORETURN void et_pal_abort(void) {
92   std::abort();
93 }
94 
95 /**
96  * Return a monotonically non-decreasing timestamp in system ticks.
97  *
98  * @retval Timestamp value in system ticks.
99  */
et_pal_current_ticks(void)100 et_timestamp_t et_pal_current_ticks(void) {
101   _ASSERT_PAL_INITIALIZED();
102   auto systemCurrentTime = std::chrono::steady_clock::now();
103   return std::chrono::duration_cast<std::chrono::nanoseconds>(
104              systemCurrentTime - systemStartTime)
105       .count();
106 }
107 
108 /**
109  * Return the conversion rate from system ticks to nanoseconds, as a fraction.
110  * To convert an interval from system ticks to nanoseconds, multiply the tick
111  * count by the numerator and then divide by the denominator:
112  *   nanoseconds = ticks * numerator / denominator
113  *
114  * @retval The ratio of nanoseconds to system ticks.
115  */
et_pal_ticks_to_ns_multiplier(void)116 et_tick_ratio_t et_pal_ticks_to_ns_multiplier(void) {
117   // The system tick interval is 1 nanosecond, so the conversion factor is 1.
118   return {1, 1};
119 }
120 
121 /**
122  * Emit a log message via platform output (serial port, console, etc).
123  *
124  * @param[in] timestamp Timestamp of the log event in system ticks since boot.
125  * @param[in] level Severity level of the message. Must be a printable 7-bit
126  *     ASCII uppercase letter.
127  * @param[in] filename Name of the file that created the log event.
128  * @param[in] function Name of the function that created the log event.
129  * @param[in] line Line in the source file where the log event was created.
130  * @param[in] message Message string to log.
131  * @param[in] length Message string length.
132  */
et_pal_emit_log_message(et_timestamp_t timestamp,et_pal_log_level_t level,const char * filename,ET_UNUSED const char * function,size_t line,const char * message,ET_UNUSED size_t length)133 void et_pal_emit_log_message(
134     et_timestamp_t timestamp,
135     et_pal_log_level_t level,
136     const char* filename,
137     ET_UNUSED const char* function,
138     size_t line,
139     const char* message,
140     ET_UNUSED size_t length) {
141   _ASSERT_PAL_INITIALIZED();
142 
143   // Not all platforms have ticks == nanoseconds, but this one does.
144   timestamp /= 1000; // To microseconds
145   unsigned long int us = timestamp % 1000000;
146   timestamp /= 1000000; // To seconds
147   unsigned int sec = timestamp % 60;
148   timestamp /= 60; // To minutes
149   unsigned int min = timestamp % 60;
150   timestamp /= 60; // To hours
151   unsigned int hour = timestamp;
152 
153   // Use a format similar to glog and folly::logging, except:
154   // - Print time since et_pal_init since we don't have wall time
155   // - Don't include the thread ID, to avoid adding a threading dependency
156   // - Add the string "executorch:" to make the logs more searchable
157   //
158   // Clients who want to change the format or add other fields can override this
159   // weak implementation of et_pal_emit_log_message.
160   fprintf(
161       ET_LOG_OUTPUT_FILE,
162       "%c %02u:%02u:%02u.%06lu executorch:%s:%zu] %s\n",
163       level,
164       hour,
165       min,
166       sec,
167       us,
168       filename,
169       line,
170       message);
171   fflush(ET_LOG_OUTPUT_FILE);
172 }
173 
174 /**
175  * NOTE: Core runtime code must not call this directly. It may only be called by
176  * a MemoryAllocator wrapper.
177  *
178  * Allocates size bytes of memory via malloc.
179  *
180  * @param[in] size Number of bytes to allocate.
181  * @returns the allocated memory, or nullptr on failure. Must be freed using
182  *     et_pal_free().
183  */
et_pal_allocate(size_t size)184 void* et_pal_allocate(size_t size) {
185   return malloc(size);
186 }
187 
188 /**
189  * Frees memory allocated by et_pal_allocate().
190  *
191  * @param[in] ptr Pointer to memory to free. May be nullptr.
192  */
et_pal_free(void * ptr)193 void et_pal_free(void* ptr) {
194   free(ptr);
195 }
196