mm: add PageWaiters indicating tasks are waiting for a page bit
authorNicholas Piggin <npiggin@gmail.com>
Sun, 25 Dec 2016 03:00:30 +0000 (13:00 +1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 25 Dec 2016 19:54:48 +0000 (11:54 -0800)
commit62906027091f1d02de44041524f0769f60bb9cf3
tree6444171af03e463bb0123a392d7b91a0ae6a1f40
parent6326fec1122cde256bd2a8c63f2606e08e44ce1d
mm: add PageWaiters indicating tasks are waiting for a page bit

Add a new page flag, PageWaiters, to indicate the page waitqueue has
tasks waiting. This can be tested rather than testing waitqueue_active
which requires another cacheline load.

This bit is always set when the page has tasks on page_waitqueue(page),
and is set and cleared under the waitqueue lock. It may be set when
there are no tasks on the waitqueue, which will cause a harmless extra
wakeup check that will clears the bit.

The generic bit-waitqueue infrastructure is no longer used for pages.
Instead, waitqueues are used directly with a custom key type. The
generic code was not flexible enough to have PageWaiters manipulation
under the waitqueue lock (which simplifies concurrency).

This improves the performance of page lock intensive microbenchmarks by
2-3%.

Putting two bits in the same word opens the opportunity to remove the
memory barrier between clearing the lock bit and testing the waiters
bit, after some work on the arch primitives (e.g., ensuring memory
operand widths match and cover both bits).

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Bob Peterson <rpeterso@redhat.com>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Cc: Andrew Lutomirski <luto@kernel.org>
Cc: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mel Gorman <mgorman@techsingularity.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/mm.h
include/linux/page-flags.h
include/linux/pagemap.h
include/linux/writeback.h
include/trace/events/mmflags.h
init/main.c
mm/filemap.c
mm/internal.h
mm/swap.c