From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933668AbcH2Nt7 (ORCPT ); Mon, 29 Aug 2016 09:49:59 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54126 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933507AbcH2Nt5 (ORCPT ); Mon, 29 Aug 2016 09:49:57 -0400 Date: Mon, 29 Aug 2016 15:48:58 +0200 From: Oleg Nesterov To: Hillf Danton Cc: linux-kernel Subject: Re: [PATCH 2/2] sched/wait: avoid abort_exclusive_wait() in __wait_on_bit_lock() Message-ID: <20160829134857.GA28568@redhat.com> References: <00e501d201cf$7bfecd40$73fc67c0$@alibaba-inc.com> <00e601d201d1$2fbb1c70$8f315550$@alibaba-inc.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <00e601d201d1$2fbb1c70$8f315550$@alibaba-inc.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 29 Aug 2016 13:49:29 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 08/29, Hillf Danton wrote: > > > > On 08/26, Oleg Nesterov wrote: > > __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, > > wait_bit_action_f *action, unsigned mode) > > { > > int ret = 0; > > > > for (;;) { > > prepare_to_wait_exclusive(wq, &q->wait, mode); > > if (test_bit(q->key.bit_nr, q->key.flags)) { > > ret = action(&q->key, mode); > > /* > > * Ensure that clear_bit() + wake_up() right after > > * test_and_set_bit() below can't see us; it should > > * wake up another exclusive waiter if we fail. > > */ > > if (ret) > > finish_wait(wq, &q->wait); > > } > > if (!test_and_set_bit(q->key.bit_nr, q->key.flags)) { > > if (!ret) > > finish_wait(wq, &q->wait); > > return 0; > > } else if (ret) { > > return ret; > > } > > } > > } > > > Can we fold two bit operations into one? Yes, we can, but I am not sure we want. I guess the first test_bit() is optimization to avoid the locked test_and_set_bit() which should likely fail. > __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, > wait_bit_action_f *action, unsigned mode) > { > - do { > - int ret; > + int ret = 0; > > - prepare_to_wait_exclusive(wq, &q->wait, mode); > - if (!test_bit(q->key.bit_nr, q->key.flags)) > - continue; > + prepare_to_wait_exclusive(wq, &q->wait, mode); > + do { > + if (!test_and_set_bit(q->key.bit_nr, q->key.flags)) > + break; > ret = action(&q->key, mode); > - if (!ret) > - continue; > - abort_exclusive_wait(wq, &q->wait, mode, &q->key); > - return ret; > - } while (test_and_set_bit(q->key.bit_nr, q->key.flags)); > + } while (!ret); > + No, no, this is wrong. We can't simply remove abort_exclusive_wait(), please read the comment above this function and the comment added by this patch. And we can't move prepare_to_wait_exclusive() outside of the main loop. Oleg. > finish_wait(wq, &q->wait); > - return 0; > + return ret; > } > EXPORT_SYMBOL(__wait_on_bit_lock); > > -- >