Created
September 5, 2012 12:24
-
-
Save kiryl/3635853 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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