1 // Copyright 2023 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 //============================================================================== 15 // 16 17 #include <pthread.h> 18 #include <sys/syscall.h> 19 #include <unistd.h> 20 21 #include <chrono> 22 #include <cstdio> 23 #include <thread> 24 25 #include "pw_log/log.h" 26 #include "pw_trace/trace.h" 27 #include "pw_trace_tokenized/example/trace_to_file.h" 28 29 // Example for annotating trace events with thread id. 30 // The platform annotates instants and duration events with the thread id if the 31 // caller does not explicitly provide a group. The thread id is written in 32 // the trace_id field. 33 // 34 // This example requires linux_config_overrides.h to define 35 // PW_TRACE_HAS_TRACE_ID. Set pw_trace_CONFIG to 36 // "$dir_pw_trace_tokenized:linux_config_overrides" in target_toolchains.gni to 37 // enable the override before building this example. 38 // 39 // TODO(ykyyip): update trace_tokenized.py to handle the trace_id. 40 TraceEventCallback(void *,pw_trace_tokenized_TraceEvent * event)41pw_trace_TraceEventReturnFlags TraceEventCallback( 42 void* /*user_data*/, pw_trace_tokenized_TraceEvent* event) { 43 // Instant and duration events with no group means group by pid/tid. 44 if ((event->event_type == PW_TRACE_EVENT_TYPE_INSTANT) || 45 (event->event_type == PW_TRACE_EVENT_TYPE_DURATION_START) || 46 (event->event_type == PW_TRACE_EVENT_TYPE_DURATION_END)) { 47 event->trace_id = syscall(__NR_gettid); 48 } 49 return PW_TRACE_EVENT_RETURN_FLAGS_NONE; 50 } 51 ExampleTask(void *)52void ExampleTask(void* /*arg*/) { 53 int times_to_run = 10; 54 while (times_to_run--) { 55 PW_TRACE_START("Processing"); 56 // Fake processing time. 57 std::this_thread::sleep_for(std::chrono::milliseconds(42)); 58 PW_TRACE_END("Processing"); 59 // Sleep for a random amount before running again. 60 int sleep_time = 1 + std::rand() % 20; 61 std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time)); 62 } 63 } 64 RunThreadedTraceSampleApp()65void RunThreadedTraceSampleApp() { 66 std::srand(std::time(nullptr)); 67 68 // Start threads to show parallel processing. 69 int num_threads = 5; 70 while (num_threads--) { 71 PW_TRACE_INSTANT("CreateThread"); 72 std::thread thread(ExampleTask, nullptr); 73 thread.detach(); 74 } 75 } 76 main(int argc,char ** argv)77int main(int argc, char** argv) { 78 if (argc != 2) { 79 PW_LOG_ERROR("Expected output file name as argument.\n"); 80 return -1; 81 } 82 83 // Enable tracing. 84 PW_TRACE_SET_ENABLED(true); 85 86 // Dump trace data to the file passed in. 87 pw::trace::TraceToFile trace_to_file{argv[1]}; 88 89 // Register platform callback 90 pw::trace::RegisterCallbackWhenCreated{TraceEventCallback}; 91 92 PW_LOG_INFO("Running threaded trace example...\n"); 93 RunThreadedTraceSampleApp(); 94 95 // Sleep forever 96 while (true) { 97 std::this_thread::sleep_for(std::chrono::seconds(60)); 98 } 99 return 0; 100 } 101