Thread (104 messages) 104 messages, 13 authors, 2013-02-19

[PATCH v5 04/45] percpu_rwlock: Implement the core design of Per-CPU Reader-Writer Locks

From: Paul E. McKenney <hidden>
Date: 2013-02-10 22:14:12
Also in: linux-arch, linux-pm, linuxppc-dev, lkml, netdev

On Mon, Feb 11, 2013 at 01:39:24AM +0530, Srivatsa S. Bhat wrote:
On 02/11/2013 01:20 AM, Oleg Nesterov wrote:
quoted
On 02/11, Srivatsa S. Bhat wrote:
quoted
On 02/10/2013 11:36 PM, Oleg Nesterov wrote:
quoted
quoted
quoted
+static void announce_writer_inactive(struct percpu_rwlock *pcpu_rwlock)
+{
+   unsigned int cpu;
+
+   drop_writer_signal(pcpu_rwlock, smp_processor_id());
Why do we drop ourselves twice?  More to the point, why is it important to
drop ourselves first?
And don't we need mb() _before_ we clear ->writer_signal ?
Oh, right! Or, how about moving announce_writer_inactive() to _after_
write_unlock()?
Not sure this will help... but, either way it seems we have another
problem...

percpu_rwlock tries to be "generic". This means we should "ignore" its
usage in hotplug, and _write_lock should not race with _write_unlock.
Yes, good point!
quoted
IOW. Suppose that _write_unlock clears ->writer_signal. We need to ensure
that this can't race with another write which wants to set this flag.
Perhaps it should be counter as well, and it should be protected by
the same ->global_rwlock, but _write_lock() should drop it before
sync_all_readers() and then take it again?
Hmm, or we could just add an extra mb() like you suggested, and keep it
simple...
quoted
quoted
quoted
quoted
quoted
+static inline void sync_reader(struct percpu_rwlock *pcpu_rwlock,
+			       unsigned int cpu)
+{
+	smp_rmb(); /* Paired with smp_[w]mb() in percpu_read_[un]lock() */
As I understand it, the purpose of this memory barrier is to ensure
that the stores in drop_writer_signal() happen before the reads from
->reader_refcnt in reader_uses_percpu_refcnt(), thus preventing the
race between a new reader attempting to use the fastpath and this writer
acquiring the lock.  Unless I am confused, this must be smp_mb() rather
than smp_rmb().
And note that before sync_reader() we call announce_writer_active() which
already adds mb() before sync_all_readers/sync_reader, so this rmb() looks
unneeded.
My intention was to help the writer see the ->reader_refcnt drop to zero
ASAP; hence I used smp_wmb() at reader and smp_rmb() here at the writer.
Hmm, interesting... Not sure, but can't really comment. However I can
answer your next question:
Paul told me in another mail that I was expecting too much out of memory
barriers, like increasing the speed of electrons and what not ;-)
[ It would have been cool though, if it had such magical powers :P ]
"But because you have used the special mb_tachyonic instruction, the
speed of light is 600,000 km/s for the next five clock cycles"...  ;-)

							Thanx, Paul
quoted
quoted
Please correct me if my understanding of memory barriers is wrong here..
Who? Me??? No we have paulmck for that ;)
Haha ;-)

Regards,
Srivatsa S. Bhat
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help