linux/include/linux/page_ref.h
<<
>>
Prefs
   1#ifndef _LINUX_PAGE_REF_H
   2#define _LINUX_PAGE_REF_H
   3
   4#include <linux/atomic.h>
   5#include <linux/mm_types.h>
   6#include <linux/page-flags.h>
   7
   8static inline struct page *compound_head_by_tail(struct page *tail)
   9{
  10        struct page *head = tail->first_page;
  11
  12        /*
  13         * page->first_page may be a dangling pointer to an old
  14         * compound page, so recheck that it is still a tail
  15         * page before returning.
  16         */
  17        smp_rmb();
  18        if (likely(PageTail(tail)))
  19                return head;
  20        return tail;
  21}
  22
  23static inline struct page *compound_head(struct page *page)
  24{
  25        if (unlikely(PageTail(page)))
  26                return compound_head_by_tail(page);
  27        return page;
  28}
  29
  30static inline int page_ref_count(struct page *page)
  31{
  32        return atomic_read(&page->_count);
  33}
  34
  35static inline int page_count(struct page *page)
  36{
  37        return atomic_read(&compound_head(page)->_count);
  38}
  39
  40static inline void set_page_count(struct page *page, int v)
  41{
  42        atomic_set(&page->_count, v);
  43}
  44
  45/*
  46 * Setup the page count before being freed into the page allocator for
  47 * the first time (boot or memory hotplug)
  48 */
  49static inline void init_page_count(struct page *page)
  50{
  51        set_page_count(page, 1);
  52}
  53
  54static inline void page_ref_add(struct page *page, int nr)
  55{
  56        atomic_add(nr, &page->_count);
  57}
  58
  59static inline void page_ref_sub(struct page *page, int nr)
  60{
  61        atomic_sub(nr, &page->_count);
  62}
  63
  64static inline void page_ref_inc(struct page *page)
  65{
  66        atomic_inc(&page->_count);
  67}
  68
  69static inline void page_ref_dec(struct page *page)
  70{
  71        atomic_dec(&page->_count);
  72}
  73
  74static inline int page_ref_sub_and_test(struct page *page, int nr)
  75{
  76        return atomic_sub_and_test(nr, &page->_count);
  77}
  78
  79static inline int page_ref_dec_and_test(struct page *page)
  80{
  81        return atomic_dec_and_test(&page->_count);
  82}
  83
  84static inline int page_ref_dec_return(struct page *page)
  85{
  86        return atomic_dec_return(&page->_count);
  87}
  88
  89static inline int page_ref_add_unless(struct page *page, int nr, int u)
  90{
  91        return atomic_add_unless(&page->_count, nr, u);
  92}
  93
  94static inline int page_ref_freeze(struct page *page, int count)
  95{
  96        return likely(atomic_cmpxchg(&page->_count, count, 0) == count);
  97}
  98
  99static inline void page_ref_unfreeze(struct page *page, int count)
 100{
 101        VM_BUG_ON_PAGE(page_count(page) != 0, page);
 102        VM_BUG_ON(count == 0);
 103
 104        atomic_set(&page->_count, count);
 105}
 106
 107#endif
 108