esphome: name: host-logger-thread-test host: api: logger: button: - platform: template name: "Start Thread Race Test" id: start_test_button on_press: - lambda: |- // Number of threads and messages per thread static const int NUM_THREADS = 3; static const int MESSAGES_PER_THREAD = 100; // Counters static std::atomic total_messages_logged{0}; // Thread function - must be a regular function pointer for pthread struct ThreadTest { static void *thread_func(void *arg) { int thread_id = *static_cast(arg); // Set thread name (different signatures on macOS vs Linux) char thread_name[16]; snprintf(thread_name, sizeof(thread_name), "LogThread%d", thread_id); #ifdef __APPLE__ pthread_setname_np(thread_name); #else pthread_setname_np(pthread_self(), thread_name); #endif // Log messages with different log levels for (int i = 0; i < MESSAGES_PER_THREAD; i++) { switch (i % 4) { case 0: ESP_LOGI("thread_test", "THREAD%d_MSG%03d_INFO_MESSAGE_WITH_DATA_%08X", thread_id, i, i * 12345); break; case 1: ESP_LOGD("thread_test", "THREAD%d_MSG%03d_DEBUG_MESSAGE_WITH_DATA_%08X", thread_id, i, i * 12345); break; case 2: ESP_LOGW("thread_test", "THREAD%d_MSG%03d_WARN_MESSAGE_WITH_DATA_%08X", thread_id, i, i * 12345); break; case 3: ESP_LOGE("thread_test", "THREAD%d_MSG%03d_ERROR_MESSAGE_WITH_DATA_%08X", thread_id, i, i * 12345); break; } total_messages_logged.fetch_add(1, std::memory_order_relaxed); // Small busy loop to vary timing between threads int delay_count = (thread_id + 1) * 10; while (delay_count-- > 0) { asm volatile("" ::: "memory"); // Prevent optimization } } return nullptr; } }; ESP_LOGI("thread_test", "RACE_TEST_START: Starting %d threads with %d messages each", NUM_THREADS, MESSAGES_PER_THREAD); // Reset counter for this test run total_messages_logged.store(0, std::memory_order_relaxed); pthread_t threads[NUM_THREADS]; int thread_ids[NUM_THREADS]; // Create all threads for (int i = 0; i < NUM_THREADS; i++) { thread_ids[i] = i; int ret = pthread_create(&threads[i], nullptr, ThreadTest::thread_func, &thread_ids[i]); if (ret != 0) { ESP_LOGE("thread_test", "RACE_TEST_ERROR: Failed to create thread %d", i); return; } } // Wait for all threads to complete for (int i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], nullptr); } ESP_LOGI("thread_test", "RACE_TEST_COMPLETE: All threads finished, total messages: %d", total_messages_logged.load(std::memory_order_relaxed));