| // Copyright 2023 The Pigweed Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| //============================================================================== |
| // |
| |
| #include <pthread.h> |
| #include <sys/syscall.h> |
| #include <unistd.h> |
| |
| #include <chrono> |
| #include <cstdio> |
| #include <thread> |
| |
| #include "pw_log/log.h" |
| #include "pw_trace/trace.h" |
| #include "pw_trace_tokenized/example/trace_to_file.h" |
| |
| // Example for annotating trace events with thread id. |
| // The platform annotates instants and duration events with the thread id if the |
| // caller does not explicitly provide a group. The thread id is written in |
| // the trace_id field. |
| // |
| // This example requires linux_config_overrides.h to define |
| // PW_TRACE_HAS_TRACE_ID. Set pw_trace_CONFIG to |
| // "$dir_pw_trace_tokenized:linux_config_overrides" in target_toolchains.gni to |
| // enable the override before building this example. |
| // |
| // TODO(ykyyip): update trace_tokenized.py to handle the trace_id. |
| |
| pw_trace_TraceEventReturnFlags TraceEventCallback( |
| void* /*user_data*/, pw_trace_tokenized_TraceEvent* event) { |
| // Instant and duration events with no group means group by pid/tid. |
| if ((event->event_type == PW_TRACE_EVENT_TYPE_INSTANT) || |
| (event->event_type == PW_TRACE_EVENT_TYPE_DURATION_START) || |
| (event->event_type == PW_TRACE_EVENT_TYPE_DURATION_END)) { |
| event->trace_id = syscall(__NR_gettid); |
| } |
| return PW_TRACE_EVENT_RETURN_FLAGS_NONE; |
| } |
| |
| void ExampleTask(void* /*arg*/) { |
| int times_to_run = 10; |
| while (times_to_run--) { |
| PW_TRACE_START("Processing"); |
| // Fake processing time. |
| std::this_thread::sleep_for(std::chrono::milliseconds(42)); |
| PW_TRACE_END("Processing"); |
| // Sleep for a random amount before running again. |
| int sleep_time = 1 + std::rand() % 20; |
| std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time)); |
| } |
| } |
| |
| void RunThreadedTraceSampleApp() { |
| std::srand(std::time(nullptr)); |
| |
| // Start threads to show parallel processing. |
| int num_threads = 5; |
| while (num_threads--) { |
| PW_TRACE_INSTANT("CreateThread"); |
| std::thread thread(ExampleTask, nullptr); |
| thread.detach(); |
| } |
| } |
| |
| int main(int argc, char** argv) { |
| if (argc != 2) { |
| PW_LOG_ERROR("Expected output file name as argument.\n"); |
| return -1; |
| } |
| |
| // Enable tracing. |
| PW_TRACE_SET_ENABLED(true); |
| |
| // Dump trace data to the file passed in. |
| pw::trace::TraceToFile trace_to_file{argv[1]}; |
| |
| // Register platform callback |
| pw::trace::RegisterCallbackWhenCreated{TraceEventCallback}; |
| |
| PW_LOG_INFO("Running threaded trace example...\n"); |
| RunThreadedTraceSampleApp(); |
| |
| // Sleep forever |
| while (true) { |
| std::this_thread::sleep_for(std::chrono::seconds(60)); |
| } |
| return 0; |
| } |