emdbg.analyze.backtrace
1# Copyright (c) 2023, Auterion AG 2# SPDX-License-Identifier: BSD-3-Clause 3 4from __future__ import annotations 5import re 6from pathlib import Path 7from .priority import _BoostOperation 8 9class Frame: 10 """ 11 Parses a GDB frame of a `backtrace` or `px4_backtrace` command. 12 """ 13 def __init__(self, description: str): 14 """ 15 :param description: A single line of the backtrace command starting with a `#` 16 """ 17 self.is_valid = False 18 self.description = description 19 if match := re.match(r"#(\d+) +(?:0x.+? in )?(.+)\((.*?)\) at (.+?):(\d+)", description): 20 self.index = int(match.group(1)) 21 self.function_name = match.group(2) 22 self.args = match.group(3) 23 self.filename = match.group(4) 24 self.line = match.group(5) 25 self.is_valid = True 26 self.function = f"{self.function_name}({self.args})" 27 self.location = f"{Path(self.filename).relative_to(Path().cwd())}:{self.line}" 28 self._unique_location = self.function + "\n" + self.location 29 30 def __hash__(self) -> int: 31 return hash(self._node) 32 33 def __eq__(self, other) -> int: 34 return self.function == other.function and self.filename == other.filename 35 36 def __repr__(self) -> str: 37 return self.function 38 39 def __str__(self) -> str: 40 return f"#{self.index:<2} {self.function}" 41 42 43class Backtrace: 44 """ 45 Holds the entire call chain of a `backtrace` or `px4_backtrace` command. 46 """ 47 EDGES = {} 48 COLORS = {} 49 50 def __init__(self, description: str): 51 """ 52 :param description: All lines of the backtrace command 53 """ 54 self.description = description 55 tasks = (re.match(r"Task=(.+)", d) for d in description.splitlines()) 56 tasks = [t.group(1) for t in tasks if t is not None] 57 self.task = tasks[0] if tasks else None 58 self.type = self.task 59 60 frames = (Frame(d) for d in description.splitlines()) 61 self.frames = [f for f in frames if f.is_valid] 62 self.is_valid = len(self.frames) 63 if self.is_valid: 64 funcs = {f.function for f in self.frames} 65 for name, pattern in self.EDGES.items(): 66 if any(re.search(pattern, f) for f in funcs): 67 self.type = name 68 break 69 70 def __hash__(self) -> int: 71 return hash("".join(f.filename + f.function for f in self.frames)) 72 73 def __eq__(self, other) -> int: 74 ours = "".join(f.filename + f.function for f in self.frames) 75 others = "".join(f.filename + f.function for f in other.frames) 76 return ours == others 77 78 def __repr__(self) -> str: 79 return str(self.frames) 80 81# ----------------------------------------------------------------------------- 82def _fill(color): 83 return {"style": "filled", "fillcolor": color} 84 85def _bfill(color): 86 return {"style": "bold,filled", "fillcolor": color} 87 88 89class FileSystemBacktrace(Backtrace): 90 EDGES = dict( 91 READ = r"^read$", 92 WRITE = r"^write$", 93 FSYNC = r"^fsync$", 94 UNLINK = r"^unlink$", 95 LSEEK = r"^lseek$", 96 OPEN = r"^open$", 97 CLOSE = r"^close$", 98 READDIR = r"^readdir$", 99 OPENDIR = r"^opendir$", 100 MOUNT = r"^mount$", 101 MKDIR = r"^mkdir$", 102 STAT = r"^stat$", 103 IRQ = r"^stm32_sdmmc_interrupt$", 104 INIT = r"^stm32_sdio_initialize$", 105 ) 106 COLORS = {**{"^fat_.*$": _fill("LightYellow"), 107 "^mmc?sd_.*$": _fill("LightCyan"), 108 "^stm32_.*$": _fill("DarkSeaGreen"), 109 "px4::logger::": _fill("Gold"), 110 "Navigator": _fill("GreenYellow"), 111 "can": _fill("LightSalmon"), 112 "^nsh_.*": _fill("LightSkyBlue"), 113 "^(param|bson)_.*": _fill("Bisque")}, 114 **{pattern: _bfill("Silver") for pattern in EDGES.values()}} 115 116 117class SpiBacktrace(Backtrace): 118 EDGES = dict( 119 READ = r"RegisterRead|FIFOReadCount", 120 WRITE = r"RegisterWrite", 121 PARAM = r"^param_main$", 122 NSH = r"^nsh_initialize$", 123 ) 124 COLORS = {**{pattern: _bfill("Silver") for pattern in EDGES.values()}, 125 **{"^(ramtron|bch|bchlib)_.*$": _fill("LightYellow"), 126 "^spi_.*$": _fill("LightCyan"), 127 "^stm32_.*$": _fill("DarkSeaGreen"), 128 "ICM20602": _fill("Gold"), 129 "BMI088": _fill("GreenYellow"), 130 "ICM42688": _fill("LightSalmon"), 131 "^nsh_.*": _fill("LightSkyBlue"), 132 "^(param|bson)_.*": _fill("Bisque")}} 133 134 135class I2cBacktrace(Backtrace): 136 EDGES = dict( 137 TRANSFER = r"stm32_i2c_transfer", 138 NSH = r"^nsh_initialize$", 139 IRQ = r"^stm32_i2c_isr$", 140 INIT = r"^stm32_i2c_setclock$", 141 ) 142 COLORS = {**{"^stm32_.*$": _fill("DarkSeaGreen"), 143 "BMM150": _fill("Yellow"), 144 "IST8310": _fill("Cyan"), 145 "BMP388": _fill("Gold"), 146 "RGBLED": _fill("LightSkyBlue"), 147 "MCP23009": _fill("LightSalmon")}, 148 **{pattern: _bfill("Silver") for pattern in EDGES.values()}} 149 150 151class CanBacktrace(Backtrace): 152 EDGES = dict( 153 SEND = r"CanIface::send$", 154 RECEIVE = r"CanIface::receive$", 155 INIT = r"CanIface::init$", 156 FRAME = r"TransferListener::handleFrame$", 157 ) 158 COLORS = {**{pattern: _bfill("Silver") for pattern in EDGES.values()}, 159 **{"^(ramtron|bch|bchlib)_.*$": _fill("LightYellow"), 160 "Publisher": _fill("DarkSeaGreen")}} 161 162 163class UartBacktrace(Backtrace): 164 EDGES = dict( 165 READ = r"^read$", 166 WRITE = r"^write$", 167 FFLUSH = r"^fflush$", 168 FPUTC = r"^fputc$", 169 FPUTS = r"^fputs$", 170 OPEN = r"^open$", 171 SYSLOG = r"^syslog$", 172 PRINTF = r"^printf$", 173 IRQ = r"^irq_dispatch$", 174 INIT = r"^arm_earlyserialinit$", 175 ) 176 COLORS = {**{"^I2CSPI": _fill("LightYellow"), 177 "^(up|uart)_.*$": _fill("LightCyan"), 178 "^stm32_.*$": _fill("DarkSeaGreen"), 179 "px4::logger": _fill("Gold"), 180 "[mM]avlink": _fill("GreenYellow"), 181 "can": _fill("LightSalmon"), 182 "^nsh_.*": _fill("LightSkyBlue"), 183 "^(param|bson)_.*": _fill("Bisque")}, 184 **{pattern: _bfill("Silver") for pattern in EDGES.values()}} 185 186 187class SemaphoreBacktrace(Backtrace): 188 # EDGES = dict( 189 # RESTORE = r"^nxsem_restoreholderprio$", 190 # BOOST = r"^nxsem_boostholderprio$", 191 # WAIT = r"^nxsem_wait$", 192 # POST = r"^nxsem_post$", 193 # INIT = r"^sem_init$", 194 # DESTROY = r"^sem_destroy$", 195 # FREE = r"^free$", 196 # MALLOC = r"^malloc$", 197 # MEMSET = r"^memset$", 198 # ) 199 # COLORS = {pattern: _bfill("Silver") for pattern in EDGES.values()} 200 def __init__(self, description: str): 201 """ 202 :param description: All lines of the backtrace command also containing a boost trace command. 203 """ 204 super().__init__(description) 205 ops = (_BoostOperation(d) for d in description.splitlines()) 206 ops = [o for o in ops if o.is_valid] 207 self.operation = ops[0] if ops else None 208 if self.operation is not None: 209 self.type = self.operation.task 210 if ops and self.operation.prio_to == 255: 211 if self.type is not None: 212 self.type += "_255" 213 else: 214 self.type = "255"
class
Frame:
10class Frame: 11 """ 12 Parses a GDB frame of a `backtrace` or `px4_backtrace` command. 13 """ 14 def __init__(self, description: str): 15 """ 16 :param description: A single line of the backtrace command starting with a `#` 17 """ 18 self.is_valid = False 19 self.description = description 20 if match := re.match(r"#(\d+) +(?:0x.+? in )?(.+)\((.*?)\) at (.+?):(\d+)", description): 21 self.index = int(match.group(1)) 22 self.function_name = match.group(2) 23 self.args = match.group(3) 24 self.filename = match.group(4) 25 self.line = match.group(5) 26 self.is_valid = True 27 self.function = f"{self.function_name}({self.args})" 28 self.location = f"{Path(self.filename).relative_to(Path().cwd())}:{self.line}" 29 self._unique_location = self.function + "\n" + self.location 30 31 def __hash__(self) -> int: 32 return hash(self._node) 33 34 def __eq__(self, other) -> int: 35 return self.function == other.function and self.filename == other.filename 36 37 def __repr__(self) -> str: 38 return self.function 39 40 def __str__(self) -> str: 41 return f"#{self.index:<2} {self.function}"
Parses a GDB frame of a backtrace
or px4_backtrace
command.
Frame(description: str)
14 def __init__(self, description: str): 15 """ 16 :param description: A single line of the backtrace command starting with a `#` 17 """ 18 self.is_valid = False 19 self.description = description 20 if match := re.match(r"#(\d+) +(?:0x.+? in )?(.+)\((.*?)\) at (.+?):(\d+)", description): 21 self.index = int(match.group(1)) 22 self.function_name = match.group(2) 23 self.args = match.group(3) 24 self.filename = match.group(4) 25 self.line = match.group(5) 26 self.is_valid = True 27 self.function = f"{self.function_name}({self.args})" 28 self.location = f"{Path(self.filename).relative_to(Path().cwd())}:{self.line}" 29 self._unique_location = self.function + "\n" + self.location
Parameters
- description: A single line of the backtrace command starting with a
#
class
Backtrace:
44class Backtrace: 45 """ 46 Holds the entire call chain of a `backtrace` or `px4_backtrace` command. 47 """ 48 EDGES = {} 49 COLORS = {} 50 51 def __init__(self, description: str): 52 """ 53 :param description: All lines of the backtrace command 54 """ 55 self.description = description 56 tasks = (re.match(r"Task=(.+)", d) for d in description.splitlines()) 57 tasks = [t.group(1) for t in tasks if t is not None] 58 self.task = tasks[0] if tasks else None 59 self.type = self.task 60 61 frames = (Frame(d) for d in description.splitlines()) 62 self.frames = [f for f in frames if f.is_valid] 63 self.is_valid = len(self.frames) 64 if self.is_valid: 65 funcs = {f.function for f in self.frames} 66 for name, pattern in self.EDGES.items(): 67 if any(re.search(pattern, f) for f in funcs): 68 self.type = name 69 break 70 71 def __hash__(self) -> int: 72 return hash("".join(f.filename + f.function for f in self.frames)) 73 74 def __eq__(self, other) -> int: 75 ours = "".join(f.filename + f.function for f in self.frames) 76 others = "".join(f.filename + f.function for f in other.frames) 77 return ours == others 78 79 def __repr__(self) -> str: 80 return str(self.frames)
Holds the entire call chain of a backtrace
or px4_backtrace
command.
Backtrace(description: str)
51 def __init__(self, description: str): 52 """ 53 :param description: All lines of the backtrace command 54 """ 55 self.description = description 56 tasks = (re.match(r"Task=(.+)", d) for d in description.splitlines()) 57 tasks = [t.group(1) for t in tasks if t is not None] 58 self.task = tasks[0] if tasks else None 59 self.type = self.task 60 61 frames = (Frame(d) for d in description.splitlines()) 62 self.frames = [f for f in frames if f.is_valid] 63 self.is_valid = len(self.frames) 64 if self.is_valid: 65 funcs = {f.function for f in self.frames} 66 for name, pattern in self.EDGES.items(): 67 if any(re.search(pattern, f) for f in funcs): 68 self.type = name 69 break
Parameters
- description: All lines of the backtrace command
90class FileSystemBacktrace(Backtrace): 91 EDGES = dict( 92 READ = r"^read$", 93 WRITE = r"^write$", 94 FSYNC = r"^fsync$", 95 UNLINK = r"^unlink$", 96 LSEEK = r"^lseek$", 97 OPEN = r"^open$", 98 CLOSE = r"^close$", 99 READDIR = r"^readdir$", 100 OPENDIR = r"^opendir$", 101 MOUNT = r"^mount$", 102 MKDIR = r"^mkdir$", 103 STAT = r"^stat$", 104 IRQ = r"^stm32_sdmmc_interrupt$", 105 INIT = r"^stm32_sdio_initialize$", 106 ) 107 COLORS = {**{"^fat_.*$": _fill("LightYellow"), 108 "^mmc?sd_.*$": _fill("LightCyan"), 109 "^stm32_.*$": _fill("DarkSeaGreen"), 110 "px4::logger::": _fill("Gold"), 111 "Navigator": _fill("GreenYellow"), 112 "can": _fill("LightSalmon"), 113 "^nsh_.*": _fill("LightSkyBlue"), 114 "^(param|bson)_.*": _fill("Bisque")}, 115 **{pattern: _bfill("Silver") for pattern in EDGES.values()}}
Holds the entire call chain of a backtrace
or px4_backtrace
command.
EDGES =
{'READ': '^read$', 'WRITE': '^write$', 'FSYNC': '^fsync$', 'UNLINK': '^unlink$', 'LSEEK': '^lseek$', 'OPEN': '^open$', 'CLOSE': '^close$', 'READDIR': '^readdir$', 'OPENDIR': '^opendir$', 'MOUNT': '^mount$', 'MKDIR': '^mkdir$', 'STAT': '^stat$', 'IRQ': '^stm32_sdmmc_interrupt$', 'INIT': '^stm32_sdio_initialize$'}
COLORS =
{'^fat_.*$': {'style': 'filled', 'fillcolor': 'LightYellow'}, '^mmc?sd_.*$': {'style': 'filled', 'fillcolor': 'LightCyan'}, '^stm32_.*$': {'style': 'filled', 'fillcolor': 'DarkSeaGreen'}, 'px4::logger::': {'style': 'filled', 'fillcolor': 'Gold'}, 'Navigator': {'style': 'filled', 'fillcolor': 'GreenYellow'}, 'can': {'style': 'filled', 'fillcolor': 'LightSalmon'}, '^nsh_.*': {'style': 'filled', 'fillcolor': 'LightSkyBlue'}, '^(param|bson)_.*': {'style': 'filled', 'fillcolor': 'Bisque'}, '^read$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^write$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^fsync$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^unlink$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^lseek$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^open$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^close$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^readdir$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^opendir$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^mount$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^mkdir$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^stat$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^stm32_sdmmc_interrupt$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^stm32_sdio_initialize$': {'style': 'bold,filled', 'fillcolor': 'Silver'}}
118class SpiBacktrace(Backtrace): 119 EDGES = dict( 120 READ = r"RegisterRead|FIFOReadCount", 121 WRITE = r"RegisterWrite", 122 PARAM = r"^param_main$", 123 NSH = r"^nsh_initialize$", 124 ) 125 COLORS = {**{pattern: _bfill("Silver") for pattern in EDGES.values()}, 126 **{"^(ramtron|bch|bchlib)_.*$": _fill("LightYellow"), 127 "^spi_.*$": _fill("LightCyan"), 128 "^stm32_.*$": _fill("DarkSeaGreen"), 129 "ICM20602": _fill("Gold"), 130 "BMI088": _fill("GreenYellow"), 131 "ICM42688": _fill("LightSalmon"), 132 "^nsh_.*": _fill("LightSkyBlue"), 133 "^(param|bson)_.*": _fill("Bisque")}}
Holds the entire call chain of a backtrace
or px4_backtrace
command.
EDGES =
{'READ': 'RegisterRead|FIFOReadCount', 'WRITE': 'RegisterWrite', 'PARAM': '^param_main$', 'NSH': '^nsh_initialize$'}
COLORS =
{'RegisterRead|FIFOReadCount': {'style': 'bold,filled', 'fillcolor': 'Silver'}, 'RegisterWrite': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^param_main$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^nsh_initialize$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^(ramtron|bch|bchlib)_.*$': {'style': 'filled', 'fillcolor': 'LightYellow'}, '^spi_.*$': {'style': 'filled', 'fillcolor': 'LightCyan'}, '^stm32_.*$': {'style': 'filled', 'fillcolor': 'DarkSeaGreen'}, 'ICM20602': {'style': 'filled', 'fillcolor': 'Gold'}, 'BMI088': {'style': 'filled', 'fillcolor': 'GreenYellow'}, 'ICM42688': {'style': 'filled', 'fillcolor': 'LightSalmon'}, '^nsh_.*': {'style': 'filled', 'fillcolor': 'LightSkyBlue'}, '^(param|bson)_.*': {'style': 'filled', 'fillcolor': 'Bisque'}}
136class I2cBacktrace(Backtrace): 137 EDGES = dict( 138 TRANSFER = r"stm32_i2c_transfer", 139 NSH = r"^nsh_initialize$", 140 IRQ = r"^stm32_i2c_isr$", 141 INIT = r"^stm32_i2c_setclock$", 142 ) 143 COLORS = {**{"^stm32_.*$": _fill("DarkSeaGreen"), 144 "BMM150": _fill("Yellow"), 145 "IST8310": _fill("Cyan"), 146 "BMP388": _fill("Gold"), 147 "RGBLED": _fill("LightSkyBlue"), 148 "MCP23009": _fill("LightSalmon")}, 149 **{pattern: _bfill("Silver") for pattern in EDGES.values()}}
Holds the entire call chain of a backtrace
or px4_backtrace
command.
EDGES =
{'TRANSFER': 'stm32_i2c_transfer', 'NSH': '^nsh_initialize$', 'IRQ': '^stm32_i2c_isr$', 'INIT': '^stm32_i2c_setclock$'}
COLORS =
{'^stm32_.*$': {'style': 'filled', 'fillcolor': 'DarkSeaGreen'}, 'BMM150': {'style': 'filled', 'fillcolor': 'Yellow'}, 'IST8310': {'style': 'filled', 'fillcolor': 'Cyan'}, 'BMP388': {'style': 'filled', 'fillcolor': 'Gold'}, 'RGBLED': {'style': 'filled', 'fillcolor': 'LightSkyBlue'}, 'MCP23009': {'style': 'filled', 'fillcolor': 'LightSalmon'}, 'stm32_i2c_transfer': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^nsh_initialize$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^stm32_i2c_isr$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^stm32_i2c_setclock$': {'style': 'bold,filled', 'fillcolor': 'Silver'}}
152class CanBacktrace(Backtrace): 153 EDGES = dict( 154 SEND = r"CanIface::send$", 155 RECEIVE = r"CanIface::receive$", 156 INIT = r"CanIface::init$", 157 FRAME = r"TransferListener::handleFrame$", 158 ) 159 COLORS = {**{pattern: _bfill("Silver") for pattern in EDGES.values()}, 160 **{"^(ramtron|bch|bchlib)_.*$": _fill("LightYellow"), 161 "Publisher": _fill("DarkSeaGreen")}}
Holds the entire call chain of a backtrace
or px4_backtrace
command.
EDGES =
{'SEND': 'CanIface::send$', 'RECEIVE': 'CanIface::receive$', 'INIT': 'CanIface::init$', 'FRAME': 'TransferListener::handleFrame$'}
COLORS =
{'CanIface::send$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, 'CanIface::receive$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, 'CanIface::init$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, 'TransferListener::handleFrame$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^(ramtron|bch|bchlib)_.*$': {'style': 'filled', 'fillcolor': 'LightYellow'}, 'Publisher': {'style': 'filled', 'fillcolor': 'DarkSeaGreen'}}
164class UartBacktrace(Backtrace): 165 EDGES = dict( 166 READ = r"^read$", 167 WRITE = r"^write$", 168 FFLUSH = r"^fflush$", 169 FPUTC = r"^fputc$", 170 FPUTS = r"^fputs$", 171 OPEN = r"^open$", 172 SYSLOG = r"^syslog$", 173 PRINTF = r"^printf$", 174 IRQ = r"^irq_dispatch$", 175 INIT = r"^arm_earlyserialinit$", 176 ) 177 COLORS = {**{"^I2CSPI": _fill("LightYellow"), 178 "^(up|uart)_.*$": _fill("LightCyan"), 179 "^stm32_.*$": _fill("DarkSeaGreen"), 180 "px4::logger": _fill("Gold"), 181 "[mM]avlink": _fill("GreenYellow"), 182 "can": _fill("LightSalmon"), 183 "^nsh_.*": _fill("LightSkyBlue"), 184 "^(param|bson)_.*": _fill("Bisque")}, 185 **{pattern: _bfill("Silver") for pattern in EDGES.values()}}
Holds the entire call chain of a backtrace
or px4_backtrace
command.
EDGES =
{'READ': '^read$', 'WRITE': '^write$', 'FFLUSH': '^fflush$', 'FPUTC': '^fputc$', 'FPUTS': '^fputs$', 'OPEN': '^open$', 'SYSLOG': '^syslog$', 'PRINTF': '^printf$', 'IRQ': '^irq_dispatch$', 'INIT': '^arm_earlyserialinit$'}
COLORS =
{'^I2CSPI': {'style': 'filled', 'fillcolor': 'LightYellow'}, '^(up|uart)_.*$': {'style': 'filled', 'fillcolor': 'LightCyan'}, '^stm32_.*$': {'style': 'filled', 'fillcolor': 'DarkSeaGreen'}, 'px4::logger': {'style': 'filled', 'fillcolor': 'Gold'}, '[mM]avlink': {'style': 'filled', 'fillcolor': 'GreenYellow'}, 'can': {'style': 'filled', 'fillcolor': 'LightSalmon'}, '^nsh_.*': {'style': 'filled', 'fillcolor': 'LightSkyBlue'}, '^(param|bson)_.*': {'style': 'filled', 'fillcolor': 'Bisque'}, '^read$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^write$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^fflush$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^fputc$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^fputs$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^open$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^syslog$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^printf$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^irq_dispatch$': {'style': 'bold,filled', 'fillcolor': 'Silver'}, '^arm_earlyserialinit$': {'style': 'bold,filled', 'fillcolor': 'Silver'}}
188class SemaphoreBacktrace(Backtrace): 189 # EDGES = dict( 190 # RESTORE = r"^nxsem_restoreholderprio$", 191 # BOOST = r"^nxsem_boostholderprio$", 192 # WAIT = r"^nxsem_wait$", 193 # POST = r"^nxsem_post$", 194 # INIT = r"^sem_init$", 195 # DESTROY = r"^sem_destroy$", 196 # FREE = r"^free$", 197 # MALLOC = r"^malloc$", 198 # MEMSET = r"^memset$", 199 # ) 200 # COLORS = {pattern: _bfill("Silver") for pattern in EDGES.values()} 201 def __init__(self, description: str): 202 """ 203 :param description: All lines of the backtrace command also containing a boost trace command. 204 """ 205 super().__init__(description) 206 ops = (_BoostOperation(d) for d in description.splitlines()) 207 ops = [o for o in ops if o.is_valid] 208 self.operation = ops[0] if ops else None 209 if self.operation is not None: 210 self.type = self.operation.task 211 if ops and self.operation.prio_to == 255: 212 if self.type is not None: 213 self.type += "_255" 214 else: 215 self.type = "255"
Holds the entire call chain of a backtrace
or px4_backtrace
command.
SemaphoreBacktrace(description: str)
201 def __init__(self, description: str): 202 """ 203 :param description: All lines of the backtrace command also containing a boost trace command. 204 """ 205 super().__init__(description) 206 ops = (_BoostOperation(d) for d in description.splitlines()) 207 ops = [o for o in ops if o.is_valid] 208 self.operation = ops[0] if ops else None 209 if self.operation is not None: 210 self.type = self.operation.task 211 if ops and self.operation.prio_to == 255: 212 if self.type is not None: 213 self.type += "_255" 214 else: 215 self.type = "255"
Parameters
- description: All lines of the backtrace command also containing a boost trace command.