Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

pace_poll: allow other platforms to delay#1281

Closed
xobs wants to merge 1 commit intoblackmagic-debug:mainfrom
xobs:platform-pace-poll
Closed

pace_poll: allow other platforms to delay#1281
xobs wants to merge 1 commit intoblackmagic-debug:mainfrom
xobs:platform-pace-poll

Conversation

@xobs
Copy link
Copy Markdown
Contributor

@xobs xobs commented Nov 11, 2022

Detailed description

The RTT implementation normally spends most of its time in a tight loop. This can cause problems on some platforms where tight loops can starve other threads.

Add support for defining PLATFORM_HAS_PACE_POLL in platform.h in order to supply a platform_pace_poll() function that can implement this.

This prevents WDT triggers on ESP32 where RTT blocks the IDLE thread from running. The IDLE thread is responsible for resetting the WDT.

Your checklist for this pull request

  • I've read the Code of Conduct
  • I've read the guidelines for contributing to this repository
  • It builds for hardware native (make PROBE_HOST=native)
  • It builds as BMDA (make PROBE_HOST=hosted)
  • I've tested it to the best of my ability
  • My commit messages provide a useful short description of what the commits do

dragonmux
dragonmux previously approved these changes Nov 11, 2022
Copy link
Copy Markdown
Member

@dragonmux dragonmux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, and seems like a reasonable patch for the problem. @koendv does this seem reasonable to you too?

We'll merge this if it is

@dragonmux dragonmux added the Bug Confirmed bug label Nov 11, 2022
@dragonmux dragonmux added this to the v1.9 release milestone Nov 11, 2022
@koendv
Copy link
Copy Markdown
Contributor

koendv commented Nov 11, 2022 via email

@dragonmux
Copy link
Copy Markdown
Member

We'll hold off on merging till xobs has been able to answer that excellent question

@xobs
Copy link
Copy Markdown
Contributor Author

xobs commented Nov 11, 2022

I'm not sure I understand what you mean by "how tight" the loop is, but my understanding is that it's a busy loop.

The code in gdb_main.c that calls this is here:

blackmagic/src/gdb_main.c

Lines 221 to 230 in 02986d6

while(!(reason = target_halt_poll(cur_target, &watch))) {
char c = (char)gdb_if_getchar_to(0);
if(c == '\x03' || c == '\x04')
target_halt_request(cur_target);
platform_pace_poll();
#ifdef ENABLE_RTT
if (rtt_enabled)
poll_rtt(cur_target);
#endif
}

This will:

  1. Poll the target to see if it needs to halt
  2. Poll the input buffer to see if there's any data
  3. Try to poll RTT

None of these have any delays, so it will busy-wait polling those three things. The RTT code you quoted seems to decide whether the call to poll_rtt() actually does something, but it doesn't prevent that from being repeatedly called and having no work done.

I think it was incorrect of me to call out rtt as being the culprit here. I believe it's just exposing an existing issue that is causing instability on my host. The ultimate solution is still to insert a delay every once in a while, similar to how it's done with PC_HOSTED.

@koendv
Copy link
Copy Markdown
Contributor

koendv commented Nov 11, 2022

Yes, it seems a generic issue, not limited to rtt.

I attach a small patch that breaks out the variable rtt_poll_ms.
With default settings, rtt_poll_ms is between 8ms (lots of things to print) and 256ms (nothing to print, just checking).
As far as rtt is concerned, you can put a delay of rtt_poll_ms milliseconds in gdb_main_loop(), no problem.

rtt_poll_patch.txt

@xobs xobs changed the title rtt: pace_poll: allow other platforms to delay pace_poll: allow other platforms to delay Nov 11, 2022
The gdb_main normally spends most of its time in a tight loop. This can
cause problems on some platforms where tight loops can starve other
threads.

Add support for defining PLATFORM_HAS_PACE_POLL in `platform.h` in order
to supply a `platform_pace_poll()` function that can implement this.

Signed-off-by: Sean Cross <sean@xobs.io>
@xobs
Copy link
Copy Markdown
Contributor Author

xobs commented Nov 11, 2022

I've updated the PR title and commit message to reflect the fact that it's not RTT that's causing the issue, and ultimately what my target needs is a way to occasionally call yield() similar to how 868e76b adds slow polling as the default setting for hosted mode.

I can apply your rtt patch if you like, but I don't immediately have a need for examining rtt_poll_ms.

@koendv
Copy link
Copy Markdown
Contributor

koendv commented Nov 11, 2022 via email

@xobs
Copy link
Copy Markdown
Contributor Author

xobs commented Nov 11, 2022

This is BMP on an ESP32, yes. I'm creating a task that wraps gdb_main() and I've rewritten the gdb_if_* commands to call versions that map to wifi equivalents. The GDB main wrapper is at https://github.com/farpatch/farpatch/blob/main/main/gdb_if.c#L88-L131

By taking this approach I'm able to reuse almost the entirety of BMP. I just have to omit the JTAG/SWD drivers, USB code, and main loop. Everything else is used wholesale. I've taken this approach to try and be light-fingered and avoid introducing too many architectural changes in BMP.

If you'd prefer me to rewrite gdb_main() in gdb_main.c so that it's state-based, I can do that and submit a PR. Overall there are just two states -- halted and not-halted. My concern is that it essentially turns the loop inside-out, and I'd want to make sure the approach is what you had in mind prior to starting that.

@koendv
Copy link
Copy Markdown
Contributor

koendv commented Nov 11, 2022 via email

@xobs
Copy link
Copy Markdown
Contributor Author

xobs commented Nov 11, 2022

I'm still not entirely sure what architecture you're looking to move to.

Right now it looks like this:

  1. Platform setup calls gdb_main(), which never returns
  2. gdb_main() calls gdb_main_loop() with a struct target_controller argument that is non-public
  3. gdb_main_loop() spends most of its time in gdb_getpacket() or the target_halt_poll() tight loop

What approach are you looking for in the new design?

Would you make struct target_controller gdb_controller public? Would gdb_main_loop() return now between calls? Would gdb_getpacket() get hoisted into gdb_main()?

Some of these changes would be nice, because it would be great to be able to put a mutex around the main loop and share it among different network sockets. But making these changes requires removing static from a lots of structs that I've tried to not touch so far. Is that your intended approach?

@koendv
Copy link
Copy Markdown
Contributor

koendv commented Nov 11, 2022 via email

@xobs xobs mentioned this pull request Nov 13, 2022
6 tasks
@xobs
Copy link
Copy Markdown
Contributor Author

xobs commented Nov 13, 2022

I'll close this issue in favour of #1284

@xobs xobs closed this Nov 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Bug Confirmed bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants