xref: /aosp_15_r20/external/pigweed/pw_trace_tokenized/example/linux_group_by_tid.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 #include "pw_trace_tokenized/trace_callback.h"
29 #include "pw_trace_tokenized/trace_tokenized.h"
30 
31 // Example for annotating trace events with thread id.
32 // The platform annotates instants and duration events with the thread id if the
33 // caller does not explicitly provide a group. The thread id is written in
34 // the trace_id field.
35 //
36 // This example requires linux_config_overrides.h to define
37 // PW_TRACE_HAS_TRACE_ID. Set pw_trace_CONFIG to
38 // "$dir_pw_trace_tokenized:linux_config_overrides" in target_toolchains.gni to
39 // enable the override before building this example.
40 //
41 // TODO(ykyyip): update trace_tokenized.py to handle the trace_id.
42 
TraceEventCallback(void *,pw_trace_tokenized_TraceEvent * event)43 pw_trace_TraceEventReturnFlags TraceEventCallback(
44     void* /*user_data*/, pw_trace_tokenized_TraceEvent* event) {
45   // Instant and duration events with no group means group by pid/tid.
46   if ((event->event_type == PW_TRACE_EVENT_TYPE_INSTANT) ||
47       (event->event_type == PW_TRACE_EVENT_TYPE_DURATION_START) ||
48       (event->event_type == PW_TRACE_EVENT_TYPE_DURATION_END)) {
49     event->trace_id = syscall(__NR_gettid);
50   }
51   return PW_TRACE_EVENT_RETURN_FLAGS_NONE;
52 }
53 
ExampleTask(void *)54 void ExampleTask(void* /*arg*/) {
55   int times_to_run = 10;
56   while (times_to_run--) {
57     PW_TRACE_START("Processing");
58     //  Fake processing time.
59     std::this_thread::sleep_for(std::chrono::milliseconds(42));
60     PW_TRACE_END("Processing");
61     //  Sleep for a random amount before running again.
62     int sleep_time = 1 + std::rand() % 20;
63     std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
64   }
65 }
66 
RunThreadedTraceSampleApp()67 void RunThreadedTraceSampleApp() {
68   std::srand(std::time(nullptr));
69 
70   // Start threads to show parallel processing.
71   int num_threads = 5;
72   while (num_threads--) {
73     PW_TRACE_INSTANT("CreateThread");
74     std::thread thread(ExampleTask, nullptr);
75     thread.detach();
76   }
77 }
78 
main(int argc,char ** argv)79 int main(int argc, char** argv) {
80   if (argc != 2) {
81     PW_LOG_ERROR("Expected output file name as argument.\n");
82     return -1;
83   }
84 
85   // Enable tracing.
86   PW_TRACE_SET_ENABLED(true);
87 
88   // Dump trace data to the file passed in.
89   pw::trace::TraceToFile trace_to_file(pw::trace::GetCallbacks(), argv[1]);
90 
91   // Register platform callback
92   pw::trace::RegisterCallbackWhenCreated(pw::trace::GetCallbacks(),
93                                          TraceEventCallback);
94 
95   PW_LOG_INFO("Running threaded trace example...\n");
96   RunThreadedTraceSampleApp();
97 
98   // Sleep forever
99   while (true) {
100     std::this_thread::sleep_for(std::chrono::seconds(60));
101   }
102   return 0;
103 }
104