-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 54214 b: refs/heads/master c: 6225e93 h: refs/heads/master v: v3
- Loading branch information
Christoph Lameter
authored and
Linus Torvalds
committed
May 7, 2007
1 parent
6f0882f
commit 96b273b
Showing
5 changed files
with
190 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: c09d87517298fd01543739ba26987645deb4e6a9 | ||
refs/heads/master: 6225e93735acaa09865bce746958f1046c2e0bc3 |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#ifndef LINUX_QUICKLIST_H | ||
#define LINUX_QUICKLIST_H | ||
/* | ||
* Fast allocations and disposal of pages. Pages must be in the condition | ||
* as needed after allocation when they are freed. Per cpu lists of pages | ||
* are kept that only contain node local pages. | ||
* | ||
* (C) 2007, SGI. Christoph Lameter <clameter@sgi.com> | ||
*/ | ||
#include <linux/kernel.h> | ||
#include <linux/gfp.h> | ||
#include <linux/percpu.h> | ||
|
||
#ifdef CONFIG_QUICKLIST | ||
|
||
struct quicklist { | ||
void *page; | ||
int nr_pages; | ||
}; | ||
|
||
DECLARE_PER_CPU(struct quicklist, quicklist)[CONFIG_NR_QUICK]; | ||
|
||
/* | ||
* The two key functions quicklist_alloc and quicklist_free are inline so | ||
* that they may be custom compiled for the platform. | ||
* Specifying a NULL ctor can remove constructor support. Specifying | ||
* a constant quicklist allows the determination of the exact address | ||
* in the per cpu area. | ||
* | ||
* The fast patch in quicklist_alloc touched only a per cpu cacheline and | ||
* the first cacheline of the page itself. There is minmal overhead involved. | ||
*/ | ||
static inline void *quicklist_alloc(int nr, gfp_t flags, void (*ctor)(void *)) | ||
{ | ||
struct quicklist *q; | ||
void **p = NULL; | ||
|
||
q =&get_cpu_var(quicklist)[nr]; | ||
p = q->page; | ||
if (likely(p)) { | ||
q->page = p[0]; | ||
p[0] = NULL; | ||
q->nr_pages--; | ||
} | ||
put_cpu_var(quicklist); | ||
if (likely(p)) | ||
return p; | ||
|
||
p = (void *)__get_free_page(flags | __GFP_ZERO); | ||
if (ctor && p) | ||
ctor(p); | ||
return p; | ||
} | ||
|
||
static inline void __quicklist_free(int nr, void (*dtor)(void *), void *p, | ||
struct page *page) | ||
{ | ||
struct quicklist *q; | ||
int nid = page_to_nid(page); | ||
|
||
if (unlikely(nid != numa_node_id())) { | ||
if (dtor) | ||
dtor(p); | ||
__free_page(page); | ||
return; | ||
} | ||
|
||
q = &get_cpu_var(quicklist)[nr]; | ||
*(void **)p = q->page; | ||
q->page = p; | ||
q->nr_pages++; | ||
put_cpu_var(quicklist); | ||
} | ||
|
||
static inline void quicklist_free(int nr, void (*dtor)(void *), void *pp) | ||
{ | ||
__quicklist_free(nr, dtor, pp, virt_to_page(pp)); | ||
} | ||
|
||
static inline void quicklist_free_page(int nr, void (*dtor)(void *), | ||
struct page *page) | ||
{ | ||
__quicklist_free(nr, dtor, page_address(page), page); | ||
} | ||
|
||
void quicklist_trim(int nr, void (*dtor)(void *), | ||
unsigned long min_pages, unsigned long max_free); | ||
|
||
unsigned long quicklist_total_size(void); | ||
|
||
#endif | ||
|
||
#endif /* LINUX_QUICKLIST_H */ | ||
|
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Quicklist support. | ||
* | ||
* Quicklists are light weight lists of pages that have a defined state | ||
* on alloc and free. Pages must be in the quicklist specific defined state | ||
* (zero by default) when the page is freed. It seems that the initial idea | ||
* for such lists first came from Dave Miller and then various other people | ||
* improved on it. | ||
* | ||
* Copyright (C) 2007 SGI, | ||
* Christoph Lameter <clameter@sgi.com> | ||
* Generalized, added support for multiple lists and | ||
* constructors / destructors. | ||
*/ | ||
#include <linux/kernel.h> | ||
|
||
#include <linux/mm.h> | ||
#include <linux/mmzone.h> | ||
#include <linux/module.h> | ||
#include <linux/quicklist.h> | ||
|
||
DEFINE_PER_CPU(struct quicklist, quicklist)[CONFIG_NR_QUICK]; | ||
|
||
#define FRACTION_OF_NODE_MEM 16 | ||
|
||
static unsigned long max_pages(unsigned long min_pages) | ||
{ | ||
unsigned long node_free_pages, max; | ||
|
||
node_free_pages = node_page_state(numa_node_id(), | ||
NR_FREE_PAGES); | ||
max = node_free_pages / FRACTION_OF_NODE_MEM; | ||
return max(max, min_pages); | ||
} | ||
|
||
static long min_pages_to_free(struct quicklist *q, | ||
unsigned long min_pages, long max_free) | ||
{ | ||
long pages_to_free; | ||
|
||
pages_to_free = q->nr_pages - max_pages(min_pages); | ||
|
||
return min(pages_to_free, max_free); | ||
} | ||
|
||
/* | ||
* Trim down the number of pages in the quicklist | ||
*/ | ||
void quicklist_trim(int nr, void (*dtor)(void *), | ||
unsigned long min_pages, unsigned long max_free) | ||
{ | ||
long pages_to_free; | ||
struct quicklist *q; | ||
|
||
q = &get_cpu_var(quicklist)[nr]; | ||
if (q->nr_pages > min_pages) { | ||
pages_to_free = min_pages_to_free(q, min_pages, max_free); | ||
|
||
while (pages_to_free > 0) { | ||
/* | ||
* We pass a gfp_t of 0 to quicklist_alloc here | ||
* because we will never call into the page allocator. | ||
*/ | ||
void *p = quicklist_alloc(nr, 0, NULL); | ||
|
||
if (dtor) | ||
dtor(p); | ||
free_page((unsigned long)p); | ||
pages_to_free--; | ||
} | ||
} | ||
put_cpu_var(quicklist); | ||
} | ||
|
||
unsigned long quicklist_total_size(void) | ||
{ | ||
unsigned long count = 0; | ||
int cpu; | ||
struct quicklist *ql, *q; | ||
|
||
for_each_online_cpu(cpu) { | ||
ql = per_cpu(quicklist, cpu); | ||
for (q = ql; q < ql + CONFIG_NR_QUICK; q++) | ||
count += q->nr_pages; | ||
} | ||
return count; | ||
} | ||
|