On Fri, 14 Jun 2019 at 17:42, Doug Anderson dianders@chromium.org wrote:
Hi,
On Fri, Jun 14, 2019 at 4:56 AM Ulf Hansson ulf.hansson@linaro.org wrote:
I was more worried about the safety of mmc_card_set_suspended() itself. That is:
#define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
...so it's doing a read-modify-write of "state". Is that safe to do without any type of locking?
In this case, yes I think so.
The point is, it really doesn't matter if the reader (work or thread), reads a non-updated value, because the synchronization is managed by the later mmc_claim_host() and the cancel_delayed_work_sync().
If this were just an "int" then perhaps, but this is a bitfield. So if someone else updates the bitfield at the same time then we can fully clobber their modification or they can clobber ours, right?
task 1: load "state" from memory into CPU register on cpu0 task 2: load "state" from memory into CPU register on cpu1 task 1: OR in MMC_CARD_REMOVED task 1: write "state" from CPU register on cpu0 task 2: OR in MMC_STATE_SUSPENDED task 2: write "state" from CPU register on cpu1
...so now we've clobbered MMC_CARD_REMOVED. ...or am I just being paranoid here and everything else in "state" is somehow guaranteed to not be touched at the same time this function is running?
I understand your concern. It's not obvious by looking at the code, but yes, there should be no other writing to the "state" at the same time mmc_sdio_supend() is running.
MMC_CARD_REMOVED for example, is set from _mmc_detect_card_removed(), but because the detect work (mmc_recan()) has been disabled and the block device driver has been suspended, it can't be called.
Anyway, perhaps we get reasons to add a lock to the card struct when going forward, but at this point I think we are fine.
Kind regards Uffe