-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lock fix #62
Lock fix #62
Conversation
@luarvique - I did some research on the C++ attribute 'volatile' tonight, and it doesn't seem to help much with multithreading (see here for instance: https://stackoverflow.com/a/4558031). Franco |
The 'volatile' keyword makes sure that the compiler does not optimize accesses to these variables away, i.e. if you do something like
the loop will actually read "done" variable on every pass. The use of "volatile" keywords is helpful, but it is not what fixes the threading issue. Two separate changes fix the threading issue in the proposed patch:
If you call sleep_for() while holding the mutex, the rx_callback() will simply get stuck for the entire duration of sleep_for(), as many times as you call it. Here is what a typical wait for such a flag looks like now, in Settings.cpp:
This code is not very different from yours, except that every time it puts thread to sleep for 1msec, it releases the mutex first, to let rx_callback() set gr_changed safely. I have forked SoapySDRPlay3 code and implemented all the changes I deemed necessary, including the above lock fix, multiple sdrplay_api_Update() retries, and the removal of RFGR gain from the overall gain control. The modified code is available here: https://github.com/luarvique/SoapySDRPlay3/tree/develop You are welcome to look at it, use it, and import any of the changes into your own code. Send me a private email if you would like access to an ARM64-based receiver running this code. |
Regarding volatile, I would recommend using a std::atomic_flag and maybe memory order relaxed. I have recently forked and rewritten the SoapyAirspy and SoapyAirspyHF drivers. In the process I wrote a new ring buffer class specifically for writing Soapy drivers. Maybe that could be of interest? You can take a look at github.com/ast/SoapyAirspy and github.com/ast/SoapyRingbuffer |
As already said in #59 (comment) and also pointed out by @ast and @fventuri , the |
The 'volatile' keyword is not used to guarantee memory ordering between threads in the changes being discussed. It has been said so earlier in the comments. |
Strawman lol. I apologize to everyone involved that I got involved in this thread with my unsolicited advice, but I got a notification from pothosware and couldn't keep my mouth shut. I will leave you with a final piece of advice: When using sleep for "mutex lock slack" you should have a pretty damn good argument why you are not using a condition variable. |
It is not a particularly good argument, but I did not want to refactor the original code too much. The goal was to fix, not to rewrite. |
@ast, @fmoessbauer - First of all I really appreciate your interesting and valuable comments in this discussion. Regarding the use of a condition variable (which I agree should be the way to go), sometime ago a created a branch called @ast, I took a look at your very fast ring buffer, and it seems similar to a ring buffer implementation I wrote a few months ago (https://github.com/fventuri/rsp_snd/blob/main/src/ringbuffer.cpp), which follows more or less what Jakob Ketterl did in the Franco |
@fventuri thank you for the additional information! That's very interesting! The APIs for double mapping memory exist under Windows and macOS (but they are different, of course) ps. I think you only need one mmap and one mremap. Albin |
@ast - Albin, thanks for the useful info about Windows and Mac. All the implementations of this virtual memory approach I saw use a total of three mmap/mremap calls (see here for instance: https://abhinavag.medium.com/a-fast-circular-ring-buffer-4d102ef4d4a3); I didn't know it could be done with just two. Franco |
I'm not sure but your approach with using mremap instead of mmap with a file descriptor was new to me. I Googled around and saw some indications that one mmap and one mremap could be sufficient. I will experiment with it. Yes gnuradio uses the same idea and you can probably find code for windows and macOS memory mapping there. |
Merged with the latest upstream code. Added better locking granularity to the callback. The fix for intermittently failing sdrplay_api_Update() call can be found in a separate pull request.