From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54529) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZK7Wb-0005uF-Cc for qemu-devel@nongnu.org; Tue, 28 Jul 2015 12:14:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZK7WV-00025G-Ln for qemu-devel@nongnu.org; Tue, 28 Jul 2015 12:14:41 -0400 Received: from mail-wi0-x231.google.com ([2a00:1450:400c:c05::231]:37454) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZK7WV-000254-Ec for qemu-devel@nongnu.org; Tue, 28 Jul 2015 12:14:35 -0400 Received: by wibud3 with SMTP id ud3so166792095wib.0 for ; Tue, 28 Jul 2015 09:14:34 -0700 (PDT) Sender: Paolo Bonzini References: <55B6E854.9090600@cn.fujitsu.com> <55B75278.80909@redhat.com> <55B7532D.9010506@cn.fujitsu.com> <55B756D8.9090503@redhat.com> <55B75A70.8080203@cn.fujitsu.com> <55B76BA3.4080804@redhat.com> <55B783D6.3020102@gmail.com> From: Paolo Bonzini Message-ID: <55B7AA66.1070209@redhat.com> Date: Tue, 28 Jul 2015 18:14:30 +0200 MIME-Version: 1.0 In-Reply-To: <55B783D6.3020102@gmail.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Subject: Re: [Qemu-devel] [PATCH v2 for-2.5] rcu: Allow calling rcu_(un)register_thread() during synchronize_rcu() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Wen Congyang , Wen Congyang , qemu-devl On 28/07/2015 15:29, Wen Congyang wrote: >>> >> >> If you call it just once, you have the same problem as before. In fact, >> it's worse because instead of having an overflow every 2^31 periods, you >> have one every 2 periods. Instead, by checking that rcu_reader went >> through 1 _and_ 3 (or that it was at least once 0, i.e. the thread was >> quiescent), you are sure that the thread went through _at least one_ >> grace period. > > The overflow is acceptable. We only compare if rcu_reader.ctr is equal than > rcu_gp_ctr. If not, we should wait that thread to call rcu_read_unlock(). > We don't care which is bigger. If no threads calls sync_rcu(), all threads > rcu_read.ctr is 0 or rcu_gp_ctr. If one thread calls sync_rcu(), all > threads rcu_read.ctr is 0, old_rcu_gp_ctr, or new_rcu_gp_ctr. We only wait the > thread that's rcu_read.ctr is old_rcu_gp_ctr. Suppose you have reader writer --------------------------------------------------------------- rcu_read_lock() ctr = atomic_read(&rcu_gp_ctr); ctr = 1 synchronize_rcu() rcu_gp_ctr = 3 atomic_xchg(&p_rcu_reader->ctr, ctr); rcu_reader.ctr = 1 We're in the critical section. synchronize_rcu() rcu_gp_ctr = 1 rcu_gp_ongoing(&p_rcu_reader->ctr) returns false, so synchronize_rcu() exits. But we're still in the critical section. p = atomic_rcu_read(&foo); g_free(p); Boom. :) For more information see http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.220.8810 Paolo