#include <asm/tlb.h>
#include <asm/tlbflush.h>
+#include <linux/sysctl.h>
+
static long htlbpagemem;
int htlbpage_max;
static long htlbzone_pages;
return alloc_shared_hugetlb_pages(key, addr, len, prot, flag);
return alloc_private_hugetlb_pages(key, addr, len, prot, flag);
}
+void update_and_free_page(struct page *page)
+{
+ int j;
+ struct page *map;
+
+ map = page;
+ htlbzone_pages--;
+ for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) {
+ map->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
+ 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
+ 1 << PG_private | 1<< PG_writeback);
+ set_page_count(map, 0);
+ map++;
+ }
+ set_page_count(page, 1);
+ __free_pages(page, HUGETLB_PAGE_ORDER);
+}
+
+int try_to_free_low(int count)
+{
+ struct list_head *p;
+ struct page *page, *map;
+
+ map = NULL;
+ spin_lock(&htlbpage_lock);
+ list_for_each(p, &htlbpage_freelist) {
+ if (map) {
+ list_del(&map->list);
+ update_and_free_page(map);
+ htlbpagemem--;
+ map = NULL;
+ if (++count == 0)
+ break;
+ }
+ page = list_entry(p, struct page, list);
+ if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem
+ map = page;
+ }
+ if (map) {
+ list_del(&map->list);
+ update_and_free_page(map);
+ htlbpagemem--;
+ count++;
+ }
+ spin_unlock(&htlbpage_lock);
+ return count;
+}
int set_hugetlb_mem_size(int count)
{
else
lcount = count - htlbzone_pages;
+ if (lcount == 0)
+ return (int)htlbzone_pages;
if (lcount > 0) { /* Increase the mem size. */
while (lcount--) {
page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER);
return (int) htlbzone_pages;
}
/* Shrink the memory size. */
+ lcount = try_to_free_low(lcount);
while (lcount++) {
page = alloc_hugetlb_page();
if (page == NULL)
break;
spin_lock(&htlbpage_lock);
- htlbzone_pages--;
+ update_and_free_page(page);
spin_unlock(&htlbpage_lock);
- map = page;
- for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) {
- map->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
- 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
- 1 << PG_private | 1<< PG_writeback);
- set_page_count(map, 0);
- map++;
- }
- set_page_count(page, 1);
- __free_pages(page, HUGETLB_PAGE_ORDER);
}
return (int) htlbzone_pages;
}
HPAGE_SIZE/1024);
}
+int is_hugepage_mem_enough(size_t size)
+{
+ if (size > (htlbpagemem << HPAGE_SHIFT))
+ return 0;
+ return 1;
+}
+
static struct page * hugetlb_nopage(struct vm_area_struct * area, unsigned long address, int unused)
{
BUG();
void huge_page_release(struct page *);
void hugetlb_release_key(struct hugetlb_key *);
int hugetlb_report_meminfo(char *);
+int is_hugepage_mem_enough(size_t);
extern int htlbpage_max;
#define zap_hugepage_range(vma, start, len) BUG()
#define unmap_hugepage_range(vma, start, end) BUG()
#define huge_page_release(page) BUG()
+#define is_hugepage_mem_enough(size) 0
#define hugetlb_report_meminfo(buf) 0
#endif /* !CONFIG_HUGETLB_PAGE */