From patchwork Mon Mar 21 22:27:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 649091 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2LMSwfk015788 for ; Mon, 21 Mar 2011 22:28:58 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753875Ab1CUW1v (ORCPT ); Mon, 21 Mar 2011 18:27:51 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:35836 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753277Ab1CUW1u (ORCPT ); Mon, 21 Mar 2011 18:27:50 -0400 Received: by fxm17 with SMTP id 17so5923422fxm.19 for ; Mon, 21 Mar 2011 15:27:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:subject:from:to:cc:in-reply-to:references :content-type:date:message-id:mime-version:x-mailer :content-transfer-encoding; bh=KF4KUouL+w3uvYbE3ZH8yXIEXF/cPjXkEXhp85o/3uw=; b=h9SYR6Z2VO5gSgP/IkONEhf/2zYqIQmvq/eRaCXeMI5fMAHtL++AqReNHJOmpNzrwa +BVgg091KuFLQEocgIRqedPjK6NqDZP4WHinic8UCV9ZI0DIhzX4b5Phm3cFviweEddu owVlMaC7jEWKHjonti+mNzdxB5ymnb0mtbKkI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=subject:from:to:cc:in-reply-to:references:content-type:date :message-id:mime-version:x-mailer:content-transfer-encoding; b=wvWs2l2pJUBx8XwHIUkXxrd3T/QdZMYHLx646RPQjERJccKL4cfFGm6cNaPJxKwGMq wAHFRrq6pczskH6qEmtzSmf9uAGG0JAgDX6MOccqWB04OLqmq8PRbCc0U6DzwNVHnYvD F67ojMywtCLqCUE/M3cQ4deK+Jk49fWRpWVqQ= Received: by 10.223.3.132 with SMTP id 4mr5636165fan.132.1300746435525; Mon, 21 Mar 2011 15:27:15 -0700 (PDT) Received: from [10.150.51.212] (gw0.net.jmsp.net [212.23.165.14]) by mx.google.com with ESMTPS id j12sm306695fax.33.2011.03.21.15.27.12 (version=SSLv3 cipher=OTHER); Mon, 21 Mar 2011 15:27:14 -0700 (PDT) Subject: [RFC] posix-timers: RCU conversion From: Eric Dumazet To: ben@iagu.net Cc: Avi Kivity , KVM list , Thomas Gleixner , linux-kernel , John Stultz , Richard Cochran In-Reply-To: References: <20110318123031.GB6066@8bytes.org> <4D871F6C.40207@redhat.com> <4D875842.9050308@redhat.com> <4D8773AA.8030408@redhat.com> <1300726498.2884.493.camel@edumazet-laptop> <4D8784A9.8040303@redhat.com> <1300727545.2884.513.camel@edumazet-laptop> Date: Mon, 21 Mar 2011 23:27:09 +0100 Message-ID: <1300746429.2837.20.camel@edumazet-laptop> Mime-Version: 1.0 X-Mailer: Evolution 2.30.3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 21 Mar 2011 22:28:58 +0000 (UTC) diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index d51243a..5dc27ca 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -81,6 +81,7 @@ struct k_itimer { unsigned long expires; } mmtimer; } it; + struct rcu_head rcu; }; struct k_clock { diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 4c01249..e2a823a 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -491,6 +491,11 @@ static struct k_itimer * alloc_posix_timer(void) return tmr; } +static void k_itimer_rcu_free(struct rcu_head *head) +{ + kmem_cache_free(posix_timers_cache, container_of(head, struct k_itimer, rcu)); +} + #define IT_ID_SET 1 #define IT_ID_NOT_SET 0 static void release_posix_timer(struct k_itimer *tmr, int it_id_set) @@ -499,11 +504,12 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set) unsigned long flags; spin_lock_irqsave(&idr_lock, flags); idr_remove(&posix_timers_id, tmr->it_id); + tmr->it_id = -1; spin_unlock_irqrestore(&idr_lock, flags); } put_pid(tmr->it_pid); sigqueue_free(tmr->sigq); - kmem_cache_free(posix_timers_cache, tmr); + call_rcu(&tmr->rcu, k_itimer_rcu_free); } static struct k_clock *clockid_to_kclock(const clockid_t id) @@ -631,22 +637,18 @@ out: static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) { struct k_itimer *timr; - /* - * Watch out here. We do a irqsave on the idr_lock and pass the - * flags part over to the timer lock. Must not let interrupts in - * while we are moving the lock. - */ - spin_lock_irqsave(&idr_lock, *flags); + + rcu_read_lock(); timr = idr_find(&posix_timers_id, (int)timer_id); if (timr) { - spin_lock(&timr->it_lock); - if (timr->it_signal == current->signal) { - spin_unlock(&idr_lock); + spin_lock_irqsave(&timr->it_lock, *flags); + if (timr->it_id == (int)timer_id && timr->it_signal == current->signal) { + rcu_read_unlock(); return timr; } - spin_unlock(&timr->it_lock); + spin_unlock_irqrestore(&timr->it_lock, *flags); } - spin_unlock_irqrestore(&idr_lock, *flags); + rcu_read_unlock(); return NULL; }