1a4e91f50Sopenharmony_ci#!/usr/bin/env python
2a4e91f50Sopenharmony_ci# -*- coding: utf-8 -*-
3a4e91f50Sopenharmony_ci# Copyright (C) 2021 Huawei Device Co., Ltd.
4a4e91f50Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
5a4e91f50Sopenharmony_ci# you may not use this file except in compliance with the License.
6a4e91f50Sopenharmony_ci# You may obtain a copy of the License at
7a4e91f50Sopenharmony_ci#
8a4e91f50Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
9a4e91f50Sopenharmony_ci#
10a4e91f50Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
11a4e91f50Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
12a4e91f50Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4e91f50Sopenharmony_ci# See the License for the specific language governing permissions and
14a4e91f50Sopenharmony_ci# limitations under the License.
15a4e91f50Sopenharmony_ci
16a4e91f50Sopenharmony_ciimport codecs
17a4e91f50Sopenharmony_ciimport sys
18a4e91f50Sopenharmony_ciimport os
19a4e91f50Sopenharmony_ciimport re
20a4e91f50Sopenharmony_ciimport time
21a4e91f50Sopenharmony_ci
22a4e91f50Sopenharmony_cifiles = []
23a4e91f50Sopenharmony_citrace_regex = "\s*(.*?)-(\d+?)\s+\(\s*(\d+?)\)\s+\[\d+\]\s+(.*?)\s+(.*?):\s+"
24a4e91f50Sopenharmony_ciall_traces_dict = {} # {"deviceName": [(timestamp, line) ...]}
25a4e91f50Sopenharmony_ciall_real_time_dict = {}
26a4e91f50Sopenharmony_cidefault_real_time = 7983849599000 # 2222-12-31 23:59:59
27a4e91f50Sopenharmony_ci
28a4e91f50Sopenharmony_cidef compare_timestamp(time1, time2):
29a4e91f50Sopenharmony_ci    return float(time1) < float(time2)
30a4e91f50Sopenharmony_ci
31a4e91f50Sopenharmony_cidef read_files(file, devices_name):
32a4e91f50Sopenharmony_ci    traces = []
33a4e91f50Sopenharmony_ci    with codecs.open(file, 'r', encoding='utf-8') as fp:
34a4e91f50Sopenharmony_ci        for line in fp:
35a4e91f50Sopenharmony_ci            if line.find("binder_transaction") > -1 \
36a4e91f50Sopenharmony_ci                or line.find("tracing_mark_write") > -1:
37a4e91f50Sopenharmony_ci                line = line.replace("\n", "")
38a4e91f50Sopenharmony_ci                trace_match = re.match(trace_regex, line)
39a4e91f50Sopenharmony_ci                if trace_match:
40a4e91f50Sopenharmony_ci                    traces.append((float(trace_match.group(5)), line))
41a4e91f50Sopenharmony_ci                if line.find("realtime_ts") > -1:
42a4e91f50Sopenharmony_ci                    time_regex = "{}{}".format(trace_regex, \
43a4e91f50Sopenharmony_ci                        "tracing_mark_write:\s+trace_event_clock_sync: realtime_ts=(.*)")
44a4e91f50Sopenharmony_ci                    time_match = re.match(time_regex, line)
45a4e91f50Sopenharmony_ci                    all_real_time_dict[devices_name] = { \
46a4e91f50Sopenharmony_ci                        "realtime_ts": int(time_match.group(6)), \
47a4e91f50Sopenharmony_ci                        "timestamp": float(time_match.group(5))}
48a4e91f50Sopenharmony_ci    if (not all_real_time_dict.__contains__(devices_name)) and traces:
49a4e91f50Sopenharmony_ci        line = traces[-1][1]
50a4e91f50Sopenharmony_ci        trace_match = re.match(trace_regex, line)
51a4e91f50Sopenharmony_ci        all_real_time_dict[devices_name] = { \
52a4e91f50Sopenharmony_ci            "realtime_ts": default_real_time, \
53a4e91f50Sopenharmony_ci            "timestamp": float(trace_match.group(5))}
54a4e91f50Sopenharmony_ci    return traces
55a4e91f50Sopenharmony_ci
56a4e91f50Sopenharmony_cidef handle_option():
57a4e91f50Sopenharmony_ci    if len(sys.argv) < 2:
58a4e91f50Sopenharmony_ci        print("eg: python bytrace_multi.py file1.ftrace file2.ftrace ...")
59a4e91f50Sopenharmony_ci        exit(0)
60a4e91f50Sopenharmony_ci    for i in range(len(sys.argv)):
61a4e91f50Sopenharmony_ci        if i == 0:
62a4e91f50Sopenharmony_ci            continue
63a4e91f50Sopenharmony_ci        if sys.argv[i] == "-h" or sys.argv[i] == "--help":
64a4e91f50Sopenharmony_ci            print("eg: python bytrace_multi.py file1.ftrace file2.ftrace ...")
65a4e91f50Sopenharmony_ci            exit(0)
66a4e91f50Sopenharmony_ci        elif not os.path.exists(sys.argv[i]):
67a4e91f50Sopenharmony_ci            print("Warning: {} is not found.".format(sys.argv[i]))
68a4e91f50Sopenharmony_ci        else:
69a4e91f50Sopenharmony_ci            files.append(sys.argv[i])
70a4e91f50Sopenharmony_ci
71a4e91f50Sopenharmony_cidef change_trace_time(all_trace_list, \
72a4e91f50Sopenharmony_ci                      base_real_time, \
73a4e91f50Sopenharmony_ci                      base_time_stamp, \
74a4e91f50Sopenharmony_ci                      target_device):
75a4e91f50Sopenharmony_ci    target_real_time = all_real_time_dict[target_device]["realtime_ts"]
76a4e91f50Sopenharmony_ci    target_time_stamp = all_real_time_dict[target_device]["timestamp"]
77a4e91f50Sopenharmony_ci    if not target_real_time == default_real_time:
78a4e91f50Sopenharmony_ci        diff_real_time = float(target_real_time - base_real_time) / 1000
79a4e91f50Sopenharmony_ci        target_time_stamp_ = base_time_stamp + diff_real_time
80a4e91f50Sopenharmony_ci        diff_time = target_time_stamp - target_time_stamp_
81a4e91f50Sopenharmony_ci    else:
82a4e91f50Sopenharmony_ci        # If the file does not have realtime, the difference is 0.5s.
83a4e91f50Sopenharmony_ci        diff_real_time = 0.5
84a4e91f50Sopenharmony_ci        target_time_stamp_ = base_time_stamp + diff_real_time
85a4e91f50Sopenharmony_ci        diff_time = target_time_stamp - target_time_stamp_
86a4e91f50Sopenharmony_ci    traces = all_traces_dict[target_device]
87a4e91f50Sopenharmony_ci    for mtuple in traces:
88a4e91f50Sopenharmony_ci        timestamp = float(mtuple[0])
89a4e91f50Sopenharmony_ci        line = mtuple[1]
90a4e91f50Sopenharmony_ci        timestamp_ = "{:.6f}".format(timestamp - diff_time)
91a4e91f50Sopenharmony_ci        line_ = target_device + \
92a4e91f50Sopenharmony_ci            line.replace("{:.6f}".format(timestamp), str(timestamp_))
93a4e91f50Sopenharmony_ci        all_trace_list.append((timestamp_, line_))
94a4e91f50Sopenharmony_ci
95a4e91f50Sopenharmony_cidef write_to_file(data, file_name):
96a4e91f50Sopenharmony_ci    with codecs.open(file_name, 'w+', encoding='utf-8') as fp:
97a4e91f50Sopenharmony_ci        fp.write("# tracer: nop\n")
98a4e91f50Sopenharmony_ci        fp.write("#\n")
99a4e91f50Sopenharmony_ci        fp.write("#                                      _-----=> irqs-off\n")
100a4e91f50Sopenharmony_ci        fp.write("#                                     / _----=> need-resched\n")
101a4e91f50Sopenharmony_ci        fp.write("#                                    | / _---=> hardirq/softirq\n")
102a4e91f50Sopenharmony_ci        fp.write("#                                    || / _--=> preempt-depth\n")
103a4e91f50Sopenharmony_ci        fp.write("#                                    ||| /     delay\n")
104a4e91f50Sopenharmony_ci        fp.write("#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION\n")
105a4e91f50Sopenharmony_ci        fp.write("#              | |        |      |   ||||       |         |\n")
106a4e91f50Sopenharmony_ci        for mtuple in data:
107a4e91f50Sopenharmony_ci            fp.write(mtuple[1])
108a4e91f50Sopenharmony_ci            fp.write("\n")
109a4e91f50Sopenharmony_ci
110a4e91f50Sopenharmony_cidef main():
111a4e91f50Sopenharmony_ci    handle_option()
112a4e91f50Sopenharmony_ci    if len(files) == 0:
113a4e91f50Sopenharmony_ci        exit(-1)
114a4e91f50Sopenharmony_ci
115a4e91f50Sopenharmony_ci    for i, val in enumerate(files):
116a4e91f50Sopenharmony_ci        device_name = "[device_{}]".format(str(i))
117a4e91f50Sopenharmony_ci        all_traces_dict[device_name] = read_files(val, device_name)
118a4e91f50Sopenharmony_ci
119a4e91f50Sopenharmony_ci    all_time_sorted_list = sorted(all_real_time_dict.items(), key=lambda \
120a4e91f50Sopenharmony_ci        all_real_time_dict: all_real_time_dict[1]["realtime_ts"])
121a4e91f50Sopenharmony_ci    base_real_time = all_time_sorted_list[0][1]["realtime_ts"]
122a4e91f50Sopenharmony_ci    base_time_stamp = all_time_sorted_list[0][1]["timestamp"]
123a4e91f50Sopenharmony_ci    all_trace_list = [] # [(timestamp, line)]
124a4e91f50Sopenharmony_ci    for mtuple in all_time_sorted_list:
125a4e91f50Sopenharmony_ci        target_device = mtuple[0]
126a4e91f50Sopenharmony_ci        change_trace_time(all_trace_list, \
127a4e91f50Sopenharmony_ci                          base_real_time, \
128a4e91f50Sopenharmony_ci                          base_time_stamp, \
129a4e91f50Sopenharmony_ci                          target_device)
130a4e91f50Sopenharmony_ci    # Sort by timestamp from small to large
131a4e91f50Sopenharmony_ci    all_trace_sorted_list = sorted(all_trace_list, key=lambda x: x[0])
132a4e91f50Sopenharmony_ci    curtime = time.strftime("%Y%m%d_%H%M%S", time.localtime())
133a4e91f50Sopenharmony_ci    write_to_file(all_trace_sorted_list, "multi_trace_{}.ftrace".format(str(curtime)))
134a4e91f50Sopenharmony_ci
135a4e91f50Sopenharmony_ciif __name__ == '__main__':
136a4e91f50Sopenharmony_ci    main()
137