1484543d1Sopenharmony_ci#!/usr/bin/env python3
2484543d1Sopenharmony_ci# -*- coding: UTF-8 -*-
3484543d1Sopenharmony_ci
4484543d1Sopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd.
5484543d1Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
6484543d1Sopenharmony_ci# you may not use this file except in compliance with the License.
7484543d1Sopenharmony_ci# You may obtain a copy of the License at
8484543d1Sopenharmony_ci#
9484543d1Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
10484543d1Sopenharmony_ci#
11484543d1Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
12484543d1Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
13484543d1Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14484543d1Sopenharmony_ci# See the License for the specific language governing permissions and
15484543d1Sopenharmony_ci# limitations under the License.
16484543d1Sopenharmony_ci
17484543d1Sopenharmony_ciimport os
18484543d1Sopenharmony_ciimport re
19484543d1Sopenharmony_ciimport argparse
20484543d1Sopenharmony_ciimport stat
21484543d1Sopenharmony_ciimport copy
22484543d1Sopenharmony_cifrom ffrt_trace_process import extract_process_id
23484543d1Sopenharmony_ci
24484543d1Sopenharmony_ci
25484543d1Sopenharmony_cidef extract_timestamp_str(log):
26484543d1Sopenharmony_ci    """
27484543d1Sopenharmony_ci    extract timestamp(us) from trace line
28484543d1Sopenharmony_ci    """
29484543d1Sopenharmony_ci    m = re.search(r" (\d+)\.(\d+): ", log)
30484543d1Sopenharmony_ci    if m is None:
31484543d1Sopenharmony_ci        return 0
32484543d1Sopenharmony_ci
33484543d1Sopenharmony_ci    match = m.group()
34484543d1Sopenharmony_ci
35484543d1Sopenharmony_ci    return match.strip()[:-1]
36484543d1Sopenharmony_ci
37484543d1Sopenharmony_ci
38484543d1Sopenharmony_cidef extract_cpu_id_str(log):
39484543d1Sopenharmony_ci    """
40484543d1Sopenharmony_ci    extract #cpu from trace line
41484543d1Sopenharmony_ci    """
42484543d1Sopenharmony_ci    m = re.search(r"\) \[.*\]", log)
43484543d1Sopenharmony_ci    if m is None:
44484543d1Sopenharmony_ci        return -1
45484543d1Sopenharmony_ci
46484543d1Sopenharmony_ci    match = m.group()
47484543d1Sopenharmony_ci
48484543d1Sopenharmony_ci    return match.split(']')[0].split('[')[-1]
49484543d1Sopenharmony_ci
50484543d1Sopenharmony_ci
51484543d1Sopenharmony_cidef make_costart_fake_log(mark, pid, label, gid, tid, tname, prio):
52484543d1Sopenharmony_ci    """
53484543d1Sopenharmony_ci    when ffrt task start running, make a fake log that sched_switch from ffrt thread -> ffrt task
54484543d1Sopenharmony_ci    """
55484543d1Sopenharmony_ci    timestamp = extract_timestamp_str(mark)
56484543d1Sopenharmony_ci    cpu_id = extract_cpu_id_str(mark)
57484543d1Sopenharmony_ci    fake_log = mark + "\n  %s-%d    (%7d) [%s] ....   %s: sched_switch: prev_comm=%s prev_pid=%d prev_prio=%d prev_state=S ==> next_comm=%s next_pid=%d0%d next_prio=%d\n" % (
58484543d1Sopenharmony_ci        tname, tid, pid, cpu_id, timestamp, tname, tid, prio, label, pid, gid, prio)
59484543d1Sopenharmony_ci
60484543d1Sopenharmony_ci    return fake_log
61484543d1Sopenharmony_ci
62484543d1Sopenharmony_ci
63484543d1Sopenharmony_cidef make_coyield_fake_log(mark, pid, label, gid, tid, tname, prio):
64484543d1Sopenharmony_ci    """
65484543d1Sopenharmony_ci    when ffrt task leave running, make a fake log that sched_switch from ffrt task -> ffrt thread
66484543d1Sopenharmony_ci    """
67484543d1Sopenharmony_ci    timestamp = extract_timestamp_str(mark)
68484543d1Sopenharmony_ci    cpu_id = extract_cpu_id_str(mark)
69484543d1Sopenharmony_ci    fake_log = "  %s-%d0%d    (%7d) [%s] ....   %s: sched_switch: prev_comm=%s prev_pid=%d0%d prev_prio=%d prev_state=S ==> next_comm=%s next_pid=%d next_prio=%d\n" % (
70484543d1Sopenharmony_ci        label, pid, gid, pid, cpu_id, timestamp, label, pid, gid, prio, tname, tid, prio)
71484543d1Sopenharmony_ci
72484543d1Sopenharmony_ci    if "|B|" in mark or "|H:B " in mark:
73484543d1Sopenharmony_ci        fake_log = "  %s-%d0%d    (%7d) [%s] ....   %s: tracing_mark_write: E|%d\n" % \
74484543d1Sopenharmony_ci                   (label, pid, gid, pid, cpu_id, timestamp, pid) + fake_log
75484543d1Sopenharmony_ci
76484543d1Sopenharmony_ci    return fake_log
77484543d1Sopenharmony_ci
78484543d1Sopenharmony_ci
79484543d1Sopenharmony_cidef replace_sched_switch_log(fake_log, mark, pid, label, gid, tid):
80484543d1Sopenharmony_ci    """
81484543d1Sopenharmony_ci    replace ffrt worker sched_swtich log with ffrt task
82484543d1Sopenharmony_ci    """
83484543d1Sopenharmony_ci    if "prev_pid=%d" % tid in mark:
84484543d1Sopenharmony_ci        index = re.search("\(.+\)\s+\[\d", fake_log).span()[0]
85484543d1Sopenharmony_ci        fake_log = "  %s-%d0%d " % (label, pid, gid) + fake_log[index:]
86484543d1Sopenharmony_ci        fake_log = fake_log[:fake_log.index("prev_comm=")] + "prev_comm=%s " % label + \
87484543d1Sopenharmony_ci                   fake_log[fake_log.index("prev_pid="):]
88484543d1Sopenharmony_ci        fake_log = fake_log[:fake_log.index("prev_pid=")] + "prev_pid=%d0%d " % (pid, gid) + \
89484543d1Sopenharmony_ci                   fake_log[fake_log.index("prev_prio="):]
90484543d1Sopenharmony_ci    elif "next_pid=%d" % tid in mark:
91484543d1Sopenharmony_ci        fake_log = fake_log[:fake_log.index("next_comm=")] + "next_comm=%s " % label + \
92484543d1Sopenharmony_ci                   fake_log[fake_log.index("next_pid="):]
93484543d1Sopenharmony_ci        fake_log = fake_log[:fake_log.index("next_pid=")] + "next_pid=%d0%d " % (pid, gid) + \
94484543d1Sopenharmony_ci                   fake_log[fake_log.index("next_prio="):]
95484543d1Sopenharmony_ci
96484543d1Sopenharmony_ci    return fake_log
97484543d1Sopenharmony_ci
98484543d1Sopenharmony_ci
99484543d1Sopenharmony_cidef replace_sched_wake_log(fake_log, label, pid, gid):
100484543d1Sopenharmony_ci    """
101484543d1Sopenharmony_ci    replace ffrt worker sched_wake log with ffrt task
102484543d1Sopenharmony_ci    """
103484543d1Sopenharmony_ci    fake_log = fake_log[:fake_log.index("comm=")] + "comm=%s " % label + fake_log[fake_log.index("pid="):]
104484543d1Sopenharmony_ci    fake_log = fake_log[:fake_log.index("pid=")] + "pid=%d0%d " % (pid, gid) + fake_log[fake_log.index("prio="):]
105484543d1Sopenharmony_ci
106484543d1Sopenharmony_ci    return fake_log
107484543d1Sopenharmony_ci
108484543d1Sopenharmony_ci
109484543d1Sopenharmony_cidef replace_sched_block_log(fake_log, pid, gid):
110484543d1Sopenharmony_ci    """
111484543d1Sopenharmony_ci    replace ffrt worker sched_block log with ffrt task
112484543d1Sopenharmony_ci    """
113484543d1Sopenharmony_ci    fake_log = fake_log[:fake_log.index("pid=")] + "pid=%d0%d " % (pid, gid) + fake_log[fake_log.index("iowait="):]
114484543d1Sopenharmony_ci
115484543d1Sopenharmony_ci    return fake_log
116484543d1Sopenharmony_ci
117484543d1Sopenharmony_ci
118484543d1Sopenharmony_cidef replace_tracing_mark_log(fake_log, label, pid, gid):
119484543d1Sopenharmony_ci    """
120484543d1Sopenharmony_ci    replace ffrt worker normal tracing log with ffrt task
121484543d1Sopenharmony_ci    """
122484543d1Sopenharmony_ci    index = re.search("\(.+\)\s+\[\d", fake_log).span()[0]
123484543d1Sopenharmony_ci    fake_log = "  %s-%d0%d " % (label, pid, gid) + fake_log[index:]
124484543d1Sopenharmony_ci
125484543d1Sopenharmony_ci    return fake_log
126484543d1Sopenharmony_ci
127484543d1Sopenharmony_ci
128484543d1Sopenharmony_cidef convert_worker_log_to_task(mark, pid, label, gid, tid):
129484543d1Sopenharmony_ci    """
130484543d1Sopenharmony_ci    convert ffrt worker trace logs to ffrt task trace logs
131484543d1Sopenharmony_ci    """
132484543d1Sopenharmony_ci    fake_log = mark
133484543d1Sopenharmony_ci
134484543d1Sopenharmony_ci    if "sched_switch: " in mark:
135484543d1Sopenharmony_ci        return replace_sched_switch_log(fake_log, mark, pid, label, gid, tid)
136484543d1Sopenharmony_ci
137484543d1Sopenharmony_ci    if ": sched_wak" in mark:
138484543d1Sopenharmony_ci        return replace_sched_wake_log(fake_log, label, pid, gid)
139484543d1Sopenharmony_ci
140484543d1Sopenharmony_ci    if "sched_blocked_reason: " in mark:
141484543d1Sopenharmony_ci        return replace_sched_block_log(fake_log, pid, gid)
142484543d1Sopenharmony_ci
143484543d1Sopenharmony_ci    return replace_tracing_mark_log(fake_log, label, pid, gid)
144484543d1Sopenharmony_ci
145484543d1Sopenharmony_ci
146484543d1Sopenharmony_cidef find_ffrt_process_and_classify_logs(log, lineno, trace_map, ffrt_pids):
147484543d1Sopenharmony_ci    """
148484543d1Sopenharmony_ci    find ffrt related process and threads (ffrtwk/ffrt_io), and classify logs for threads
149484543d1Sopenharmony_ci    """
150484543d1Sopenharmony_ci    if "prev_comm=ffrt" in log:
151484543d1Sopenharmony_ci        pid = extract_process_id(log)
152484543d1Sopenharmony_ci        if pid not in ffrt_pids.keys():
153484543d1Sopenharmony_ci            ffrt_pids[pid] = {}
154484543d1Sopenharmony_ci        tname = log[log.index("prev_comm="):].split("prev_pid=")[0].split('=')[-1].rstrip()
155484543d1Sopenharmony_ci        tid = int(log[log.index("prev_pid="):].split(' ')[0].split('=')[-1])
156484543d1Sopenharmony_ci        if tid not in ffrt_pids[pid].keys():
157484543d1Sopenharmony_ci            ffrt_pids[pid][tid] = {"name": tname, "logs": []}
158484543d1Sopenharmony_ci
159484543d1Sopenharmony_ci    if "sched_switch: " in log:
160484543d1Sopenharmony_ci        prev_tid = int(log[log.index("prev_pid="):].split(' ')[0].split('=')[-1])
161484543d1Sopenharmony_ci        next_tid = int(log[log.index("next_pid="):].split(' ')[0].split('=')[-1])
162484543d1Sopenharmony_ci        if prev_tid not in trace_map.keys():
163484543d1Sopenharmony_ci            trace_map[prev_tid] = []
164484543d1Sopenharmony_ci        trace_map[prev_tid].append(lineno)
165484543d1Sopenharmony_ci        if next_tid not in trace_map.keys():
166484543d1Sopenharmony_ci            trace_map[next_tid] = []
167484543d1Sopenharmony_ci        trace_map[next_tid].append(lineno)
168484543d1Sopenharmony_ci        return
169484543d1Sopenharmony_ci
170484543d1Sopenharmony_ci    if ": sched_wak" in log or "sched_blocked_reason: " in log:
171484543d1Sopenharmony_ci        tid = int(log[log.index("pid="):].split(' ')[0].split('=')[-1])
172484543d1Sopenharmony_ci        if tid not in trace_map.keys():
173484543d1Sopenharmony_ci            trace_map[tid] = []
174484543d1Sopenharmony_ci        trace_map[tid].append(lineno)
175484543d1Sopenharmony_ci        return
176484543d1Sopenharmony_ci
177484543d1Sopenharmony_ci    match = re.search(" \(.+\)\s+\[\d", log)
178484543d1Sopenharmony_ci    if match is not None:
179484543d1Sopenharmony_ci        tid = int(log[:match.span()[0]].split('-')[-1])
180484543d1Sopenharmony_ci        if tid not in trace_map.keys():
181484543d1Sopenharmony_ci            trace_map[tid] = []
182484543d1Sopenharmony_ci        trace_map[tid].append(lineno)
183484543d1Sopenharmony_ci
184484543d1Sopenharmony_ci    return
185484543d1Sopenharmony_ci
186484543d1Sopenharmony_ci
187484543d1Sopenharmony_cidef classify_logs_for_ffrt_worker(logs):
188484543d1Sopenharmony_ci    """
189484543d1Sopenharmony_ci    split traces that written in the same line and classify logs based on ffrt worker
190484543d1Sopenharmony_ci    """
191484543d1Sopenharmony_ci    trace_map = {}
192484543d1Sopenharmony_ci    ffrt_pids = {}
193484543d1Sopenharmony_ci
194484543d1Sopenharmony_ci    lineno = 0
195484543d1Sopenharmony_ci    while lineno < len(logs):
196484543d1Sopenharmony_ci        log = logs[lineno]
197484543d1Sopenharmony_ci
198484543d1Sopenharmony_ci        indexs = [m.span()[0] for m in re.finditer("\S+-\d+\s+\(", log)]
199484543d1Sopenharmony_ci
200484543d1Sopenharmony_ci        if len(indexs) > 1:
201484543d1Sopenharmony_ci            del logs[lineno]
202484543d1Sopenharmony_ci            for j in range(len(indexs)):
203484543d1Sopenharmony_ci                begin = indexs[j]
204484543d1Sopenharmony_ci                end = indexs[j + 1] if j + 1 < len(indexs) else len(log)
205484543d1Sopenharmony_ci                log_split = log[begin:end]
206484543d1Sopenharmony_ci                if j + 1 < len(indexs):
207484543d1Sopenharmony_ci                    log_split = "%s\n" % log_split
208484543d1Sopenharmony_ci                logs.insert(lineno + j, log_split)
209484543d1Sopenharmony_ci
210484543d1Sopenharmony_ci                find_ffrt_process_and_classify_logs(logs[lineno + j], lineno + j, trace_map, ffrt_pids)
211484543d1Sopenharmony_ci                if "<faulted>" in logs[lineno + j]:
212484543d1Sopenharmony_ci                    pid = extract_process_id(logs[lineno + j])
213484543d1Sopenharmony_ci                    logs[lineno + j] = logs[lineno + j][:logs[lineno + j].index("<faulted>")] + "E|%d\n" % pid
214484543d1Sopenharmony_ci
215484543d1Sopenharmony_ci            lineno += len(indexs) - 1
216484543d1Sopenharmony_ci        else:
217484543d1Sopenharmony_ci            find_ffrt_process_and_classify_logs(logs[lineno], lineno, trace_map, ffrt_pids)
218484543d1Sopenharmony_ci            if "<faulted>" in logs[lineno]:
219484543d1Sopenharmony_ci                pid = extract_process_id(logs[lineno])
220484543d1Sopenharmony_ci                logs[lineno] = logs[lineno][:logs[lineno].index("<faulted>")] + "E|%d\n" % pid
221484543d1Sopenharmony_ci
222484543d1Sopenharmony_ci        lineno += 1
223484543d1Sopenharmony_ci
224484543d1Sopenharmony_ci    for pid, tids in ffrt_pids.items():
225484543d1Sopenharmony_ci        for tid in tids.keys():
226484543d1Sopenharmony_ci            ffrt_pids[pid][tid]["logs"] = trace_map[tid]
227484543d1Sopenharmony_ci
228484543d1Sopenharmony_ci    return ffrt_pids
229484543d1Sopenharmony_ci
230484543d1Sopenharmony_ci
231484543d1Sopenharmony_cidef convert_ffrt_thread_to_ffrt_task(logs, ffrt_pids):
232484543d1Sopenharmony_ci    """
233484543d1Sopenharmony_ci    convert tracing mark of ffrt worker to ffrt task
234484543d1Sopenharmony_ci    """
235484543d1Sopenharmony_ci    task_labels = {}
236484543d1Sopenharmony_ci
237484543d1Sopenharmony_ci    for pid, tids in ffrt_pids.items():
238484543d1Sopenharmony_ci        task_labels[pid] = {}
239484543d1Sopenharmony_ci        for tid, info in ffrt_pids[pid].items():
240484543d1Sopenharmony_ci            tname = info["name"]
241484543d1Sopenharmony_ci            linenos = info["logs"]
242484543d1Sopenharmony_ci            prio = 120
243484543d1Sopenharmony_ci
244484543d1Sopenharmony_ci            switch_in_fake_log = False
245484543d1Sopenharmony_ci            switch_out_fake_log = False
246484543d1Sopenharmony_ci            ffbk_mark_remove = False
247484543d1Sopenharmony_ci            task_running = None
248484543d1Sopenharmony_ci            for lineno in linenos:
249484543d1Sopenharmony_ci                mark = logs[lineno]
250484543d1Sopenharmony_ci
251484543d1Sopenharmony_ci                if "sched_switch: " in mark:
252484543d1Sopenharmony_ci                    if "prev_pid=%d" % tid in mark:
253484543d1Sopenharmony_ci                        prio = int(mark[mark.index("prev_prio="):].split(' ')[0].split('=')[-1])
254484543d1Sopenharmony_ci                    elif "next_pid=%d" % tid in mark:
255484543d1Sopenharmony_ci                        prio = int(mark[mark.index("next_prio="):].split(' ')[0].split('=')[-1])
256484543d1Sopenharmony_ci
257484543d1Sopenharmony_ci                # FFRT Task Running
258484543d1Sopenharmony_ci                if "FFRT::[" in mark:
259484543d1Sopenharmony_ci                    miss_log = None
260484543d1Sopenharmony_ci                    if task_running is not None:  # trace end missing
261484543d1Sopenharmony_ci                        miss_log = make_coyield_fake_log(mark, pid, task_labels[pid][task_running], task_running,
262484543d1Sopenharmony_ci                                                         tid, tname, prio)
263484543d1Sopenharmony_ci                        timestamp = extract_timestamp_str(mark)
264484543d1Sopenharmony_ci                        cpu_id = extract_cpu_id_str(mark)
265484543d1Sopenharmony_ci                        miss_log += "  %s-%d    (%7d) [%s] ....   %s: tracing_mark_write: E|%d\n" % (
266484543d1Sopenharmony_ci                                        tname, tid, pid, cpu_id, timestamp, pid)
267484543d1Sopenharmony_ci
268484543d1Sopenharmony_ci                    label = mark.split('[')[-1].split(']')[0]
269484543d1Sopenharmony_ci                    try:
270484543d1Sopenharmony_ci                        gid = int(mark.split('|')[-1])
271484543d1Sopenharmony_ci                    except ValueError:
272484543d1Sopenharmony_ci                        continue
273484543d1Sopenharmony_ci                    if gid not in task_labels[pid].keys():
274484543d1Sopenharmony_ci                        task_labels[pid][gid] = label
275484543d1Sopenharmony_ci
276484543d1Sopenharmony_ci                    task_running = gid
277484543d1Sopenharmony_ci                    fake_log = make_costart_fake_log(mark, pid, task_labels[pid][task_running], task_running,
278484543d1Sopenharmony_ci                                                     tid, tname, prio)
279484543d1Sopenharmony_ci                    logs[lineno] = fake_log
280484543d1Sopenharmony_ci
281484543d1Sopenharmony_ci                    if miss_log is not None:
282484543d1Sopenharmony_ci                        logs[lineno] = miss_log + logs[lineno]
283484543d1Sopenharmony_ci
284484543d1Sopenharmony_ci                    switch_in_fake_log = True
285484543d1Sopenharmony_ci                    continue
286484543d1Sopenharmony_ci
287484543d1Sopenharmony_ci                if task_running is not None:
288484543d1Sopenharmony_ci                    # Remove FFRT Supplemented Log for CoSwitch
289484543d1Sopenharmony_ci                    if re.search(r" F\|(\d+)\|Co\|(\d+)", mark) is not None or \
290484543d1Sopenharmony_ci                            re.search(r" F\|(\d+)\|H:Co\s(\d+)", mark) is not None:
291484543d1Sopenharmony_ci                        logs[lineno] = "\n"
292484543d1Sopenharmony_ci                        if switch_in_fake_log is True:
293484543d1Sopenharmony_ci                            switch_in_fake_log = False
294484543d1Sopenharmony_ci                            continue
295484543d1Sopenharmony_ci                        else:
296484543d1Sopenharmony_ci                            switch_out_fake_log = True
297484543d1Sopenharmony_ci                            continue
298484543d1Sopenharmony_ci                    if switch_in_fake_log is True and "tracing_mark_write: B" in mark:
299484543d1Sopenharmony_ci                        logs[lineno] = "\n"
300484543d1Sopenharmony_ci                        continue
301484543d1Sopenharmony_ci                    if switch_out_fake_log is True and "tracing_mark_write: E" in mark:
302484543d1Sopenharmony_ci                        logs[lineno] = "\n"
303484543d1Sopenharmony_ci                        continue
304484543d1Sopenharmony_ci
305484543d1Sopenharmony_ci                    # FFRT Task Blocked/Finished Marks
306484543d1Sopenharmony_ci                    if re.search(r" F\|(\d+)\|[BF]\|(\d+)", mark) is not None or \
307484543d1Sopenharmony_ci                            re.search(r" F\|(\d+)\|H:[BF]\s(\d+)", mark) is not None:
308484543d1Sopenharmony_ci                        fake_log = make_coyield_fake_log(mark, pid, task_labels[pid][task_running], task_running,
309484543d1Sopenharmony_ci                                                         tid, tname, prio)
310484543d1Sopenharmony_ci                        logs[lineno] = fake_log
311484543d1Sopenharmony_ci                        task_running = None
312484543d1Sopenharmony_ci
313484543d1Sopenharmony_ci                        if switch_out_fake_log is True:
314484543d1Sopenharmony_ci                            switch_out_fake_log = False
315484543d1Sopenharmony_ci
316484543d1Sopenharmony_ci                        continue
317484543d1Sopenharmony_ci
318484543d1Sopenharmony_ci                    if ffbk_mark_remove is True and "tracing_mark_write: E" in mark:
319484543d1Sopenharmony_ci                        logs[lineno] = "\n"
320484543d1Sopenharmony_ci                        ffbk_mark_remove = False
321484543d1Sopenharmony_ci                        continue
322484543d1Sopenharmony_ci
323484543d1Sopenharmony_ci                    fake_log = convert_worker_log_to_task(mark, pid, task_labels[pid][task_running], task_running,
324484543d1Sopenharmony_ci                                                          tid)
325484543d1Sopenharmony_ci
326484543d1Sopenharmony_ci                    # FFRT Blocked Reason
327484543d1Sopenharmony_ci                    if "FFBK[" in fake_log:
328484543d1Sopenharmony_ci                        if "[dep]" in fake_log:
329484543d1Sopenharmony_ci                            fake_log = "\n"
330484543d1Sopenharmony_ci                        elif "[chd]" in fake_log:
331484543d1Sopenharmony_ci                            fake_log = "%sFFBK[wait_child]%s" % (
332484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 9:])
333484543d1Sopenharmony_ci                        elif "[dat]" in fake_log:
334484543d1Sopenharmony_ci                            fake_log = "%sFFBK[wait_data]%s" % (
335484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 9:])
336484543d1Sopenharmony_ci                        elif "[fd]" in fake_log:
337484543d1Sopenharmony_ci                            fake_log = "%sFFBK[wait_fd]%s" % (
338484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 8:])
339484543d1Sopenharmony_ci                        elif "[mtx]" in fake_log:
340484543d1Sopenharmony_ci                            fake_log = "%sFFBK[mutex]%s" % (
341484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 9:])
342484543d1Sopenharmony_ci                        elif "[slp]" in fake_log:
343484543d1Sopenharmony_ci                            fake_log = "%sFFBK[sleep]%s" % (
344484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 9:])
345484543d1Sopenharmony_ci                        elif "[yld]" in fake_log:
346484543d1Sopenharmony_ci                            fake_log = "%sFFBK[yield]%s" % (
347484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 9:])
348484543d1Sopenharmony_ci                        elif "[cnd]" in fake_log:
349484543d1Sopenharmony_ci                            fake_log = "%sFFBK[cond_wait]%s" % (
350484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 9:])
351484543d1Sopenharmony_ci                        elif "[cnt]" in fake_log:
352484543d1Sopenharmony_ci                            fake_log = "%sFFBK[cond_timedwait]%s" % (
353484543d1Sopenharmony_ci                                fake_log[:fake_log.index("FFBK[")], fake_log[fake_log.index("FFBK[") + 9:])
354484543d1Sopenharmony_ci
355484543d1Sopenharmony_ci                        ffbk_mark_remove = True
356484543d1Sopenharmony_ci
357484543d1Sopenharmony_ci                    logs[lineno] = fake_log
358484543d1Sopenharmony_ci                    continue
359484543d1Sopenharmony_ci
360484543d1Sopenharmony_ci    return
361484543d1Sopenharmony_ci
362484543d1Sopenharmony_ci
363484543d1Sopenharmony_cidef supplement_ffrt_block_and_wake_info(logs):
364484543d1Sopenharmony_ci    """
365484543d1Sopenharmony_ci    supplement ffrt block slice and link ffrt wake with ffrt block
366484543d1Sopenharmony_ci    """
367484543d1Sopenharmony_ci    task_labels = {}
368484543d1Sopenharmony_ci
369484543d1Sopenharmony_ci    for lineno in range(len(logs)):
370484543d1Sopenharmony_ci        log = logs[lineno]
371484543d1Sopenharmony_ci
372484543d1Sopenharmony_ci        if "FFBK[" in log:
373484543d1Sopenharmony_ci            pid = extract_process_id(log)
374484543d1Sopenharmony_ci            gid = int(log.split('|')[-1])
375484543d1Sopenharmony_ci
376484543d1Sopenharmony_ci            if pid not in task_labels.keys():
377484543d1Sopenharmony_ci                task_labels[pid] = {}
378484543d1Sopenharmony_ci            if gid not in task_labels[pid].keys():
379484543d1Sopenharmony_ci                task_labels[pid][gid] = {
380484543d1Sopenharmony_ci                    "state": "none",
381484543d1Sopenharmony_ci                    "prev_wake_lineno": None,
382484543d1Sopenharmony_ci                    "prev_wake_log": None,
383484543d1Sopenharmony_ci                }
384484543d1Sopenharmony_ci
385484543d1Sopenharmony_ci            ready_end_log = None
386484543d1Sopenharmony_ci            if task_labels[pid][gid]["state"] == "ready":  # abnormal scene: ready -> block, running missed
387484543d1Sopenharmony_ci                timestamp = extract_timestamp_str(log)
388484543d1Sopenharmony_ci                cpu_id = extract_cpu_id_str(log)
389484543d1Sopenharmony_ci                ready_end_log = "  <...>-%d0%d    (%7d) [%s] ....   %s: tracing_mark_write: E|%d\n" % (
390484543d1Sopenharmony_ci                    pid, gid, pid, cpu_id, timestamp, pid)
391484543d1Sopenharmony_ci
392484543d1Sopenharmony_ci            task_labels[pid][gid]["state"] = "block"
393484543d1Sopenharmony_ci
394484543d1Sopenharmony_ci            logs[lineno] = "%s\n" % logs[lineno][:logs[lineno].rfind('|')]
395484543d1Sopenharmony_ci
396484543d1Sopenharmony_ci            if ready_end_log is not None:
397484543d1Sopenharmony_ci                logs[lineno] = ready_end_log + logs[lineno]
398484543d1Sopenharmony_ci
399484543d1Sopenharmony_ci            continue
400484543d1Sopenharmony_ci
401484543d1Sopenharmony_ci        if "FFWK|" in log:
402484543d1Sopenharmony_ci            pid = extract_process_id(log)
403484543d1Sopenharmony_ci            gid = int(log.split('|')[-1])
404484543d1Sopenharmony_ci
405484543d1Sopenharmony_ci            if pid in task_labels.keys() and gid in task_labels[pid].keys():
406484543d1Sopenharmony_ci                timestamp = extract_timestamp_str(log)
407484543d1Sopenharmony_ci                cpu_id = extract_cpu_id_str(log)
408484543d1Sopenharmony_ci                if "H:FFWK" in log:
409484543d1Sopenharmony_ci                    ready_begin_log = "  <...>-%d0%d    (%7d) [%s] ....   %s: tracing_mark_write: B|%d|H:FFREADY\n" % (
410484543d1Sopenharmony_ci                        pid, gid, pid, cpu_id, timestamp, pid)
411484543d1Sopenharmony_ci                else:
412484543d1Sopenharmony_ci                    ready_begin_log = "  <...>-%d0%d    (%7d) [%s] ....   %s: tracing_mark_write: B|%d|FFREADY\n" % (
413484543d1Sopenharmony_ci                        pid, gid, pid, cpu_id, timestamp, pid)
414484543d1Sopenharmony_ci                logs[lineno] = ready_begin_log + logs[lineno]
415484543d1Sopenharmony_ci
416484543d1Sopenharmony_ci                if task_labels[pid][gid]["state"] == "ready":  # abnormal scene: ready -> ready, running & block missed
417484543d1Sopenharmony_ci                    logs[task_labels[pid][gid]["prev_wake_lineno"]] = logs[task_labels[pid][gid]["prev_wake_lineno"]][
418484543d1Sopenharmony_ci                                                                      logs[task_labels[pid][gid][
419484543d1Sopenharmony_ci                                                                          "prev_wake_lineno"]].index("FFREADY") + 8:]
420484543d1Sopenharmony_ci
421484543d1Sopenharmony_ci                task_labels[pid][gid]["state"] = "ready"
422484543d1Sopenharmony_ci                task_labels[pid][gid]["prev_wake_log"] = copy.copy(log)
423484543d1Sopenharmony_ci                task_labels[pid][gid]["prev_wake_lineno"] = lineno
424484543d1Sopenharmony_ci
425484543d1Sopenharmony_ci            continue
426484543d1Sopenharmony_ci
427484543d1Sopenharmony_ci        if "FFRT::[" in log:
428484543d1Sopenharmony_ci            pid = extract_process_id(log)
429484543d1Sopenharmony_ci            try:
430484543d1Sopenharmony_ci                gid = int([e for e in log.split('\n') if "FFRT::[" in e][0].split('|')[-1])
431484543d1Sopenharmony_ci            except ValueError:
432484543d1Sopenharmony_ci                continue
433484543d1Sopenharmony_ci
434484543d1Sopenharmony_ci            if pid in task_labels.keys() and gid in task_labels[pid].keys():
435484543d1Sopenharmony_ci                if task_labels[pid][gid]["state"] == "ready":
436484543d1Sopenharmony_ci                    timestamp = extract_timestamp_str(log)
437484543d1Sopenharmony_ci                    cpu_id = extract_cpu_id_str(log)
438484543d1Sopenharmony_ci
439484543d1Sopenharmony_ci                    switch_log = log.split('\n')[-2]
440484543d1Sopenharmony_ci                    task_comm = switch_log[switch_log.index("next_comm="):].split("next_pid=")[0].split('=')[
441484543d1Sopenharmony_ci                        -1].rstrip()
442484543d1Sopenharmony_ci                    task_pid = int(switch_log[switch_log.index("next_pid="):].split(' ')[0].split('=')[-1])
443484543d1Sopenharmony_ci                    task_prio = int(switch_log[switch_log.index("next_prio="):].split('=')[-1])
444484543d1Sopenharmony_ci                    cpu_id_wake = extract_cpu_id_str(switch_log)
445484543d1Sopenharmony_ci                    waking_log = task_labels[pid][gid]["prev_wake_log"][:task_labels[pid][gid]["prev_wake_log"].index(
446484543d1Sopenharmony_ci                        "tracing_mark_write:")] + "sched_waking: comm=%s pid=%d prio=%d target_cpu=%s\n" % (
447484543d1Sopenharmony_ci                                 task_comm, task_pid, task_prio, cpu_id_wake)
448484543d1Sopenharmony_ci                    wakeup_log = task_labels[pid][gid]["prev_wake_log"][
449484543d1Sopenharmony_ci                                 :task_labels[pid][gid]["prev_wake_log"].index("tracing_mark_write:")] + \
450484543d1Sopenharmony_ci                                 "sched_wakeup: comm=%s pid=%d prio=%d target_cpu=%s\n" % (
451484543d1Sopenharmony_ci                                 task_comm, task_pid, task_prio, cpu_id_wake)
452484543d1Sopenharmony_ci                    logs[task_labels[pid][gid]["prev_wake_lineno"]] += waking_log + wakeup_log
453484543d1Sopenharmony_ci
454484543d1Sopenharmony_ci                    ready_end_log = "  <...>-%d0%d    (%7d) [%s] ....   %s: tracing_mark_write: E|%d\n" % (
455484543d1Sopenharmony_ci                        pid, gid, pid, cpu_id, timestamp, pid)
456484543d1Sopenharmony_ci                    logs[lineno] = ready_end_log + logs[lineno]
457484543d1Sopenharmony_ci
458484543d1Sopenharmony_ci                    task_labels[pid][gid]["state"] = "none"
459484543d1Sopenharmony_ci
460484543d1Sopenharmony_ci            continue
461484543d1Sopenharmony_ci
462484543d1Sopenharmony_ci    return
463484543d1Sopenharmony_ci
464484543d1Sopenharmony_ci
465484543d1Sopenharmony_cidef trace_recover(file):
466484543d1Sopenharmony_ci    with open(file, 'r', encoding="gb18030", errors="ignore") as infile:
467484543d1Sopenharmony_ci        logs = infile.readlines()
468484543d1Sopenharmony_ci
469484543d1Sopenharmony_ci        ffrt_pids = classify_logs_for_ffrt_worker(logs)
470484543d1Sopenharmony_ci
471484543d1Sopenharmony_ci        convert_ffrt_thread_to_ffrt_task(logs, ffrt_pids)
472484543d1Sopenharmony_ci
473484543d1Sopenharmony_ci        supplement_ffrt_block_and_wake_info(logs)
474484543d1Sopenharmony_ci
475484543d1Sopenharmony_ci        file_name, file_ext = os.path.splitext(file)[0], os.path.splitext(file)[1]
476484543d1Sopenharmony_ci
477484543d1Sopenharmony_ci        with os.fdopen(os.open("%s_ffrt_recover%s" % (file_name, file_ext), os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
478484543d1Sopenharmony_ci                    stat.S_IWUSR | stat.S_IRUSR), 'w', encoding="gb18030", errors="ignore") as outfile:
479484543d1Sopenharmony_ci            outfile.writelines(logs)
480484543d1Sopenharmony_ci            outfile.close()
481484543d1Sopenharmony_ci
482484543d1Sopenharmony_ci        infile.close()
483484543d1Sopenharmony_ci
484484543d1Sopenharmony_ci    return
485484543d1Sopenharmony_ci
486484543d1Sopenharmony_ci
487484543d1Sopenharmony_cidef main():
488484543d1Sopenharmony_ci    parser = argparse.ArgumentParser(description="parse")
489484543d1Sopenharmony_ci    parser.add_argument('--file', '-f', type=str, required=True, help="input trace file path")
490484543d1Sopenharmony_ci
491484543d1Sopenharmony_ci    args = parser.parse_args()
492484543d1Sopenharmony_ci
493484543d1Sopenharmony_ci    if not os.path.isfile(args.file):
494484543d1Sopenharmony_ci        exit(1)
495484543d1Sopenharmony_ci
496484543d1Sopenharmony_ci    trace_recover(args.file)
497484543d1Sopenharmony_ci
498484543d1Sopenharmony_ci    return
499484543d1Sopenharmony_ci
500484543d1Sopenharmony_ci
501484543d1Sopenharmony_ciif __name__ == "__main__":
502484543d1Sopenharmony_ci    main()