Re: synchronize with a non-atomic flag

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thanks Paul and Akira,

2017-10-07 3:12 GMT+08:00 Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx>:
> On Fri, Oct 06, 2017 at 08:35:00PM +0800, Yubin Ruan wrote:
>> 2017-10-06 20:03 GMT+08:00 Akira Yokosawa <akiyks@xxxxxxxxx>:
>> > On 2017/10/06 14:52, Yubin Ruan wrote:
>
> [ . . . ]
>
>> > I/O operations in printf() might make the situation trickier.
>>
>> printf(3) is claimed to be thread-safe, so I think this issue will not
>> concern us.

so now I can pretty much confirm this.

>> > In a more realistic case where you do something meaningful in
>> > do_something() in both threads:
>> >
>> >     //process 1
>> >     while(1) {
>> >         if(READ_ONCE(flag) == 0) {
>> >             do_something();
>> >             WRITE_ONCE(flag, 1); // let another process to run
>> >         } else {
>> >             continue;
>> >         }
>> >     }
>> >
>> >     //process 2
>> >     while(1) {
>> >         if(READ_ONCE(flag) == 1) {
>> >             do_something();
>> >             WRITE_ONCE(flag, 0); // let another process to run
>> >         } else {
>> >             continue;
>> >         }
>> >     }
>
> In the Linux kernel, there is control-dependency ordering between
> the READ_ONCE(flag) and any stores in either the then-clause or
> the else-clause.  However, I see no ordering between do_something()
> and the WRITE_ONCE().

I was not aware of the "control-dependency" ordering issue in the
Linux kernel before. Is it true for all architectures?

But anyway, the ordering between READ_ONCE(flag) and any subsequent
stores are guaranteed on X86/X64, so we didn't need any memory barrier
here.

>> > and if do_something() uses some shared variables other than "flag",
>> > you need a couple of memory barriers to ensure the ordering of
>> > READ_ONCE(), do_something(), and WRITE_ONCE() something like:
>> >
>> >     //process 1
>> >     while(1) {
>> >         if(READ_ONCE(flag) == 0) {
>> >             smp_rmb();
>> >             do_something();
>> >             smp_wmb();
>> >             WRITE_ONCE(flag, 1); // let another process to run
>> >         } else {
>> >             continue;
>> >         }
>> >     }
>> >
>> >     //process 2
>> >     while(1) {
>> >         if(READ_ONCE(flag) == 1) {
>> >             smp_rmb();
>> >             do_something();
>> >             smp_wmb();
>> >             WRITE_ONCE(flag, 0); // let another process to run
>> >         } else {
>> >             continue;
>> >         }
>> >     }
>
> Here, the control dependency again orders the READ_ONCE() against later
> stores, and the smp_rmb() orders the READ_ONCE() against any later
> loads.

Understand and agree.

> The smp_wmb() orders do_something()'s writes (but not its reads!)
> against the WRITE_ONCE().

Understand and agree. But do we really need the smp_rmb() on X86/64?
As far as I know, on X86/64 stores are not reordered with other
stores...[1]

>> > In Linux kernel memory model, you can use acquire/release APIs instead:
>> >
>> >     //process 1
>> >     while(1) {
>> >         if(smp_load_acquire(&flag) == 0) {
>> >             do_something();
>> >             smp_store_release(&flag, 1); // let another process to run
>> >         } else {
>> >             continue;
>> >         }
>> >     }
>> >
>> >     //process 2
>> >     while(1) {
>> >         if(smp_load_acquire(&flag) == 1) {
>> >             do_something();
>> >             smp_store_release(&flag, 0); // let another process to run
>> >         } else {
>> >             continue;
>> >         }
>> >     }
>
> This is probably the most straightforward of the above approaches.
>
> That said, if you really want a series of things to execute in a
> particular order, why not just put them into the same process?

I will be very happy if I can. But sometimes we just have to deal with
issues concerning multiple processes...

[1]: One thing I got a little confused is that some people claim that
on x86/64 there are several guarantees[2]:
    1) Loads are not reordered with other loads.
    2) Stores are not reordered with other stores.
    3) Stores are not reordered with older loads.
(note that Loads may still be reordered with older stores to different
locations)

So, if 1) and 2) are true, why do we have "lfence" and "sfence"
instructions at all?

[2]: I found those claims here, but not so sure whether or not they
are true: https://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/
--
To unsubscribe from this list: send the line "unsubscribe perfbook" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux