diff --git a/doc/gdb_macros.md b/doc/gdb_macros.md index 3c2260073..b0fb82e8b 100644 --- a/doc/gdb_macros.md +++ b/doc/gdb_macros.md @@ -125,6 +125,54 @@ nqn "nqn.2016-06.io.spdk.umgmt:cnode1", '\000' ID 1 ~~~ +Printing SPDK spinlocks: + +In this example, the spinlock has been initialized and locked but has never been unlocked. +After it is unlocked the first time the last unlocked stack will be present and the +`Locked by spdk_thread` line will say `not locked`. + +~~~{.sh} +Breakpoint 2, spdk_spin_unlock (sspin=0x655110 ) at thread.c:2915 +2915 struct spdk_thread *thread = spdk_get_thread(); +(gdb) print *sspin +$2 = struct spdk_spinlock: + Locked by spdk_thread: 0x658080 + Initialized at: + 0x43e677 thread.c:2878 + 0x404feb <_bdev_init+16> /build/spdk/spdk-review-public/lib/bdev/bdev.c:116 + 0x44483d <__libc_csu_init+77> + 0x7ffff62c9d18 <__libc_start_main+120> + 0x40268e <_start+46> + Last locked at: + 0x43e936 thread.c:2909 + 0x40ca9c /build/spdk/spdk-review-public/lib/bdev/bdev.c:3855 + 0x411a3c /build/spdk/spdk-review-public/lib/bdev/bdev.c:6660 + 0x412e1e /build/spdk/spdk-review-public/lib/bdev/bdev.c:7171 + 0x417895 bdev_ut.c:878 + 0x7ffff7bc38cb + 0x7ffff7bc3b61 + 0x7ffff7bc3f76 + 0x43351f bdev_ut.c:6295 + 0x7ffff62c9d85 <__libc_start_main+229> + 0x40268e <_start+46> + Last unlocked at: +~~~ + +Print a single spinlock stack: + +~~~{.sh} +(gdb) print sspin->internal.lock_stack +$1 = struct sspin_stack: + 0x40c6a1 /build/spdk/spdk-review-public/lib/thread/thread.c:2909 + 0x413f48 thread_ut.c:1831 + 0x7ffff7bc38cb + 0x7ffff7bc3b61 + 0x7ffff7bc3f76 + 0x4148fa thread_ut.c:1948 + 0x7ffff62c9d85 <__libc_start_main+229> + 0x40248e <_start+46> +~~~ + ## Loading The gdb Macros Copy the gdb macros to the host where you are about to debug. diff --git a/scripts/gdb_macros.py b/scripts/gdb_macros.py index ee2d13a22..977cb112e 100644 --- a/scripts/gdb_macros.py +++ b/scripts/gdb_macros.py @@ -4,6 +4,7 @@ # import gdb +import gdb.printing class SpdkTailqList(object): @@ -307,6 +308,64 @@ class spdk_print_threads(SpdkPrintCommand): super(spdk_print_threads, self).__init__(name, threads) +class SpdkSpinlockStackPrinter(object): + + def __init__(self, val): + self.val = val + + def to_array(self): + ret = [] + count = self.val['depth'] + for i in range(count): + line = '' + addr = self.val['addrs'][i] + line += ' ' + str(addr) + # Source and line (sal) only exists for objects with debug info + sal = gdb.find_pc_line(int(addr)) + try: + line += ' ' + str(sal.symtab.filename) + line += ':' + str(sal.line) + except AttributeError as e: + pass + ret.append(line) + return ret + + def to_string(self): + return 'struct sspin_stack:\n' + '\n'.join(self.to_array()) + + def display_hint(self): + return 'struct sspin_stack' + + +class SpdkSpinlockPrinter(object): + + def __init__(self, val): + self.val = val + + def to_string(self): + thread = self.val['thread'] + internal = self.val['internal'] + s = 'struct spdk_spinlock:' + s += '\n Locked by spdk_thread: ' + if thread == 0: + s += 'not locked' + else: + s += str(thread) + if internal != 0: + stacks = [ + ['Initialized', 'init_stack'], + ['Last locked', 'lock_stack'], + ['Last unlocked', 'unlock_stack']] + for stack in stacks: + s += '\n ' + stack[0] + ' at:\n ' + frames = SpdkSpinlockStackPrinter(internal[stack[1]]) + s += '\n '.join(frames.to_array()) + return s + + def display_hint(self): + return 'struct spdk_spinlock' + + class spdk_load_macros(gdb.Command): def __init__(self): @@ -316,12 +375,21 @@ class spdk_load_macros(gdb.Command): True) self.loaded = False + def load_pretty_printers(self): + pp = gdb.printing.RegexpCollectionPrettyPrinter("spdk_library") + pp.add_printer('sspin_stack', '^sspin_stack$', + SpdkSpinlockStackPrinter) + pp.add_printer('spdk_spinlock', '^spdk_spinlock$', SpdkSpinlockPrinter) + gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) + def invoke(self, arg, from_tty): if arg == '--reload': print('Reloading spdk information') reload = True else: reload = False + # These can only load once + self.load_pretty_printers() if self.loaded and not reload: return