From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37315) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZZb4l-0007ZK-Cg for qemu-devel@nongnu.org; Wed, 09 Sep 2015 04:49:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZZb4k-0005zg-84 for qemu-devel@nongnu.org; Wed, 09 Sep 2015 04:49:55 -0400 Date: Wed, 9 Sep 2015 16:49:47 +0800 From: Fam Zheng Message-ID: <20150909084947.GD21413@ad.nay.redhat.com> References: <1438868176-20364-1-git-send-email-pbonzini@redhat.com> <1438868176-20364-4-git-send-email-pbonzini@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1438868176-20364-4-git-send-email-pbonzini@redhat.com> Subject: Re: [Qemu-devel] [PATCH 03/18] qemu-thread: introduce QemuLockCnt List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Paolo Bonzini Cc: kwolf@redhat.com, qemu-block@nongnu.org, qemu-devel@nongnu.org, stefanha@redhat.com On Thu, 08/06 15:36, Paolo Bonzini wrote: > +QemuLockCnt usage > +----------------- > + > +The typical pattern for QemuLockCnt functions is as follows. > + > + qemu_lockcnt_inc(&xyz_lockcnt); > + if (xyz) { > + ... access xyz ... > + } > + > + if (qemu_lockcnt_dec_and_lock(&xyz_lockcnt)) { > + g_free(xyz); > + xyz = NULL; > + qemu_lockcnt_unlock(&xyz_lockcnt); > + } > + > +Modifications are done using qemu_lockcnt_lock and qemu_lockcnt_unlock: > + > + qemu_lockcnt_lock(&xyz_lockcnt); > + xyz = g_malloc(xyz); > + qemu_lockcnt_unlock(&xyz_lockcnt); > + > +If an object has to be freed outside a visit, you can use the following > +scheme: > + > + qemu_lockcnt_lock(&xyz_lockcnt); > + if (!qemu_lockcnt_count(&xyz_lockcnt)) { > + g_free(xyz); > + xyz = NULL; > + } > + qemu_lockcnt_unlock(&xyz_lockcnt); > + > +In both the first and the third code snippets, g_free is only executed > +if count is zero. qemu_lockcnt_inc prevents the count from becoming > +non-zero while the object is being freed. > + > + > +QemuLockCnt can also be used to access a list as follows: > + > + qemu_lockcnt_inc(&io_handlers_lockcnt); > + QLIST_FOREACH_RCU(ioh, &io_handlers, pioh) { > + if (ioh->revents & G_IO_OUT) { > + ioh->fd_write(ioh->opaque); > + } > + } I'm confused, the comment of QLIST_FOREACH_RCU says "list traversal must occur within an RCU critical section.", but there is not rcu_read_lock here. Why? Fam > + > + if (qemu_lockcnt_dec_and_lock(&io_handlers_lockcnt)) { > + QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { > + if (ioh->deleted) { > + QLIST_REMOVE(ioh, next); > + g_free(ioh); > + } > + } > + qemu_lockcnt_unlock(&io_handlers_lockcnt); > + } > + > +An alternative pattern uses qemu_lockcnt_dec_if_lock: > + > + qemu_lockcnt_inc(&io_handlers_lockcnt); > + QLIST_FOREACH_SAFE_RCU(ioh, &io_handlers, next, pioh) { > + if (ioh->deleted && qemu_lockcnt_dec_if_lock(&io_handlers_lockcnt)) { > + QLIST_REMOVE(ioh, next); > + g_free(ioh); > + qemu_lockcnt_inc_and_unlock(&io_handlers_lockcnt); > + continue; > + } > + > + if (ioh->revents & G_IO_OUT) { > + ioh->fd_write(ioh->opaque); > + } > + } > + qemu_lockcnt_dec(&io_handlers_lockcnt); > + > +Here you can use qemu_lockcnt_dec because there is no special task > +to do if the count goes from 1 to 0.