Duet3D / RepRapFirmware

OO C++ RepRap Firmware
GNU General Public License v3.0
938 stars 532 forks source link

Implement stack usage analysis of tasks #525

Open mfs12 opened 3 years ago

mfs12 commented 3 years ago
mfs12 commented 3 years ago

RRF already uses the -fstack-usage option to generate the stack usage info in su files. We need to add the other option to generate the file from which we can generate the call graph.

Looks like the other option needed is -fdump-rtl-expand

dc42 commented 3 years ago

I have added compile options -fstack-usage -fdump-rtl-expand to the SAME5x builds of all relevant projects. We can do this for the other configurations when the stack usage tool is working and we know that these options are needed by it.

mfs12 commented 3 years ago
mfs12 commented 3 years ago

Tools

avstack

The columns of the output are:

stacklyze

instrument function

Runtime: before and after each function call check the current stack usage. Compile the code with -finstrument-functions. Then define two functions in your code that roughly should get the current stack usage and operate on them:

static unsigned long long max_stack_usage = 0;

void __cyg_profile_func_enter(void * this, void * call) __attribute__((no_instrument_function)) {
      // get current stack usage using some hardware facility or intrisic function
      // like __get_SP() on ARM with CMSIS
      unsigned cur_stack_usage = __GET_CURRENT_STACK_POINTER() - __GET_BEGINNING_OF_STACK();
      // use debugger to output current stack pointer
      // for example semihosting on ARM
      __DEBUGGER_TRANSFER_STACK_POINTER(cur_stack_usage);
      // or you could store the max somewhere
      // then just run the program
      if (max_stack_usage < cur_stack_usage) {
            max_stack_usage = max_stack_usage;
      }
      // you could also manually inspect with debugger
      unsigned long long somelimit = 0x2000;
      if (cur_stack_usage > somelimit) {
           __BREAKPOINT();
      }
}
void __cyg_profile_func_exit(void * this, void * call) __attribute__((no_instrument_function)) {
      // well, nothing
}
mfs12 commented 3 years ago

stacklyze doesn't seem to work very well with c++. Because of mangled names?

mfs12 commented 3 years ago

that looks like a good start. I can see some issues that need to be fixed:

  • It reports a lot of functions as unresolved. Those appear to be functions in other projects i.e. CoreN2G, CANlib, RRFLibraries and FreeRTOS. So you need to have the program look at the .su and other files from those projects too.
  • It doesn't seem to take account of recursion. I was expecting it to detect recursion and say that it couldn't determine the cost, but it doesn't appear to. For recursive functions we need to evaluate the maximum of the stack usage when there are no recursive calls, and the stack usage to the next call t the stack check function (and report if there is a recursive call that doesn't pass through the stack check function.
  • It would be good to improve the formatting. I suggest putting the function name in the last column instead of the first.
  • It would be good to highlight task entry points. We could use a naming convention for task entry point to make them easy to recognise.
mfs12 commented 3 years ago

following files are not created by build system but are needed.

SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/Vectors.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_atomic.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_flash.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_gpio.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_mac_async.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_rand_sync.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_sleep.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_usb_device.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/src/hal_wdt.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/utils/src/utils_assert.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/utils/src/utils_event.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hal/utils/src/utils_list.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hpl/core/hpl_core_m4.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hpl/gmac/hpl_gmac.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hpl/nvmctrl/hpl_nvmctrl.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hpl/usb/hpl_usb.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/hpl/wdt/hpl_wdt.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/usb/class/cdc/device/cdcdf_acm.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/usb/device/usbdc.su missing
SAME5x_CAN_SDHC_USB_RTOS/src/SAME5x_C21/SAME5x/usb/usb_protocol.su missing
mfs12 commented 3 years ago

avstack

mfs12 commented 3 years ago

-Wstack-usage Warning

Another useful compiler option is -Wstack-usage. With this option the compiler will issue a warning whenever the stack usage exceeds a given limit.

mfs12 commented 3 years ago

interesting article about stack usage. https://mcuoneclipse.com/2015/08/21/gnu-static-stack-usage-analysis/