1616#include <zephyr/autoconf.h>
1717#include <zephyr/kernel.h>
1818#include <zephyr/sys/reboot.h>
19+ #include <zephyr/sys/util.h>
1920
2021#if defined(CONFIG_ARCH_POSIX )
2122#include <limits.h>
2930#include "lib/tlsf/tlsf.h"
3031#include <zephyr/device.h>
3132
33+ #if defined(CONFIG_TRACING_PERFETTO ) && defined(CONFIG_BOARD_NATIVE_SIM )
34+ #include "perfetto_encoder.h"
35+ #include <zephyr/sys/mem_stats.h>
36+ #define CIRCUITPY_PERFETTO_TRACK_GROUP_UUID 0x3000ULL
37+ #define CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID 0x3001ULL
38+ #define CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID 0x3002ULL
39+ #endif
40+
3241static tlsf_t heap ;
42+ static size_t tlsf_heap_used = 0 ;
3343
3444// Auto generated in pins.c
3545extern const struct device * const rams [];
@@ -72,12 +82,60 @@ static void native_sim_register_cmdline_opts(void) {
7282NATIVE_TASK (native_sim_register_cmdline_opts , PRE_BOOT_1 , 0 );
7383#endif
7484
85+ #if defined(CONFIG_TRACING_PERFETTO ) && defined(CONFIG_BOARD_NATIVE_SIM )
86+ static bool perfetto_circuitpython_tracks_emitted ;
87+
88+ static void perfetto_emit_outer_heap_stats (void ) {
89+ if (!perfetto_start ()) {
90+ return ;
91+ }
92+ size_t total = tlsf_heap_used ;
93+ #if defined(CONFIG_COMMON_LIBC_MALLOC ) && defined(CONFIG_SYS_HEAP_RUNTIME_STATS )
94+ extern int malloc_runtime_stats_get (struct sys_memory_stats * stats );
95+ struct sys_memory_stats stats ;
96+ if (malloc_runtime_stats_get (& stats ) == 0 ) {
97+ total += stats .allocated_bytes ;
98+ }
99+ #endif
100+ perfetto_emit_counter (CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID , (int64_t )total );
101+ Z_SPIN_DELAY (1 );
102+ }
103+
104+ static void perfetto_emit_circuitpython_tracks (void ) {
105+ if (perfetto_circuitpython_tracks_emitted ) {
106+ return ;
107+ }
108+ if (!perfetto_start ()) {
109+ return ;
110+ }
111+ perfetto_emit_track_descriptor (CIRCUITPY_PERFETTO_TRACK_GROUP_UUID ,
112+ perfetto_get_process_uuid (),
113+ "CircuitPython" );
114+ perfetto_emit_counter_track_descriptor (CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID ,
115+ CIRCUITPY_PERFETTO_TRACK_GROUP_UUID ,
116+ "VM Heap Used" ,
117+ PERFETTO_COUNTER_UNIT_BYTES );
118+ perfetto_emit_counter_track_descriptor (CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID ,
119+ CIRCUITPY_PERFETTO_TRACK_GROUP_UUID ,
120+ "Outer Heap Used" ,
121+ PERFETTO_COUNTER_UNIT_BYTES );
122+ perfetto_circuitpython_tracks_emitted = true;
123+ }
124+ #else
125+ static inline void perfetto_emit_outer_heap_stats (void ) {
126+ }
127+
128+ static inline void perfetto_emit_circuitpython_tracks (void ) {
129+ }
130+ #endif
131+
75132static void _tick_function (struct k_timer * timer_id ) {
76133 supervisor_tick ();
77134}
78135
79136safe_mode_t port_init (void ) {
80137 k_timer_init (& tick_timer , _tick_function , NULL );
138+ perfetto_emit_circuitpython_tracks ();
81139 return SAFE_MODE_NONE ;
82140}
83141
@@ -233,6 +291,7 @@ void port_heap_init(void) {
233291 }
234292 valid_pool_count ++ ;
235293 }
294+ perfetto_emit_outer_heap_stats ();
236295 #if !DT_HAS_CHOSEN (zephyr_sram )
237296 #error "No SRAM!"
238297 #endif
@@ -243,30 +302,54 @@ void *port_malloc(size_t size, bool dma_capable) {
243302 if (valid_pool_count > 0 ) {
244303 block = tlsf_malloc (heap , size );
245304 }
305+ if (block != NULL ) {
306+ tlsf_heap_used += tlsf_block_size (block );
307+ }
246308 #ifdef CONFIG_COMMON_LIBC_MALLOC
247309 if (block == NULL ) {
248310 block = malloc (size );
249311 }
250312 #endif
313+ if (block != NULL ) {
314+ perfetto_emit_outer_heap_stats ();
315+ }
251316 return block ;
252317}
253318
254319void port_free (void * ptr ) {
320+ if (ptr == NULL ) {
321+ return ;
322+ }
255323 if (valid_pool_count > 0 && !(ptr >= zephyr_malloc_bottom && ptr < zephyr_malloc_top )) {
324+ tlsf_heap_used -= tlsf_block_size (ptr );
256325 tlsf_free (heap , ptr );
257- return ;
326+ } else {
327+ #ifdef CONFIG_COMMON_LIBC_MALLOC
328+ free (ptr );
329+ #endif
258330 }
259- #ifdef CONFIG_COMMON_LIBC_MALLOC
260- free (ptr );
261- #endif
331+ perfetto_emit_outer_heap_stats ();
262332}
263333
264334void * port_realloc (void * ptr , size_t size , bool dma_capable ) {
335+ if (ptr == NULL ) {
336+ return port_malloc (size , dma_capable );
337+ }
265338 if (valid_pool_count > 0 && !(ptr >= zephyr_malloc_bottom && ptr < zephyr_malloc_top )) {
266- return tlsf_realloc (heap , ptr , size );
339+ size_t old_size = tlsf_block_size (ptr );
340+ void * new_block = tlsf_realloc (heap , ptr , size );
341+ if (new_block != NULL ) {
342+ tlsf_heap_used = tlsf_heap_used - old_size + tlsf_block_size (new_block );
343+ perfetto_emit_outer_heap_stats ();
344+ }
345+ return new_block ;
267346 }
268347 #ifdef CONFIG_COMMON_LIBC_MALLOC
269- return realloc (ptr , size );
348+ void * new_block = realloc (ptr , size );
349+ if (new_block != NULL ) {
350+ perfetto_emit_outer_heap_stats ();
351+ }
352+ return new_block ;
270353 #endif
271354 return NULL ;
272355}
0 commit comments