Skip to content

Instantly share code, notes, and snippets.

@kiryl
Created September 5, 2012 12:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kiryl/3635853 to your computer and use it in GitHub Desktop.
Save kiryl/3635853 to your computer and use it in GitHub Desktop.
static atomic_t huge_zero_refcount;
static unsigned long huge_zero_pfn __read_mostly;
struct page *huge_zero_page __read_mostly;
static void free_huge_zero_page(unsigned long dummy);
static DEFINE_TIMER(huge_zero_timer, free_huge_zero_page, 0, 0);
#define HUGE_ZERO_PAGE_FREE_DELAY (120 * HZ)
static inline bool is_huge_zero_pfn(unsigned long pfn)
{
unsigned long zero_pfn = ACCESS_ONCE(huge_zero_pfn);
return zero_pfn && pfn == zero_pfn;
}
static inline bool is_huge_zero_pmd(pmd_t pmd)
{
return is_huge_zero_pfn(pmd_pfn(pmd));
}
static unsigned long get_huge_zero_page(void)
{
struct page *zero_page;
unsigned long zero_pfn;
retry:
if (likely(atomic_inc_not_zero(&huge_zero_refcount)))
return ACCESS_ONCE(huge_zero_pfn);
del_timer_sync(&huge_zero_timer);
zero_page = ACCESS_ONCE(huge_zero_page);
if (unlikely(!zero_page)) {
zero_page = alloc_pages(GFP_TRANSHUGE | __GFP_ZERO,
HPAGE_PMD_ORDER);
if (!zero_page)
return 0;
if (cmpxchg(&huge_zero_page, NULL, zero_page)) {
__free_page(zero_page);
goto retry;
}
}
cmpxchg(&huge_zero_pfn, 0, page_to_pfn(zero_page));
atomic_inc(&huge_zero_refcount);
return ACCESS_ONCE(huge_zero_pfn);
}
static void put_huge_zero_page(void)
{
if (unlikely(atomic_dec_and_test(&huge_zero_refcount))) {
unsigned long zero_pfn = xchg(&huge_zero_pfn, 0);
BUG_ON(zero_pfn == 0);
mod_timer(&huge_zero_timer,
jiffies + HUGE_ZERO_PAGE_FREE_DELAY);
}
}
static void free_huge_zero_page(unsigned long dummy)
{
struct page *zero_page = xchg(&huge_zero_page, NULL);
BUG_ON(zero_page == NULL);
__free_page(zero_page);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment