aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mm.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r--include/linux/mm.h132
1 files changed, 106 insertions, 26 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 8b6e55ee8855..8aa4006b9636 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -297,12 +297,26 @@ static inline int put_page_testzero(struct page *page)
297/* 297/*
298 * Try to grab a ref unless the page has a refcount of zero, return false if 298 * Try to grab a ref unless the page has a refcount of zero, return false if
299 * that is the case. 299 * that is the case.
300 * This can be called when MMU is off so it must not access
301 * any of the virtual mappings.
300 */ 302 */
301static inline int get_page_unless_zero(struct page *page) 303static inline int get_page_unless_zero(struct page *page)
302{ 304{
303 return atomic_inc_not_zero(&page->_count); 305 return atomic_inc_not_zero(&page->_count);
304} 306}
305 307
308/*
309 * Try to drop a ref unless the page has a refcount of one, return false if
310 * that is the case.
311 * This is to make sure that the refcount won't become zero after this drop.
312 * This can be called when MMU is off so it must not access
313 * any of the virtual mappings.
314 */
315static inline int put_page_unless_one(struct page *page)
316{
317 return atomic_add_unless(&page->_count, -1, 1);
318}
319
306extern int page_is_ram(unsigned long pfn); 320extern int page_is_ram(unsigned long pfn);
307 321
308/* Support for virtually mapped pages */ 322/* Support for virtually mapped pages */
@@ -581,11 +595,11 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
581 * sets it, so none of the operations on it need to be atomic. 595 * sets it, so none of the operations on it need to be atomic.
582 */ 596 */
583 597
584/* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_NID] | ... | FLAGS | */ 598/* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_CPUPID] | ... | FLAGS | */
585#define SECTIONS_PGOFF ((sizeof(unsigned long)*8) - SECTIONS_WIDTH) 599#define SECTIONS_PGOFF ((sizeof(unsigned long)*8) - SECTIONS_WIDTH)
586#define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH) 600#define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH)
587#define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) 601#define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH)
588#define LAST_NID_PGOFF (ZONES_PGOFF - LAST_NID_WIDTH) 602#define LAST_CPUPID_PGOFF (ZONES_PGOFF - LAST_CPUPID_WIDTH)
589 603
590/* 604/*
591 * Define the bit shifts to access each section. For non-existent 605 * Define the bit shifts to access each section. For non-existent
@@ -595,7 +609,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
595#define SECTIONS_PGSHIFT (SECTIONS_PGOFF * (SECTIONS_WIDTH != 0)) 609#define SECTIONS_PGSHIFT (SECTIONS_PGOFF * (SECTIONS_WIDTH != 0))
596#define NODES_PGSHIFT (NODES_PGOFF * (NODES_WIDTH != 0)) 610#define NODES_PGSHIFT (NODES_PGOFF * (NODES_WIDTH != 0))
597#define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_WIDTH != 0)) 611#define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_WIDTH != 0))
598#define LAST_NID_PGSHIFT (LAST_NID_PGOFF * (LAST_NID_WIDTH != 0)) 612#define LAST_CPUPID_PGSHIFT (LAST_CPUPID_PGOFF * (LAST_CPUPID_WIDTH != 0))
599 613
600/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */ 614/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */
601#ifdef NODE_NOT_IN_PAGE_FLAGS 615#ifdef NODE_NOT_IN_PAGE_FLAGS
@@ -617,7 +631,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
617#define ZONES_MASK ((1UL << ZONES_WIDTH) - 1) 631#define ZONES_MASK ((1UL << ZONES_WIDTH) - 1)
618#define NODES_MASK ((1UL << NODES_WIDTH) - 1) 632#define NODES_MASK ((1UL << NODES_WIDTH) - 1)
619#define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1) 633#define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1)
620#define LAST_NID_MASK ((1UL << LAST_NID_WIDTH) - 1) 634#define LAST_CPUPID_MASK ((1UL << LAST_CPUPID_WIDTH) - 1)
621#define ZONEID_MASK ((1UL << ZONEID_SHIFT) - 1) 635#define ZONEID_MASK ((1UL << ZONEID_SHIFT) - 1)
622 636
623static inline enum zone_type page_zonenum(const struct page *page) 637static inline enum zone_type page_zonenum(const struct page *page)
@@ -661,51 +675,117 @@ static inline int page_to_nid(const struct page *page)
661#endif 675#endif
662 676
663#ifdef CONFIG_NUMA_BALANCING 677#ifdef CONFIG_NUMA_BALANCING
664#ifdef LAST_NID_NOT_IN_PAGE_FLAGS 678static inline int cpu_pid_to_cpupid(int cpu, int pid)
665static inline int page_nid_xchg_last(struct page *page, int nid)
666{ 679{
667 return xchg(&page->_last_nid, nid); 680 return ((cpu & LAST__CPU_MASK) << LAST__PID_SHIFT) | (pid & LAST__PID_MASK);
668} 681}
669 682
670static inline int page_nid_last(struct page *page) 683static inline int cpupid_to_pid(int cpupid)
671{ 684{
672 return page->_last_nid; 685 return cpupid & LAST__PID_MASK;
673} 686}
674static inline void page_nid_reset_last(struct page *page) 687
688static inline int cpupid_to_cpu(int cpupid)
675{ 689{
676 page->_last_nid = -1; 690 return (cpupid >> LAST__PID_SHIFT) & LAST__CPU_MASK;
677} 691}
678#else 692
679static inline int page_nid_last(struct page *page) 693static inline int cpupid_to_nid(int cpupid)
694{
695 return cpu_to_node(cpupid_to_cpu(cpupid));
696}
697
698static inline bool cpupid_pid_unset(int cpupid)
680{ 699{
681 return (page->flags >> LAST_NID_PGSHIFT) & LAST_NID_MASK; 700 return cpupid_to_pid(cpupid) == (-1 & LAST__PID_MASK);
682} 701}
683 702
684extern int page_nid_xchg_last(struct page *page, int nid); 703static inline bool cpupid_cpu_unset(int cpupid)
704{
705 return cpupid_to_cpu(cpupid) == (-1 & LAST__CPU_MASK);
706}
707
708static inline bool __cpupid_match_pid(pid_t task_pid, int cpupid)
709{
710 return (task_pid & LAST__PID_MASK) == cpupid_to_pid(cpupid);
711}
685 712
686static inline void page_nid_reset_last(struct page *page) 713#define cpupid_match_pid(task, cpupid) __cpupid_match_pid(task->pid, cpupid)
714#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
715static inline int page_cpupid_xchg_last(struct page *page, int cpupid)
687{ 716{
688 int nid = (1 << LAST_NID_SHIFT) - 1; 717 return xchg(&page->_last_cpupid, cpupid);
718}
689 719
690 page->flags &= ~(LAST_NID_MASK << LAST_NID_PGSHIFT); 720static inline int page_cpupid_last(struct page *page)
691 page->flags |= (nid & LAST_NID_MASK) << LAST_NID_PGSHIFT; 721{
722 return page->_last_cpupid;
723}
724static inline void page_cpupid_reset_last(struct page *page)
725{
726 page->_last_cpupid = -1;
692} 727}
693#endif /* LAST_NID_NOT_IN_PAGE_FLAGS */
694#else 728#else
695static inline int page_nid_xchg_last(struct page *page, int nid) 729static inline int page_cpupid_last(struct page *page)
696{ 730{
697 return page_to_nid(page); 731 return (page->flags >> LAST_CPUPID_PGSHIFT) & LAST_CPUPID_MASK;
698} 732}
699 733
700static inline int page_nid_last(struct page *page) 734extern int page_cpupid_xchg_last(struct page *page, int cpupid);
735
736static inline void page_cpupid_reset_last(struct page *page)
701{ 737{
702 return page_to_nid(page); 738 int cpupid = (1 << LAST_CPUPID_SHIFT) - 1;
739
740 page->flags &= ~(LAST_CPUPID_MASK << LAST_CPUPID_PGSHIFT);
741 page->flags |= (cpupid & LAST_CPUPID_MASK) << LAST_CPUPID_PGSHIFT;
742}
743#endif /* LAST_CPUPID_NOT_IN_PAGE_FLAGS */
744#else /* !CONFIG_NUMA_BALANCING */
745static inline int page_cpupid_xchg_last(struct page *page, int cpupid)
746{
747 return page_to_nid(page); /* XXX */
703} 748}
704 749
705static inline void page_nid_reset_last(struct page *page) 750static inline int page_cpupid_last(struct page *page)
706{ 751{
752 return page_to_nid(page); /* XXX */
707} 753}
708#endif 754
755static inline int cpupid_to_nid(int cpupid)
756{
757 return -1;
758}
759
760static inline int cpupid_to_pid(int cpupid)
761{
762 return -1;
763}
764
765static inline int cpupid_to_cpu(int cpupid)
766{
767 return -1;
768}
769
770static inline int cpu_pid_to_cpupid(int nid, int pid)
771{
772 return -1;
773}
774
775static inline bool cpupid_pid_unset(int cpupid)
776{
777 return 1;
778}
779
780static inline void page_cpupid_reset_last(struct page *page)
781{
782}
783
784static inline bool cpupid_match_pid(struct task_struct *task, int cpupid)
785{
786 return false;
787}
788#endif /* CONFIG_NUMA_BALANCING */
709 789
710static inline struct zone *page_zone(const struct page *page) 790static inline struct zone *page_zone(const struct page *page)
711{ 791{