From patchwork Wed Aug 31 10:22:10 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tejun Heo X-Patchwork-Id: 1120592 Received: from smtp1.linux-foundation.org (smtp1.linux-foundation.org [140.211.169.13]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p81KeVQk020522 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Thu, 1 Sep 2011 20:40:59 GMT Received: from daredevil.linux-foundation.org (localhost [127.0.0.1]) by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id p81Kbacp019699; Thu, 1 Sep 2011 13:38:23 -0700 Received: from mail-wy0-f175.google.com (mail-wy0-f175.google.com [74.125.82.175]) by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id p7VAMIpV009212 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=FAIL); Wed, 31 Aug 2011 03:22:21 -0700 Received: by wyf19 with SMTP id 19so375684wyf.6 for ; Wed, 31 Aug 2011 03:22:18 -0700 (PDT) Received: by 10.216.203.79 with SMTP id e57mr249852weo.42.1314786137852; Wed, 31 Aug 2011 03:22:17 -0700 (PDT) Received: from mtj.dyndns.org (apc01.spektrum-hotspot.de [212.77.232.233]) by mx.google.com with ESMTPS id 11sm5352465wbw.26.2011.08.31.03.22.16 (version=SSLv3 cipher=OTHER); Wed, 31 Aug 2011 03:22:17 -0700 (PDT) Date: Wed, 31 Aug 2011 12:22:10 +0200 From: Tejun Heo To: "Rafael J. Wysocki" , Oleg Nesterov , Paul Menage Message-ID: <20110831102210.GC2828@mtj.dyndns.org> References: <20110831102100.GA2828@mtj.dyndns.org> <20110831102143.GB2828@mtj.dyndns.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20110831102143.GB2828@mtj.dyndns.org> User-Agent: Mutt/1.5.21 (2010-09-15) Received-SPF: pass (domain of htejun@gmail.com designates 74.125.82.175 as permitted sender) X-Spam-Status: No, hits=-3.812 required=5 tests=AWL, BAYES_00, OSDL_HEADER_SPF_PASS, OSDL_HEADER_SUBJECT_BRACKETED X-Spam-Checker-Version: SpamAssassin 3.2.4-osdl_revision__1.47__ X-MIMEDefang-Filter: lf$Revision: 1.188 $ X-Scanned-By: MIMEDefang 2.63 on 140.211.169.21 Cc: containers@lists.linux-foundation.org, linux-pm@lists.linux-foundation.org, linux-kernel@vger.kernel.org Subject: [linux-pm] [PATCH pm-freezer 3/4] freezer: restructure __refrigerator() X-BeenThere: linux-pm@lists.linux-foundation.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux power management List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-pm-bounces@lists.linux-foundation.org Errors-To: linux-pm-bounces@lists.linux-foundation.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 01 Sep 2011 20:40:59 +0000 (UTC) If another freeze happens before all tasks leave FROZEN state after being thawed, the freezer can see the existing FROZEN and consider the tasks to be frozen but they can clear FROZEN without checking the new freezing(). Oleg suggested restructuring __refrigerator() such that there's single condition check section inside freezer_lock and sigpending is cleared afterwards, which fixes the problem and simplifies the code. Restructure accordingly. Signed-off-by: Tejun Heo Reported-by: Oleg Nesterov Cc: "Rafael J. Wysocki" --- kernel/freezer.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) Index: work/kernel/freezer.c =================================================================== --- work.orig/kernel/freezer.c +++ work/kernel/freezer.c @@ -52,36 +52,31 @@ bool __refrigerator(bool check_kthr_stop /* Hmm, should we be allowed to suspend when there are realtime processes around? */ bool was_frozen = false; - long save; + long save = current->state; - /* - * No point in checking freezing() again - the caller already did. - * Proceed to enter FROZEN. - */ - spin_lock_irq(&freezer_lock); - current->flags |= PF_FROZEN; - spin_unlock_irq(&freezer_lock); - - save = current->state; pr_debug("%s entered refrigerator\n", current->comm); - spin_lock_irq(¤t->sighand->siglock); - recalc_sigpending(); /* We sent fake signal, clean it up */ - spin_unlock_irq(¤t->sighand->siglock); - for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); + + spin_lock_irq(&freezer_lock); + current->flags |= PF_FROZEN; if (!freezing(current) || - (check_kthr_stop && kthread_should_stop())) + (check_kthr_stop && kthread_should_stop())) { + current->flags &= ~PF_FROZEN; + break; + } + spin_unlock_irq(&freezer_lock); + + if (!(current->flags & PF_FROZEN)) break; was_frozen = true; schedule(); } - /* leave FROZEN */ - spin_lock_irq(&freezer_lock); - current->flags &= ~PF_FROZEN; - spin_unlock_irq(&freezer_lock); + spin_lock_irq(¤t->sighand->siglock); + recalc_sigpending(); /* We sent fake signal, clean it up */ + spin_unlock_irq(¤t->sighand->siglock); pr_debug("%s left refrigerator\n", current->comm);