blob: 287b060a5d8da440d518e071d09c8e3625bdc0af [file] [log] [blame] [edit]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <zircon/syscalls.h>
#include <thread>
#include <stacktrack/bind.h>
// A recursive function to create a deep stack trace.
[[gnu::noinline, clang::no_sanitize("safe-stack")]]
static void deep_recursion(int n) {
uint8_t large_local_buffer[1024];
// Ensure the buffer is not optimized away before the recursive call.
asm volatile("" : : "r"(large_local_buffer) : "memory");
if (n == 0) {
// Stacktrack measures stack usage at syscall call sites, so let's call one.
zx_nanosleep(ZX_TIME_INFINITE_PAST);
} else {
deep_recursion(n - 1);
}
// Avoid tail call optimization and ensure the buffer is not optimized away after the recursive
// call.
asm volatile("" : : "r"(large_local_buffer) : "memory");
}
static void sleep_10s() {
fprintf(stderr, "Sleep start\n");
sleep(10);
fprintf(stderr, "Sleep stop\n");
}
int main(int argc, char **argv) {
fprintf(stderr, "Stacktrack example starting...\n");
stacktrack_bind_with_fdio();
for (int i = 20; i < 30; i++) {
fprintf(stderr, "Iteration %d\n", i);
deep_recursion(i);
sleep(1);
}
fprintf(stderr, "First part finished, entering second part...\n");
// This creates an alternating pattern of having four threads active (the main
// thread plus the three auxiliary threads) and then just the main thread.
while (true) {
std::thread t1(sleep_10s);
std::thread t2(sleep_10s);
std::thread t3(sleep_10s);
t1.join();
t2.join();
t3.join();
sleep_10s();
}
}