summaryrefslogtreecommitdiffstats
path: root/include/linux/pagemap.h
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2016-12-24 22:00:30 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-25 14:54:48 -0500
commit62906027091f1d02de44041524f0769f60bb9cf3 (patch)
tree6444171af03e463bb0123a392d7b91a0ae6a1f40 /include/linux/pagemap.h
parent6326fec1122cde256bd2a8c63f2606e08e44ce1d (diff)
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>
Diffstat (limited to 'include/linux/pagemap.h')
-rw-r--r--include/linux/pagemap.h23
1 files changed, 11 insertions, 12 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index f29f80f81dbf..324c8dbad1e1 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -486,22 +486,14 @@ static inline int lock_page_or_retry(struct page *page, struct mm_struct *mm,
486 * and for filesystems which need to wait on PG_private. 486 * and for filesystems which need to wait on PG_private.
487 */ 487 */
488extern void wait_on_page_bit(struct page *page, int bit_nr); 488extern void wait_on_page_bit(struct page *page, int bit_nr);
489
490extern int wait_on_page_bit_killable(struct page *page, int bit_nr); 489extern int wait_on_page_bit_killable(struct page *page, int bit_nr);
491extern int wait_on_page_bit_killable_timeout(struct page *page, 490extern void wake_up_page_bit(struct page *page, int bit_nr);
492 int bit_nr, unsigned long timeout);
493
494static inline int wait_on_page_locked_killable(struct page *page)
495{
496 if (!PageLocked(page))
497 return 0;
498 return wait_on_page_bit_killable(compound_head(page), PG_locked);
499}
500 491
501extern wait_queue_head_t *page_waitqueue(struct page *page);
502static inline void wake_up_page(struct page *page, int bit) 492static inline void wake_up_page(struct page *page, int bit)
503{ 493{
504 __wake_up_bit(page_waitqueue(page), &page->flags, bit); 494 if (!PageWaiters(page))
495 return;
496 wake_up_page_bit(page, bit);
505} 497}
506 498
507/* 499/*
@@ -517,6 +509,13 @@ static inline void wait_on_page_locked(struct page *page)
517 wait_on_page_bit(compound_head(page), PG_locked); 509 wait_on_page_bit(compound_head(page), PG_locked);
518} 510}
519 511
512static inline int wait_on_page_locked_killable(struct page *page)
513{
514 if (!PageLocked(page))
515 return 0;
516 return wait_on_page_bit_killable(compound_head(page), PG_locked);
517}
518
520/* 519/*
521 * Wait for a page to complete writeback 520 * Wait for a page to complete writeback
522 */ 521 */