opentitan icon indicating copy to clipboard operation
opentitan copied to clipboard

[dv/dpi] TCP server enters infinite loop if ring buffer is full

Open duk-37 opened this issue 1 year ago • 2 comments

Description

The rptr and wptr variables here are missing volatile, so GCC will optimize the while loop in tcp_server_put_byte to a branch and an infinite loop when compiling with -O2. as you can see in this godbolt link.

duk-37 avatar Sep 21 '24 01:09 duk-37

Oh dear! Thanks for the report and for analysing what exactly is going on here. If I understand correctly, the tcp_buffer_put_byte function expects some other thread to update rptr and, because it isn't volatile, we get the infinite loop you describe.

Presumably a trivial way to get this effect would be to pass buf is as volatile struct tcp_buf *buf or similar. It's "more volatile" than just the pointer variables (because we are allowing the outside world to change buf->buf as well), but the meaning might be more obvious (and doesn't require us to add annotations to the struct itself).

Would you be happy to file a PR with a fix?

rswarbrick avatar Sep 23 '24 13:09 rswarbrick

Oh dear! Thanks for the report and for analysing what exactly is going on here. If I understand correctly, the tcp_buffer_put_byte function expects some other thread to update rptr and, because it isn't volatile, we get the infinite loop you describe.

Yep!

Presumably a trivial way to get this effect would be to pass buf is as volatile struct tcp_buf *buf or similar. It's "more volatile" than just the pointer variables (because we are allowing the outside world to change buf->buf as well), but the meaning might be more obvious (and doesn't require us to add annotations to the struct itself).

Would you be happy to file a PR with a fix?

Sure, I can file one later today.

duk-37 avatar Sep 23 '24 14:09 duk-37