内存管理-38-页标志-2-page_flags.h 展开-6.1

1. 展开文件

enum pageflags {
    PG_locked,
    PG_referenced,
    PG_uptodate,
    PG_dirty,
    PG_lru,
    PG_active,
    PG_workingset,
    PG_waiters,
    PG_error,
    PG_slab,
    PG_owner_priv_1,
    PG_arch_1,
    PG_reserved,
    PG_private,
    PG_private_2,
    PG_writeback,
    PG_head,
    PG_mappedtodisk,
    PG_reclaim,
    PG_swapbacked,
    PG_unevictable,
    PG_mlocked,
    PG_young,
    PG_idle,
    PG_arch_2,
    PG_skip_kasan_poison,
    PG_oem_reserved_1,
    PG_oem_reserved_2,
    PG_oem_reserved_3,
    PG_oem_reserved_4,
    __NR_PAGEFLAGS,
    PG_readahead = PG_reclaim,
    PG_anon_exclusive = PG_mappedtodisk,
    PG_checked = PG_owner_priv_1,
    PG_swapcache = PG_owner_priv_1,
    PG_fscache = PG_private_2,
    PG_pinned = PG_owner_priv_1,
    PG_savepinned = PG_dirty,
    PG_foreign = PG_owner_priv_1,
    PG_xen_remapped = PG_owner_priv_1,
    PG_slob_free = PG_private,
    PG_double_map = PG_workingset,
    PG_isolated = PG_reclaim,
    PG_reported = PG_uptodate,
    PG_vmemmap_self_hosted = PG_owner_priv_1,
};

static inline const struct page *page_fixed_fake_head(const struct page *page)
{
    return page;
}

static __always_inline int page_is_fake_head(struct page *page)
{
    return page_fixed_fake_head(page) != page;
}

static inline unsigned long _compound_head(const struct page *page)
{
    unsigned long head = READ_ONCE(page->compound_head);

    if (unlikely(head & 1))
        return head - 1;
    return (unsigned long)page_fixed_fake_head(page);
}

static __always_inline int PageTail(struct page *page)
{
    return READ_ONCE(page->compound_head) & 1 || page_is_fake_head(page);
}

static __always_inline int PageCompound(struct page *page)
{
    return test_bit(PG_head, &page->flags) || READ_ONCE(page->compound_head) & 1;
}

static inline int PagePoisoned(const struct page *page)
{
    return READ_ONCE(page->flags) == -1l;
}

static inline void page_init_poison(struct page *page, size_t size)
{
}

static unsigned long *folio_flags(struct folio *folio, unsigned n)
{
    struct page *page = &folio->page;

    VM_BUG_ON_PGFLAGS(PageTail(page), page);
    VM_BUG_ON_PGFLAGS(n > 0 && !test_bit(PG_head, &page->flags), page);
    return &page[n].flags;
}

/* 这里面忽略了 VM_BUG_ON_PGFLAGS() 相关的校验,不同的类型校验还不一样, 更准确的改的是 _compound_head(page)->flags,这里为了简便写成 page->flags */
static __always_inline bool folio_test_locked(struct folio *folio) { return test_bit(PG_locked, folio_flags(folio, 0)); } 
static __always_inline int PageLocked(struct page *page) { return test_bit(PG_locked, page->flags); } 
static __always_inline void __folio_set_locked(struct folio *folio) { __set_bit(PG_locked, folio_flags(folio, 0)); }
static __always_inline void __SetPageLocked(struct page *page) { __set_bit(PG_locked, page->flags); }
static __always_inline void __folio_clear_locked(struct folio *folio) { __clear_bit(PG_locked, folio_flags(folio, 0)); }
static __always_inline void __ClearPageLocked(struct page *page) { __clear_bit(PG_locked, page->flags); }

static __always_inline bool folio_test_waiters(struct folio *folio) { return test_bit(PG_waiters, folio_flags(folio, 0)); } 
static __always_inline int PageWaiters(struct page *page) { return test_bit(PG_waiters, page->flags); }
static __always_inline void folio_set_waiters(struct folio *folio) { set_bit(PG_waiters, folio_flags(folio, 0)); } 

static __always_inline void SetPageWaiters(struct page *page) { set_bit(PG_waiters, page->flags); }
static __always_inline void folio_clear_waiters(struct folio *folio) { clear_bit(PG_waiters, folio_flags(folio, 0)); }
static __always_inline void ClearPageWaiters(struct page *page) { clear_bit(PG_waiters, page->flags); }

static __always_inline bool folio_test_error(struct folio *folio) { return test_bit(PG_error, folio_flags(folio, 0)); }
static __always_inline int PageError(struct page *page) { return test_bit(PG_error, pageflags); }
static __always_inline void folio_set_error(struct folio *folio) { set_bit(PG_error, folio_flags(folio, 0)); }
static __always_inline void SetPageError(struct page *page) { set_bit(PG_error, page->flags); }
static __always_inline void folio_clear_error(struct folio *folio) { clear_bit(PG_error, folio_flags(folio, 0)); }
static __always_inline void ClearPageError(struct page *page) { clear_bit(PG_error, page->flags); }
static __always_inline bool folio_test_clear_error(struct folio *folio) { return test_and_clear_bit(PG_error, folio_flags(folio, 0)); }
static __always_inline int TestClearPageError(struct page *page) { return test_and_clear_bit(PG_error, page->flags); }

static __always_inline bool folio_test_referenced(struct folio *folio) { return test_bit(PG_referenced, folio_flags(folio, 0)); }
static __always_inline int PageReferenced(struct page *page) { return test_bit(PG_referenced, page->flags); }
static __always_inline void folio_set_referenced(struct folio *folio) { set_bit(PG_referenced, folio_flags(folio, 0)); }
static __always_inline void SetPageReferenced(struct page *page) { set_bit(PG_referenced, page->flags); }
static __always_inline void folio_clear_referenced(struct folio *folio) { clear_bit(PG_referenced, folio_flags(folio, 0)); }
static __always_inline void ClearPageReferenced(struct page *page) { clear_bit(PG_referenced, page->flags); }
static __always_inline bool folio_test_clear_referenced(struct folio *folio) { return test_and_clear_bit(PG_referenced, folio_flags(folio, 0));
static __always_inline int TestClearPageReferenced(struct page *page) { return test_and_clear_bit(PG_referenced, page->flags); }
static __always_inline void __folio_set_referenced(struct folio *folio) { __set_bit(PG_referenced, folio_flags(folio, 0)); }
static __always_inline void __SetPageReferenced(struct page *page) { __set_bit(PG_referenced, page->flags); }
static __always_inline bool folio_test_dirty(struct folio *folio) { return test_bit(PG_dirty, folio_flags(folio, 0)); }
static __always_inline int PageDirty(struct page *page) { return test_bit(PG_dirty, page->flags); }
static __always_inline void folio_set_dirty(struct folio *folio) { set_bit(PG_dirty, folio_flags(folio, 0)); }
static __always_inline void SetPageDirty(struct page *page) { set_bit(PG_dirty, page->flags); }
static __always_inline void folio_clear_dirty(struct folio *folio) { clear_bit(PG_dirty, folio_flags(folio, 0)); }

static __always_inline void ClearPageDirty(struct page *page) { clear_bit(PG_dirty, page->flags); }

static __always_inline bool folio_test_set_dirty(struct folio *folio) { return test_and_set_bit(PG_dirty, folio_flags(folio, 0)); }

static __always_inline int TestSetPageDirty(struct page *page) { return test_and_set_bit(PG_dirty, page->flags); }

static __always_inline bool folio_test_clear_dirty(struct folio *folio) { return test_and_clear_bit(PG_dirty, folio_flags(folio, 0)); }

static __always_inline int TestClearPageDirty(struct page *page) { return test_and_clear_bit(PG_dirty, page->flags); }
static __always_inline void __folio_clear_dirty(struct folio *folio) { __clear_bit(PG_dirty, folio_flags(folio, 0)); }

static __always_inline void __ClearPageDirty(struct page *page) { __clear_bit(PG_dirty, page->flags); }
static __always_inline bool folio_test_lru(struct folio *folio) { return test_bit(PG_lru, folio_flags(folio, 0)); }

static __always_inline int PageLRU(struct page *page) { return test_bit(PG_lru, page->flags); }

static __always_inline void folio_set_lru(struct folio *folio) { set_bit(PG_lru, folio_flags(folio, 0)); }

static __always_inline void SetPageLRU(struct page *page) { set_bit(PG_lru, page->flags); }

static __always_inline void folio_clear_lru(struct folio *folio) { clear_bit(PG_lru, folio_flags(folio, 0)); }

static __always_inline void ClearPageLRU(struct page *page) { clear_bit(PG_lru, page->flags); }

static __always_inline void __folio_clear_lru(struct folio *folio) { __clear_bit(PG_lru, folio_flags(folio, 0)); }

static __always_inline void __ClearPageLRU(struct page *page) { __clear_bit(PG_lru, page->flags); }
static __always_inline bool folio_test_clear_lru(struct folio *folio) { return test_and_clear_bit(PG_lru, folio_flags(folio, 0)); }

static __always_inline int TestClearPageLRU(struct page *page) { return test_and_clear_bit(PG_lru, page->flags); }
static __always_inline bool folio_test_active(struct folio *folio) { return test_bit(PG_active, folio_flags(folio, 0)); }

static __always_inline int PageActive(struct page *page) { return test_bit(PG_active, page->flags); }

static __always_inline void folio_set_active(struct folio *folio) { set_bit(PG_active, folio_flags(folio, 0)); }

static __always_inline void SetPageActive(struct page *page) { set_bit(PG_active, page->flags); }

static __always_inline void folio_clear_active(struct folio *folio) { clear_bit(PG_active, folio_flags(folio, 0)); }

static __always_inline void ClearPageActive(struct page *page) { clear_bit(PG_active, page->flags); }

static __always_inline void __folio_clear_active(struct folio *folio) { __clear_bit(PG_active, folio_flags(folio, 0)); }

static __always_inline void __ClearPageActive(struct page *page) { __clear_bit(PG_active, page->flags); }
static __always_inline bool folio_test_clear_active(struct folio *folio) { return test_and_clear_bit(PG_active, folio_flags(folio, 0)); }

static __always_inline int TestClearPageActive(struct page *page) { return test_and_clear_bit(PG_active, page->flags); }
static __always_inline bool folio_test_workingset(struct folio *folio) { return test_bit(PG_workingset, folio_flags(folio, 0)); }

static __always_inline int PageWorkingset(struct page *page) { return test_bit(PG_workingset, page->flags); }

static __always_inline void folio_set_workingset(struct folio *folio) { set_bit(PG_workingset, folio_flags(folio, 0)); }

static __always_inline void SetPageWorkingset(struct page *page) { set_bit(PG_workingset, page->flags); }

static __always_inline void folio_clear_workingset(struct folio *folio) { clear_bit(PG_workingset, folio_flags(folio, 0)); }

static __always_inline void ClearPageWorkingset(struct page *page) { clear_bit(PG_workingset, page->flags); }
static __always_inline bool folio_test_clear_workingset(struct folio *folio) { return test_and_clear_bit(PG_workingset, folio_flags(folio, 0)); }

static __always_inline int TestClearPageWorkingset(struct page *page) { return test_and_clear_bit(PG_workingset, page->flags); }
static __always_inline bool folio_test_slab(struct folio *folio) { return test_bit(PG_slab, folio_flags(folio, 0)); }

static __always_inline int PageSlab(struct page *page) { return test_bit(PG_slab, pageflags); }

static __always_inline void __folio_set_slab(struct folio *folio) { __set_bit(PG_slab, folio_flags(folio, 0)); }

static __always_inline void __SetPageSlab(struct page *page) { __set_bit(PG_slab, page->flags); }

static __always_inline void __folio_clear_slab(struct folio *folio) { __clear_bit(PG_slab, folio_flags(folio, 0)); }

static __always_inline void __ClearPageSlab(struct page *page) { __clear_bit(PG_slab, page->flags); }
static __always_inline bool folio_test_slob_free(struct folio *folio) { return test_bit(PG_slob_free, folio_flags(folio, 0)); }

static __always_inline int PageSlobFree(struct page *page) { return test_bit(PG_slob_free, pageflags); }

static __always_inline void __folio_set_slob_free(struct folio *folio) { __set_bit(PG_slob_free, folio_flags(folio, 0)); }

static __always_inline void __SetPageSlobFree(struct page *page) { __set_bit(PG_slob_free, page->flags); }

static __always_inline void __folio_clear_slob_free(struct folio *folio) { __clear_bit(PG_slob_free, folio_flags(folio, 0)); }

static __always_inline void __ClearPageSlobFree(struct page *page) { __clear_bit(PG_slob_free, page->flags); }
static __always_inline bool folio_test_checked(struct folio *folio) { return test_bit(PG_checked, folio_flags(folio, 0)); }

static __always_inline int PageChecked(struct page *page) { return test_bit(PG_checked, page->flags); }

static __always_inline void folio_set_checked(struct folio *folio) { set_bit(PG_checked, folio_flags(folio, 0)); }

static __always_inline void SetPageChecked(struct page *page) { set_bit(PG_checked, page->flags); }

static __always_inline void folio_clear_checked(struct folio *folio) { clear_bit(PG_checked, folio_flags(folio, 0)); }

static __always_inline void ClearPageChecked(struct page *page) { clear_bit(PG_checked, page->flags); }


static __always_inline bool folio_test_pinned(struct folio *folio) { return test_bit(PG_pinned, folio_flags(folio, 0)); }

static __always_inline int PagePinned(struct page *page) { return test_bit(PG_pinned, page->flags); }

static __always_inline void folio_set_pinned(struct folio *folio) { set_bit(PG_pinned, folio_flags(folio, 0)); }

static __always_inline void SetPagePinned(struct page *page) { set_bit(PG_pinned, page->flags); }

static __always_inline void folio_clear_pinned(struct folio *folio) { clear_bit(PG_pinned, folio_flags(folio, 0)); }

static __always_inline void ClearPagePinned(struct page *page) { clear_bit(PG_pinned, page->flags); }
static __always_inline bool folio_test_set_pinned(struct folio *folio) { return test_and_set_bit(PG_pinned, folio_flags(folio, 0)); }

static __always_inline int TestSetPagePinned(struct page *page) { return test_and_set_bit(PG_pinned, page->flags); }

static __always_inline bool folio_test_clear_pinned(struct folio *folio) { return test_and_clear_bit(PG_pinned, folio_flags(folio, 0)); }

static __always_inline int TestClearPagePinned(struct page *page) { return test_and_clear_bit(PG_pinned, page->flags); }
static __always_inline bool folio_test_savepinned(struct folio *folio) { return test_bit(PG_savepinned, folio_flags(folio, 0)); }

static __always_inline int PageSavePinned(struct page *page) { return test_bit(PG_savepinned, page->flags); }

static __always_inline void folio_set_savepinned(struct folio *folio) { set_bit(PG_savepinned, folio_flags(folio, 0)); }

static __always_inline void SetPageSavePinned(struct page *page) { set_bit(PG_savepinned, page->flags); }

static __always_inline void folio_clear_savepinned(struct folio *folio) { clear_bit(PG_savepinned, folio_flags(folio, 0)); }

static __always_inline void ClearPageSavePinned(struct page *page) { clear_bit(PG_savepinned, page->flags); };
static __always_inline bool folio_test_foreign(struct folio *folio) { return test_bit(PG_foreign, folio_flags(folio, 0)); }

static __always_inline int PageForeign(struct page *page) { return test_bit(PG_foreign, page->flags); }

static __always_inline void folio_set_foreign(struct folio *folio) { set_bit(PG_foreign, folio_flags(folio, 0)); }

static __always_inline void SetPageForeign(struct page *page) { set_bit(PG_foreign, page->flags); }

static __always_inline void folio_clear_foreign(struct folio *folio) { clear_bit(PG_foreign, folio_flags(folio, 0)); }

static __always_inline void ClearPageForeign(struct page *page) { clear_bit(PG_foreign, page->flags); };
static __always_inline bool folio_test_xen_remapped(struct folio *folio) { return test_bit(PG_xen_remapped, folio_flags(folio, 0)); }

static __always_inline int PageXenRemapped(struct page *page) { return test_bit(PG_xen_remapped, page->flags); }

static __always_inline void folio_set_xen_remapped(struct folio *folio) { set_bit(PG_xen_remapped, folio_flags(folio, 0)); }

static __always_inline void SetPageXenRemapped(struct page *page) { set_bit(PG_xen_remapped, page->flags); }

static __always_inline void folio_clear_xen_remapped(struct folio *folio) { clear_bit(PG_xen_remapped, folio_flags(folio, 0)); }

static __always_inline void ClearPageXenRemapped(struct page *page) { clear_bit(PG_xen_remapped, page->flags); }
static __always_inline bool folio_test_clear_xen_remapped(struct folio *folio) { return test_and_clear_bit(PG_xen_remapped, folio_flags(folio, 0)); }

static __always_inline int TestClearPageXenRemapped(struct page *page) { return test_and_clear_bit(PG_xen_remapped, page->flags); }

static __always_inline bool folio_test_reserved(struct folio *folio) { return test_bit(PG_reserved, folio_flags(folio, 0)); }

static __always_inline int PageReserved(struct page *page) { return test_bit(PG_reserved, page->flags); }

static __always_inline void folio_set_reserved(struct folio *folio) { set_bit(PG_reserved, folio_flags(folio, 0)); }

static __always_inline void SetPageReserved(struct page *page) { set_bit(PG_reserved, page->flags); }

static __always_inline void folio_clear_reserved(struct folio *folio) { clear_bit(PG_reserved, folio_flags(folio, 0)); }

static __always_inline void ClearPageReserved(struct page *page) { clear_bit(PG_reserved, page->flags); }
static __always_inline void __folio_clear_reserved(struct folio *folio) { __clear_bit(PG_reserved, folio_flags(folio, 0)); }

static __always_inline void __ClearPageReserved(struct page *page) { __clear_bit(PG_reserved, page->flags); }
static __always_inline void __folio_set_reserved(struct folio *folio) { __set_bit(PG_reserved, folio_flags(folio, 0)); }

static __always_inline void __SetPageReserved(struct page *page) { __set_bit(PG_reserved, page->flags); }
static __always_inline bool folio_test_swapbacked(struct folio *folio) { return test_bit(PG_swapbacked, folio_flags(folio, 0)); }

static __always_inline int PageSwapBacked(struct page *page) { return test_bit(PG_swapbacked, pageflags); }

static __always_inline void folio_set_swapbacked(struct folio *folio) { set_bit(PG_swapbacked, folio_flags(folio, 0)); }

static __always_inline void SetPageSwapBacked(struct page *page) { set_bit(PG_swapbacked, page->flags); }

static __always_inline void folio_clear_swapbacked(struct folio *folio) { clear_bit(PG_swapbacked, folio_flags(folio, 0)); }

static __always_inline void ClearPageSwapBacked(struct page *page) { clear_bit(PG_swapbacked, page->flags); }
static __always_inline void __folio_clear_swapbacked(struct folio *folio) { __clear_bit(PG_swapbacked, folio_flags(folio, 0)); }

static __always_inline void __ClearPageSwapBacked(struct page *page) { __clear_bit(PG_swapbacked, page->flags); }
static __always_inline void __folio_set_swapbacked(struct folio *folio) { __set_bit(PG_swapbacked, folio_flags(folio, 0)); }

static __always_inline void __SetPageSwapBacked(struct page *page) { __set_bit(PG_swapbacked, page->flags); }


static __always_inline bool folio_test_private(struct folio *folio) { return test_bit(PG_private, folio_flags(folio, 0)); }

static __always_inline int PagePrivate(struct page *page) { return test_bit(PG_private, page->flags); }

static __always_inline void folio_set_private(struct folio *folio) { set_bit(PG_private, folio_flags(folio, 0)); }

static __always_inline void SetPagePrivate(struct page *page) { set_bit(PG_private, page->flags); }

static __always_inline void folio_clear_private(struct folio *folio) { clear_bit(PG_private, folio_flags(folio, 0)); }

static __always_inline void ClearPagePrivate(struct page *page) { clear_bit(PG_private, page->flags); }
static __always_inline bool folio_test_private_2(struct folio *folio) { return test_bit(PG_private_2, folio_flags(folio, 0)); }

static __always_inline int PagePrivate2(struct page *page) { return test_bit(PG_private_2, page->flags); }

static __always_inline void folio_set_private_2(struct folio *folio) { set_bit(PG_private_2, folio_flags(folio, 0)); }

static __always_inline void SetPagePrivate2(struct page *page) { set_bit(PG_private_2, page->flags); }

static __always_inline void folio_clear_private_2(struct folio *folio) { clear_bit(PG_private_2, folio_flags(folio, 0)); }

static __always_inline void ClearPagePrivate2(struct page *page) { clear_bit(PG_private_2, page->flags); }

static __always_inline bool folio_test_set_private_2(struct folio *folio) { return test_and_set_bit(PG_private_2, folio_flags(folio, 0)); }

static __always_inline int TestSetPagePrivate2(struct page *page) { return test_and_set_bit(PG_private_2, page->flags); }

static __always_inline bool folio_test_clear_private_2(struct folio *folio) { return test_and_clear_bit(PG_private_2, folio_flags(folio, 0)); }

static __always_inline int TestClearPagePrivate2(struct page *page) { return test_and_clear_bit(PG_private_2, page->flags); }
static __always_inline bool folio_test_owner_priv_1(struct folio *folio) { return test_bit(PG_owner_priv_1, folio_flags(folio, 0)); }

static __always_inline int PageOwnerPriv1(struct page *page) { return test_bit(PG_owner_priv_1, page->flags); }

static __always_inline void folio_set_owner_priv_1(struct folio *folio) { set_bit(PG_owner_priv_1, folio_flags(folio, 0)); }

static __always_inline void SetPageOwnerPriv1(struct page *page) { set_bit(PG_owner_priv_1, page->flags); }

static __always_inline void folio_clear_owner_priv_1(struct folio *folio) { clear_bit(PG_owner_priv_1, folio_flags(folio, 0)); }

static __always_inline void ClearPageOwnerPriv1(struct page *page) { clear_bit(PG_owner_priv_1, page->flags); }
static __always_inline bool folio_test_clear_owner_priv_1(struct folio *folio) { return test_and_clear_bit(PG_owner_priv_1, folio_flags(folio, 0)); }

static __always_inline int TestClearPageOwnerPriv1(struct page *page) { return test_and_clear_bit(PG_owner_priv_1, page->flags); }


static __always_inline bool folio_test_writeback(struct folio *folio) { return test_bit(PG_writeback, folio_flags(folio, 0)); }

static __always_inline int PageWriteback(struct page *page) { return test_bit(PG_writeback, pageflags); }
static __always_inline bool folio_test_set_writeback(struct folio *folio) { return test_and_set_bit(PG_writeback, folio_flags(folio, 0)); }

static __always_inline int TestSetPageWriteback(struct page *page) { return test_and_set_bit(PG_writeback, page->flags); }

static __always_inline bool folio_test_clear_writeback(struct folio *folio) { return test_and_clear_bit(PG_writeback, folio_flags(folio, 0)); }

static __always_inline int TestClearPageWriteback(struct page *page) { return test_and_clear_bit(PG_writeback, page->flags); }
static __always_inline bool folio_test_mappedtodisk(struct folio *folio) { return test_bit(PG_mappedtodisk, folio_flags(folio, 0)); }

static __always_inline int PageMappedToDisk(struct page *page) { return test_bit(PG_mappedtodisk, pageflags); }

static __always_inline void folio_set_mappedtodisk(struct folio *folio) { set_bit(PG_mappedtodisk, folio_flags(folio, 0)); }

static __always_inline void SetPageMappedToDisk(struct page *page) { set_bit(PG_mappedtodisk, page->flags); }

static __always_inline void folio_clear_mappedtodisk(struct folio *folio) { clear_bit(PG_mappedtodisk, folio_flags(folio, 0)); }

static __always_inline void ClearPageMappedToDisk(struct page *page) { clear_bit(PG_mappedtodisk, page->flags); }


static __always_inline bool folio_test_reclaim(struct folio *folio) { return test_bit(PG_reclaim, folio_flags(folio, 0)); }

static __always_inline int PageReclaim(struct page *page) { return test_bit(PG_reclaim, pageflags); }

static __always_inline void folio_set_reclaim(struct folio *folio) { set_bit(PG_reclaim, folio_flags(folio, 0)); }

static __always_inline void SetPageReclaim(struct page *page) { set_bit(PG_reclaim, page->flags); }

static __always_inline void folio_clear_reclaim(struct folio *folio) { clear_bit(PG_reclaim, folio_flags(folio, 0)); }

static __always_inline void ClearPageReclaim(struct page *page) { clear_bit(PG_reclaim, page->flags); }
static __always_inline bool folio_test_clear_reclaim(struct folio *folio) { return test_and_clear_bit(PG_reclaim, folio_flags(folio, 0)); }

static __always_inline int TestClearPageReclaim(struct page *page) { return test_and_clear_bit(PG_reclaim, page->flags); }
static __always_inline bool folio_test_readahead(struct folio *folio) { return test_bit(PG_readahead, folio_flags(folio, 0)); }

static __always_inline int PageReadahead(struct page *page) { return test_bit(PG_readahead, page->flags); }

static __always_inline void folio_set_readahead(struct folio *folio) { set_bit(PG_readahead, folio_flags(folio, 0)); }

static __always_inline void SetPageReadahead(struct page *page) { set_bit(PG_readahead, page->flags); }

static __always_inline void folio_clear_readahead(struct folio *folio) { clear_bit(PG_readahead, folio_flags(folio, 0)); }

static __always_inline void ClearPageReadahead(struct page *page) { clear_bit(PG_readahead, page->flags); }
static __always_inline bool folio_test_clear_readahead(struct folio *folio) { return test_and_clear_bit(PG_readahead, folio_flags(folio, 0)); }

static __always_inline int TestClearPageReadahead(struct page *page) { return test_and_clear_bit(PG_readahead, page->flags); }

static inline bool folio_test_highmem(const struct folio *folio) { return false; }

static inline int PageHighMem(const struct page *page) { return 0; }

static inline void folio_set_highmem(struct folio *folio) { }

static inline void SetPageHighMem(struct page *page) { }

static inline void folio_clear_highmem(struct folio *folio) { }

static inline void ClearPageHighMem(struct page *page) { }


static __always_inline bool folio_test_swapcache(struct folio *folio)
{
    return folio_test_swapbacked(folio) && test_bit(PG_swapcache, folio_flags(folio, 0));
}

static __always_inline bool PageSwapCache(struct page *page)
{
    return folio_test_swapcache((_Generic((page), const struct page *: (const struct folio *)_compound_head(page), struct page *: (struct folio *)_compound_head(page))));
}

static __always_inline void folio_set_swapcache(struct folio *folio) { set_bit(PG_swapcache, folio_flags(folio, 0)); }

static __always_inline void SetPageSwapCache(struct page *page) { set_bit(PG_swapcache, page->flags); }
static __always_inline void folio_clear_swapcache(struct folio *folio) { clear_bit(PG_swapcache, folio_flags(folio, 0)); }

static __always_inline void ClearPageSwapCache(struct page *page) { clear_bit(PG_swapcache, page->flags); }


static __always_inline bool folio_test_unevictable(struct folio *folio) { return test_bit(PG_unevictable, folio_flags(folio, 0)); }

static __always_inline int PageUnevictable(struct page *page) { return test_bit(PG_unevictable, page->flags); }

static __always_inline void folio_set_unevictable(struct folio *folio) { set_bit(PG_unevictable, folio_flags(folio, 0)); }

static __always_inline void SetPageUnevictable(struct page *page) { set_bit(PG_unevictable, page->flags); }

static __always_inline void folio_clear_unevictable(struct folio *folio) { clear_bit(PG_unevictable, folio_flags(folio, 0)); }

static __always_inline void ClearPageUnevictable(struct page *page) { clear_bit(PG_unevictable, page->flags); }
static __always_inline void __folio_clear_unevictable(struct folio *folio) { __clear_bit(PG_unevictable, folio_flags(folio, 0)); }

static __always_inline void __ClearPageUnevictable(struct page *page) { __clear_bit(PG_unevictable, page->flags); }
static __always_inline bool folio_test_clear_unevictable(struct folio *folio) { return test_and_clear_bit(PG_unevictable, folio_flags(folio, 0)); }

static __always_inline int TestClearPageUnevictable(struct page *page) { return test_and_clear_bit(PG_unevictable, page->flags); }


static __always_inline bool folio_test_mlocked(struct folio *folio) { return test_bit(PG_mlocked, folio_flags(folio, 0)); }

static __always_inline int PageMlocked(struct page *page) { return test_bit(PG_mlocked, pageflags); }

static __always_inline void folio_set_mlocked(struct folio *folio) { set_bit(PG_mlocked, folio_flags(folio, 0)); }

static __always_inline void SetPageMlocked(struct page *page) { set_bit(PG_mlocked, page->flags); }

static __always_inline void folio_clear_mlocked(struct folio *folio) { clear_bit(PG_mlocked, folio_flags(folio, 0)); }

static __always_inline void ClearPageMlocked(struct page *page) { clear_bit(PG_mlocked, page->flags); }
static __always_inline void __folio_clear_mlocked(struct folio *folio) { __clear_bit(PG_mlocked, folio_flags(folio, 0)); }

static __always_inline void __ClearPageMlocked(struct page *page) { __clear_bit(PG_mlocked, page->flags); }
static __always_inline bool folio_test_set_mlocked(struct folio *folio) { return test_and_set_bit(PG_mlocked, folio_flags(folio, 0)); }

static __always_inline int TestSetPageMlocked(struct page *page) { return test_and_set_bit(PG_mlocked, page->flags); }

static __always_inline bool folio_test_clear_mlocked(struct folio *folio) { return test_and_clear_bit(PG_mlocked, folio_flags(folio, 0)); }

static __always_inline int TestClearPageMlocked(struct page *page) { return test_and_clear_bit(PG_mlocked, page->flags); }

static inline bool folio_test_uncached(const struct folio *folio) { return false; }

static inline int PageUncached(const struct page *page) { return 0; }

static inline void folio_set_uncached(struct folio *folio) { }

static inline void SetPageUncached(struct page *page) { }

static inline void folio_clear_uncached(struct folio *folio) { }

static inline void ClearPageUncached(struct page *page) { }

static inline bool folio_test_hwpoison(const struct folio *folio) { return false; }

static inline int PageHWPoison(const struct page *page) { return 0; }

static inline void folio_set_hwpoison(struct folio *folio) { }

static inline void SetPageHWPoison(struct page *page) { }

static inline void folio_clear_hwpoison(struct folio *folio) { }

static inline void ClearPageHWPoison(struct page *page) { }


static __always_inline bool folio_test_young(struct folio *folio) { return test_bit(PG_young, folio_flags(folio, 0)); }

static __always_inline int PageYoung(struct page *page) { return test_bit(PG_young, page->flags); }
static __always_inline void folio_set_young(struct folio *folio) { set_bit(PG_young, folio_flags(folio, 0)); }

static __always_inline void SetPageYoung(struct page *page) { set_bit(PG_young, page->flags); }
static __always_inline bool folio_test_clear_young(struct folio *folio) { return test_and_clear_bit(PG_young, folio_flags(folio, 0)); }

static __always_inline int TestClearPageYoung(struct page *page) { return test_and_clear_bit(PG_young, page->flags); }
static __always_inline bool folio_test_idle(struct folio *folio) { return test_bit(PG_idle, folio_flags(folio, 0)); }

static __always_inline int PageIdle(struct page *page) { return test_bit(PG_idle, page->flags); }

static __always_inline void folio_set_idle(struct folio *folio) { set_bit(PG_idle, folio_flags(folio, 0)); }

static __always_inline void SetPageIdle(struct page *page) { set_bit(PG_idle, page->flags); }

static __always_inline void folio_clear_idle(struct folio *folio) { clear_bit(PG_idle, folio_flags(folio, 0)); }

static __always_inline void ClearPageIdle(struct page *page) { clear_bit(PG_idle, page->flags); }


static __always_inline bool folio_test_skip_kasan_poison(struct folio *folio) { return test_bit(PG_skip_kasan_poison, folio_flags(folio, 0)); }

static __always_inline int PageSkipKASanPoison(struct page *page) { return test_bit(PG_skip_kasan_poison, page->flags); }

static __always_inline void folio_set_skip_kasan_poison(struct folio *folio) { set_bit(PG_skip_kasan_poison, folio_flags(folio, 0)); }

static __always_inline void SetPageSkipKASanPoison(struct page *page) { set_bit(PG_skip_kasan_poison, page->flags); }

static __always_inline void folio_clear_skip_kasan_poison(struct folio *folio) { clear_bit(PG_skip_kasan_poison, folio_flags(folio, 0)); }

static __always_inline void ClearPageSkipKASanPoison(struct page *page) { clear_bit(PG_skip_kasan_poison, page->flags); }

static __always_inline bool folio_test_reported(struct folio *folio) { return test_bit(PG_reported, folio_flags(folio, 0)); }

static __always_inline int PageReported(struct page *page) { return test_bit(PG_reported, page->flags); }

static __always_inline void __folio_set_reported(struct folio *folio) { __set_bit(PG_reported, folio_flags(folio, 0)); }

static __always_inline void __SetPageReported(struct page *page) { __set_bit(PG_reported, page->flags); }

static __always_inline void __folio_clear_reported(struct folio *folio) { __clear_bit(PG_reported, folio_flags(folio, 0)); }

static __always_inline void __ClearPageReported(struct page *page) { __clear_bit(PG_reported, page->flags); }


static __always_inline bool folio_test_vmemmap_self_hosted(struct folio *folio) { return test_bit(PG_vmemmap_self_hosted, folio_flags(folio, 0)); }

static __always_inline int PageVmemmapSelfHosted(struct page *page) { return test_bit(PG_vmemmap_self_hosted, page->flags); }

static __always_inline void folio_set_vmemmap_self_hosted(struct folio *folio) { set_bit(PG_vmemmap_self_hosted, folio_flags(folio, 0)); }

static __always_inline void SetPageVmemmapSelfHosted(struct page *page) { set_bit(PG_vmemmap_self_hosted, page->flags); }

static __always_inline void folio_clear_vmemmap_self_hosted(struct folio *folio) { clear_bit(PG_vmemmap_self_hosted, folio_flags(folio, 0)); }

static __always_inline void ClearPageVmemmapSelfHosted(struct page *page) { clear_bit(PG_vmemmap_self_hosted, page->flags); }

static __always_inline bool folio_mapping_flags(struct folio *folio)
{
    return ((unsigned long)folio->mapping & (0x1 | 0x2)) != 0;
}

static __always_inline int PageMappingFlags(struct page *page)
{
    return ((unsigned long)page->mapping & (0x1 | 0x2)) != 0;
}

static __always_inline bool folio_test_anon(struct folio *folio)
{
    return ((unsigned long)folio->mapping & 0x1) != 0;
}

static __always_inline bool PageAnon(struct page *page)
{
    return folio_test_anon((_Generic((page), const struct page *: (const struct folio *)_compound_head(page), struct page *: (struct folio *)_compound_head(page))));
}

static __always_inline bool __folio_test_movable(const struct folio *folio)
{
    return ((unsigned long)folio->mapping & PAGE_MAPPING_FLAGS) == PAGE_MAPPING_MOVABLE;
}

static __always_inline int __PageMovable(struct page *page)
{
    return ((unsigned long)page->mapping & PAGE_MAPPING_FLAGS) == PAGE_MAPPING_MOVABLE;
}

static inline bool folio_test_ksm(const struct folio *folio) { return false; }

static inline int PageKsm(const struct page *page) { return 0; }


u64 stable_page_flags(struct page *page);

static inline bool folio_test_uptodate(struct folio *folio)
{
    bool ret = test_bit(PG_uptodate, folio_flags(folio, 0));

    if (ret)
        smp_rmb();

    return ret;
}

static inline int PageUptodate(struct page *page)
{
    return folio_test_uptodate((_Generic((page), const struct page *: (const struct folio *)_compound_head(page), struct page *: (struct folio *)_compound_head(page))));
}

static __always_inline void __folio_mark_uptodate(struct folio *folio)
{
    smp_wmb();
    __set_bit(PG_uptodate, folio_flags(folio, 0));
}

static __always_inline void folio_mark_uptodate(struct folio *folio)
{
    smp_wmb();
    set_bit(PG_uptodate, folio_flags(folio, 0));
}

static __always_inline void __SetPageUptodate(struct page *page)
{
    __folio_mark_uptodate((struct folio *)page);
}

static __always_inline void SetPageUptodate(struct page *page)
{
    folio_mark_uptodate((struct folio *)page);
}

static __always_inline void folio_clear_uptodate(struct folio *folio) { clear_bit(PG_uptodate, folio_flags(folio, 0)); }

static __always_inline void ClearPageUptodate(struct page *page) { clear_bit(PG_uptodate, page->flags); }

bool __folio_start_writeback(struct folio *folio, bool keep_write);
bool set_page_writeback(struct page *page);


static inline void set_page_writeback_keepwrite(struct page *page)
{
    __folio_start_writeback((_Generic((page), const struct page *: (const struct folio *)_compound_head(page), struct page *: (struct folio *)_compound_head(page))), true);
}

static inline bool test_set_page_writeback(struct page *page)
{
    return set_page_writeback(page);
}

static __always_inline bool folio_test_head(struct folio *folio)
{
    return test_bit(PG_head, folio_flags(folio, 0));
}

static __always_inline int PageHead(struct page *page)
{
    ({ VM_BUG_ON_PGFLAGS(PagePoisoned(page), page); page; });
    return test_bit(PG_head, &page->flags) && !page_is_fake_head(page);
}

static __always_inline void __folio_set_head(struct folio *folio) { __set_bit(PG_head, folio_flags(folio, 0)); }

static __always_inline void __SetPageHead(struct page *page) { __set_bit(PG_head, page->flags); }
static __always_inline void __folio_clear_head(struct folio *folio) { __clear_bit(PG_head, folio_flags(folio, 0)); }

static __always_inline void __ClearPageHead(struct page *page) { __clear_bit(PG_head, page->flags); }
static __always_inline void folio_clear_head(struct folio *folio) { clear_bit(PG_head, folio_flags(folio, 0)); }

static __always_inline void ClearPageHead(struct page *page) { clear_bit(PG_head, page->flags); }


static inline bool folio_test_large(struct folio *folio)
{
    return folio_test_head(folio);
}

static __always_inline void set_compound_head(struct page *page, struct page *head)
{
    WRITE_ONCE(page->compound_head, (unsigned long)head + 1);
}

static __always_inline void clear_compound_head(struct page *page)
{
    WRITE_ONCE(page->compound_head, 0);
}


static inline void ClearPageCompound(struct page *page)
{
    BUG_ON(!PageHead(page));
    ClearPageHead(page);
}

static inline bool folio_test_hugetlb(const struct folio *folio) { return false; }

static inline int PageHuge(const struct page *page) { return 0; }
static inline bool folio_test_headhuge(const struct folio *folio) { return false; }

static inline int PageHeadHuge(const struct page *page) { return 0; }

static inline int PageTransHuge(struct page *page)
{
    VM_BUG_ON_PAGE(PageTail(page), page);
    return PageHead(page);
}

static inline bool folio_test_transhuge(struct folio *folio)
{
    return folio_test_head(folio);
}


static inline int PageTransCompound(struct page *page)
{
 return PageCompound(page);
}

static inline int PageTransTail(struct page *page)
{
 return PageTail(page);
}

static __always_inline bool folio_test_double_map(struct folio *folio) { return test_bit(PG_double_map, folio_flags(folio, 1)); }

static __always_inline int PageDoubleMap(struct page *page) { return test_bit(PG_double_map, page->flags); }

static __always_inline void folio_set_double_map(struct folio *folio) { set_bit(PG_double_map, folio_flags(folio, 1)); }

static __always_inline void SetPageDoubleMap(struct page *page) { set_bit(PG_double_map, page->flags); }

static __always_inline void folio_clear_double_map(struct folio *folio) { clear_bit(PG_double_map, folio_flags(folio, 1)); }

static __always_inline void ClearPageDoubleMap(struct page *page) { clear_bit(PG_double_map, page->flags); }
static __always_inline bool folio_test_set_double_map(struct folio *folio) { return test_and_set_bit(PG_double_map, folio_flags(folio, 1)); }

static __always_inline int TestSetPageDoubleMap(struct page *page) { return test_and_set_bit(PG_double_map, page->flags); }

static __always_inline bool folio_test_clear_double_map(struct folio *folio) { return test_and_clear_bit(PG_double_map, folio_flags(folio, 1)); }

static __always_inline int TestClearPageDoubleMap(struct page *page) { return test_and_clear_bit(PG_double_map, page->flags); }

static inline bool folio_test_has_hwpoisoned(const struct folio *folio) { return false; }

static inline int PageHasHWPoisoned(const struct page *page) { return 0; }

static inline void folio_set_has_hwpoisoned(struct folio *folio) { }

static inline void SetPageHasHWPoisoned(struct page *page) { }

static inline void folio_clear_has_hwpoisoned(struct folio *folio) { }

static inline void ClearPageHasHWPoisoned(struct page *page) { }
static inline bool folio_test_set_has_hwpoisoned(struct folio *folio) { return 0; }

static inline int TestSetPageHasHWPoisoned(struct page *page) { return 0; }

static inline bool folio_test_clear_has_hwpoisoned(struct folio *folio) { return 0; }

static inline int TestClearPageHasHWPoisoned(struct page *page) { return 0; }

static inline bool is_page_hwpoison(struct page *page)
{
    if (PageHWPoison(page))
        return true;
    return PageHuge(page) && PageHWPoison(((typeof(page))_compound_head(page)));
}

static inline int page_has_type(struct page *page)
{
    return (int)page->page_type < -128;
}

static __always_inline int PageBuddy(struct page *page) { return ((page->page_type & (PAGE_TYPE_BASE | PG_buddy)) == PAGE_TYPE_BASE); }

static __always_inline void __SetPageBuddy(struct page *page) { VM_BUG_ON_PAGE(!((page->page_type & (PAGE_TYPE_BASE | 0)) == PAGE_TYPE_BASE), page); page->page_type &= ~PG_buddy; }

static __always_inline void __ClearPageBuddy(struct page *page) { VM_BUG_ON_PAGE(!PageBuddy(page), page); page->page_type |= PG_buddy; }

static __always_inline int PageOffline(struct page *page) { return ((page->page_type & (PAGE_TYPE_BASE | PG_offline)) == PAGE_TYPE_BASE); }

static __always_inline void __SetPageOffline(struct page *page) { VM_BUG_ON_PAGE(!((page->page_type & (PAGE_TYPE_BASE | 0)) == PAGE_TYPE_BASE), page); page->page_type &= ~PG_offline; }

static __always_inline void __ClearPageOffline(struct page *page) { VM_BUG_ON_PAGE(!PageOffline(page), page); page->page_type |= PG_offline; }

extern void page_offline_freeze(void);
extern void page_offline_thaw(void);
extern void page_offline_begin(void);
extern void page_offline_end(void);




static __always_inline int PageTable(struct page *page) { return ((page->page_type & (PAGE_TYPE_BASE | PG_table)) == PAGE_TYPE_BASE); }

static __always_inline void __SetPageTable(struct page *page) { VM_BUG_ON_PAGE(!((page->page_type & (PAGE_TYPE_BASE | 0)) == PAGE_TYPE_BASE), page); page->page_type &= ~PG_table; }

static __always_inline void __ClearPageTable(struct page *page) { VM_BUG_ON_PAGE(!PageTable(page), page); page->page_type |= PG_table; }




static __always_inline int PageGuard(struct page *page) { return ((page->page_type & (PAGE_TYPE_BASE | PG_guard)) == PAGE_TYPE_BASE); }

static __always_inline void __SetPageGuard(struct page *page) { VM_BUG_ON_PAGE(!((page->page_type & (PAGE_TYPE_BASE | 0)) == PAGE_TYPE_BASE), page); page->page_type &= ~PG_guard; }

static __always_inline void __ClearPageGuard(struct page *page) { VM_BUG_ON_PAGE(!PageGuard(page), page); page->page_type |= PG_guard; }

extern bool is_free_buddy_page(struct page *page);

static __always_inline bool folio_test_isolated(struct folio *folio) { return test_bit(PG_isolated, folio_flags(folio, 0)); }

static __always_inline int PageIsolated(struct page *page) { return test_bit(PG_isolated, page->flags); }

static __always_inline void folio_set_isolated(struct folio *folio) { set_bit(PG_isolated, folio_flags(folio, 0)); }

static __always_inline void SetPageIsolated(struct page *page) { set_bit(PG_isolated, page->flags); }

static __always_inline void folio_clear_isolated(struct folio *folio) { clear_bit(PG_isolated, folio_flags(folio, 0)); }

static __always_inline void ClearPageIsolated(struct page *page) { clear_bit(PG_isolated, page->flags); };

static __always_inline int PageAnonExclusive(struct page *page)
{
    VM_BUG_ON_PGFLAGS(!PageAnon(page), page);
    VM_BUG_ON_PGFLAGS(PageHuge(page) && !PageHead(page), page);
    return test_bit(PG_anon_exclusive, page->flags);
}

static __always_inline void SetPageAnonExclusive(struct page *page)
{
    VM_BUG_ON_PGFLAGS(!PageAnon(page) || PageKsm(page), page);
    VM_BUG_ON_PGFLAGS(PageHuge(page) && !PageHead(page), page);
    set_bit(PG_anon_exclusive, page->flags);
}

static __always_inline void ClearPageAnonExclusive(struct page *page)
{
    VM_BUG_ON_PGFLAGS(!PageAnon(page) || PageKsm(page), page);
    VM_BUG_ON_PGFLAGS(PageHuge(page) && !PageHead(page), page);
    clear_bit(PG_anon_exclusive, page->flags);
}

static __always_inline void __ClearPageAnonExclusive(struct page *page)
{
    VM_BUG_ON_PGFLAGS(!PageAnon(page), page);
    VM_BUG_ON_PGFLAGS(PageHuge(page) && !PageHead(page), page);
    __clear_bit(PG_anon_exclusive, page->flags);
}

static inline int page_has_private(struct page *page)
{
    return !!(page->flags & (1UL << PG_private | 1UL << PG_private_2));
}

static inline bool folio_has_private(struct folio *folio)
{
    return page_has_private(&folio->page);
}

 

2. 特殊实现

2.1 PageUptodate
/*
 * PageUptodate - 检查给定 page 的 PG_uptodate 标志是否置位
 *
 * PG_uptodate 的语义:该页面的内容是"最新的"(与磁盘/来源一致、已被正确填充)。
 *   - 对 page cache:读操作完成后置位,表示页面数据有效可直接使用
 *   - 对新分配的匿名页:COW 复制完成后由 __SetPageUptodate 置位
 *   - 未置位时:页面内容可能是垃圾数据,不能返回给用户态
 *
 * 参数:
 *   page - 待检查的 struct page 指针(可能是 compound page 的 tail page)
 *
 * 返回值:
 *   非零 = uptodate(内容有效)
 *   0    = 不是 uptodate(内容无效/正在加载)
 */
static inline int PageUptodate(struct page *page)
{
    /*
     * 拆解这条复杂表达式:
     *
     * 第一层:_compound_head(page)
     *   若 page 是 compound page 的 tail page,返回其 head page 指针;
     *   若 page 本身就是 head page 或普通页,返回自身。
     *   原因:PG_uptodate 标志只存储在 head page 的 flags 中(PF_HEAD 策略),对 tail page
     *   查询时必须先回溯到 head page。
     *
     * 第二层:_Generic(...)
     *   C11 泛型选择表达式,根据 page 参数的 const 修饰情况,将 _compound_head 返回的 struct page* 转
     *   换为对应的 struct folio*:
     *     - page 是 const struct page* --> 转换为 const struct folio*
     *     - page 是 struct page*       --> 转换为 struct folio*
     *   目的:保持 const 正确性(const 输入不会产生非 const 的 folio 指针),同时消除编译器的 const 丢弃警告。
     *
     *   struct folio 实质上就是 struct page 的第一个成员(头页),二者地址相同,这个强制转换在内存布局上是安全的。
     *
     * 第三层:folio_test_uptodate(folio)
     *   测试 folio(即 head page)的 PG_uptodate 标志位。
     *   由 PAGEFLAG 宏体系生成,本质是:test_bit(PG_uptodate, &folio->page.flags)
     *
     * 整体等价于(伪代码):
     *   head = compound_head(page);
     *   return test_bit(PG_uptodate, &head->flags);
     */
    return folio_test_uptodate(
        (_Generic((page),
            const struct page *: (const struct folio *)_compound_head(page),
            struct page *:       (struct folio *)_compound_head(page)
        ))
    );
}

 

2.2 PageLocked

实际定位为:

static __always_inline int PageLocked(struct page *page) {
    return test_bit(PG_locked, &({
            VM_BUG_ON_PGFLAGS(0 && PageTail(page), page);
            ({
                VM_BUG_ON_PGFLAGS(PagePoisoned(((typeof(page))_compound_head(page))), ((typeof(page))_compound_head(page)));
                ((typeof(page))_compound_head(page));
            });
    })->flags);
}

 

posted on 2026-08-06 21:02  Hello-World3  阅读(7)  评论(0)    收藏  举报

导航