diff options
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r-- | include/linux/mm.h | 132 |
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 | */ |
301 | static inline int get_page_unless_zero(struct page *page) | 303 | static 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 | */ | ||
315 | static inline int put_page_unless_one(struct page *page) | ||
316 | { | ||
317 | return atomic_add_unless(&page->_count, -1, 1); | ||
318 | } | ||
319 | |||
306 | extern int page_is_ram(unsigned long pfn); | 320 | extern 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 | ||
623 | static inline enum zone_type page_zonenum(const struct page *page) | 637 | static 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 | 678 | static inline int cpu_pid_to_cpupid(int cpu, int pid) |
665 | static 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 | ||
670 | static inline int page_nid_last(struct page *page) | 683 | static inline int cpupid_to_pid(int cpupid) |
671 | { | 684 | { |
672 | return page->_last_nid; | 685 | return cpupid & LAST__PID_MASK; |
673 | } | 686 | } |
674 | static inline void page_nid_reset_last(struct page *page) | 687 | |
688 | static 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 | |
679 | static inline int page_nid_last(struct page *page) | 693 | static inline int cpupid_to_nid(int cpupid) |
694 | { | ||
695 | return cpu_to_node(cpupid_to_cpu(cpupid)); | ||
696 | } | ||
697 | |||
698 | static 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 | ||
684 | extern int page_nid_xchg_last(struct page *page, int nid); | 703 | static inline bool cpupid_cpu_unset(int cpupid) |
704 | { | ||
705 | return cpupid_to_cpu(cpupid) == (-1 & LAST__CPU_MASK); | ||
706 | } | ||
707 | |||
708 | static 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 | ||
686 | static 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 | ||
715 | static 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); | 720 | static 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 | } | ||
724 | static 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 |
695 | static inline int page_nid_xchg_last(struct page *page, int nid) | 729 | static 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 | ||
700 | static inline int page_nid_last(struct page *page) | 734 | extern int page_cpupid_xchg_last(struct page *page, int cpupid); |
735 | |||
736 | static 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 */ | ||
745 | static inline int page_cpupid_xchg_last(struct page *page, int cpupid) | ||
746 | { | ||
747 | return page_to_nid(page); /* XXX */ | ||
703 | } | 748 | } |
704 | 749 | ||
705 | static inline void page_nid_reset_last(struct page *page) | 750 | static inline int page_cpupid_last(struct page *page) |
706 | { | 751 | { |
752 | return page_to_nid(page); /* XXX */ | ||
707 | } | 753 | } |
708 | #endif | 754 | |
755 | static inline int cpupid_to_nid(int cpupid) | ||
756 | { | ||
757 | return -1; | ||
758 | } | ||
759 | |||
760 | static inline int cpupid_to_pid(int cpupid) | ||
761 | { | ||
762 | return -1; | ||
763 | } | ||
764 | |||
765 | static inline int cpupid_to_cpu(int cpupid) | ||
766 | { | ||
767 | return -1; | ||
768 | } | ||
769 | |||
770 | static inline int cpu_pid_to_cpupid(int nid, int pid) | ||
771 | { | ||
772 | return -1; | ||
773 | } | ||
774 | |||
775 | static inline bool cpupid_pid_unset(int cpupid) | ||
776 | { | ||
777 | return 1; | ||
778 | } | ||
779 | |||
780 | static inline void page_cpupid_reset_last(struct page *page) | ||
781 | { | ||
782 | } | ||
783 | |||
784 | static inline bool cpupid_match_pid(struct task_struct *task, int cpupid) | ||
785 | { | ||
786 | return false; | ||
787 | } | ||
788 | #endif /* CONFIG_NUMA_BALANCING */ | ||
709 | 789 | ||
710 | static inline struct zone *page_zone(const struct page *page) | 790 | static inline struct zone *page_zone(const struct page *page) |
711 | { | 791 | { |