lkml.org 
[lkml]   [2016]   [Dec]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    SubjectRe: [PATCH 2/2] mm: add PageWaiters indicating tasks are waiting for a page bit
    On Tue, Dec 27, 2016 at 11:23 AM, Linus Torvalds
    <torvalds@linux-foundation.org> wrote:
    >
    > Of course, none of this is *tested*, but it looks superficially
    > correct, and allows other architectures to do the same optimization if
    > they want.

    Oops. I should include the actual patch I was talking about too, shouldn't I?

    Linus
    arch/x86/include/asm/bitops.h | 13 +++++++++++++
    include/linux/page-flags.h | 2 +-
    mm/filemap.c | 24 +++++++++++++++++++++---
    3 files changed, 35 insertions(+), 4 deletions(-)

    diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
    index 68557f52b961..34eae484a173 100644
    --- a/arch/x86/include/asm/bitops.h
    +++ b/arch/x86/include/asm/bitops.h
    @@ -139,6 +139,19 @@ static __always_inline void __clear_bit(long nr, volatile unsigned long *addr)
    asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
    }

    +static __always_inline bool clear_bit_unlock_is_negative_byte(long nr, volatile unsigned long *addr)
    +{
    + bool negative;
    + asm volatile(LOCK_PREFIX "andb %2,%1\n\t"
    + CC_SET(s)
    + : CC_OUT(s) (negative), ADDR
    + : "Ir" (1 << nr) : "memory");
    + return negative;
    +}
    +
    +// Let everybody know we have it
    +#define clear_bit_unlock_is_negative_byte clear_bit_unlock_is_negative_byte
    +
    /*
    * __clear_bit_unlock - Clears a bit in memory
    * @nr: Bit to clear
    diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
    index c56b39890a41..6b5818d6de32 100644
    --- a/include/linux/page-flags.h
    +++ b/include/linux/page-flags.h
    @@ -73,13 +73,13 @@
    */
    enum pageflags {
    PG_locked, /* Page is locked. Don't touch. */
    - PG_waiters, /* Page has waiters, check its waitqueue */
    PG_error,
    PG_referenced,
    PG_uptodate,
    PG_dirty,
    PG_lru,
    PG_active,
    + PG_waiters, /* Page has waiters, check its waitqueue. Must be bit #7 and in the same byte as "PG_locked" */
    PG_slab,
    PG_owner_priv_1, /* Owner use. If pagecache, fs may use*/
    PG_arch_1,
    diff --git a/mm/filemap.c b/mm/filemap.c
    index 82f26cde830c..01a2d4a6571c 100644
    --- a/mm/filemap.c
    +++ b/mm/filemap.c
    @@ -912,6 +912,25 @@ void add_page_wait_queue(struct page *page, wait_queue_t *waiter)
    }
    EXPORT_SYMBOL_GPL(add_page_wait_queue);

    +#ifndef clear_bit_unlock_is_negative_byte
    +
    +/*
    + * PG_waiters is the high bit in the same byte as PG_lock.
    + *
    + * On x86 (and on many other architectures), we can clear PG_lock and
    + * test the sign bit at the same time. But if the architecture does
    + * not support that special operation, we just do this all by hand
    + * instead.
    + */
    +static inline bool clear_bit_unlock_is_negative_byte(long nr, volatile void *mem)
    +{
    + clear_bit_unlock(PG_locked, mem);
    + smp_mb__after_atomic();
    + return test_bit(PG_waiters);
    +}
    +
    +#endif
    +
    /**
    * unlock_page - unlock a locked page
    * @page: the page
    @@ -928,9 +947,8 @@ void unlock_page(struct page *page)
    {
    page = compound_head(page);
    VM_BUG_ON_PAGE(!PageLocked(page), page);
    - clear_bit_unlock(PG_locked, &page->flags);
    - smp_mb__after_atomic();
    - wake_up_page(page, PG_locked);
    + if (clear_bit_unlock_is_negative_byte(PG_locked, &page->flags))
    + wake_up_page_bit(page, PG_locked);
    }
    EXPORT_SYMBOL(unlock_page);
    \
     
     \ /
      Last update: 2016-12-27 20:33    [W:15.465 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site