From: Nick Piggin <nickpiggin@yahoo.com.au>
To: Jack Steiner <steiner@sgi.com>
Cc: Linux Memory Management <linux-mm@kvack.org>
Subject: [patch 3/4] pcp: NULL pagesets
Date: Sat, 09 Apr 2005 23:24:31 +1000 [thread overview]
Message-ID: <4257D78F.7020609@yahoo.com.au> (raw)
In-Reply-To: <4257D779.30801@yahoo.com.au>
[-- Attachment #1: Type: text/plain, Size: 4 bytes --]
3/4
[-- Attachment #2: pcp-null-pagesets.patch --]
[-- Type: text/plain, Size: 7400 bytes --]
Index: linux-2.6/include/linux/mmzone.h
===================================================================
--- linux-2.6.orig/include/linux/mmzone.h 2005-04-09 22:44:48.000000000 +1000
+++ linux-2.6/include/linux/mmzone.h 2005-04-09 22:45:07.000000000 +1000
@@ -128,6 +128,9 @@ struct zone {
struct per_cpu_zone_stats stats[NR_CPUS];
#endif
+ /* global pageset for CPUs without private pagesets for this zone */
+ struct per_cpu_pageset pageset;
+
/*
* free areas of different sizes
*/
Index: linux-2.6/mm/page_alloc.c
===================================================================
--- linux-2.6.orig/mm/page_alloc.c 2005-04-09 22:45:06.000000000 +1000
+++ linux-2.6/mm/page_alloc.c 2005-04-09 22:45:07.000000000 +1000
@@ -84,7 +84,6 @@ struct zone_pagesets {
/*
* List of pointers to per_cpu_pagesets for each zone.
- * XXX: put this comment in a future patch that actually enables NULLs here
* It is used as a per-CPU set. A value of NULL in any pointer indicates
* this CPU doesn't have a pageset for this zone, and should use the public
* pageset.
@@ -363,13 +362,14 @@ static inline void free_pages_check(cons
*/
static int
free_pages_bulk(struct zone *zone, int count,
- struct list_head *list, unsigned int order)
+ struct list_head *list, unsigned int order, const int locked)
{
- unsigned long flags;
+ unsigned long flags = 0; /* shut up gcc */
struct page *page = NULL;
int ret = 0;
- spin_lock_irqsave(&zone->lock, flags);
+ if (likely(!locked))
+ spin_lock_irqsave(&zone->lock, flags);
zone->all_unreclaimable = 0;
zone->pages_scanned = 0;
while (!list_empty(list) && count--) {
@@ -379,7 +379,8 @@ free_pages_bulk(struct zone *zone, int c
__free_pages_bulk(page, zone, order);
ret++;
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ if (likely(!locked))
+ spin_unlock_irqrestore(&zone->lock, flags);
return ret;
}
@@ -402,7 +403,7 @@ void __free_pages_ok(struct page *page,
free_pages_check(__FUNCTION__, page + i);
list_add(&page->lru, &list);
kernel_map_pages(page, 1<<order, 0);
- free_pages_bulk(page_zone(page), 1, &list, order);
+ free_pages_bulk(page_zone(page), 1, &list, order, 0);
}
@@ -512,14 +513,15 @@ static struct page *__rmqueue(struct zon
* Returns the number of new pages which were placed at *list.
*/
static int rmqueue_bulk(struct zone *zone, unsigned int order,
- unsigned long count, struct list_head *list)
+ unsigned long count, struct list_head *list, const int locked)
{
- unsigned long flags;
+ unsigned long flags = 0; /* shut up gcc */
int i;
int allocated = 0;
struct page *page;
- spin_lock_irqsave(&zone->lock, flags);
+ if (likely(!locked))
+ spin_lock_irqsave(&zone->lock, flags);
for (i = 0; i < count; ++i) {
page = __rmqueue(zone, order);
if (page == NULL)
@@ -527,7 +529,8 @@ static int rmqueue_bulk(struct zone *zon
allocated++;
list_add_tail(&page->lru, list);
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ if (likely(!locked))
+ spin_unlock_irqrestore(&zone->lock, flags);
return allocated;
}
@@ -541,13 +544,15 @@ static void __drain_pages(unsigned int c
/* XXX: this can be a for i = 0 .. TOTAL_ZONES loop */
for_each_zone(zone) {
struct per_cpu_pageset *pset = zone_pageset(zp, zone);
+ if (unlikely(!pset))
+ continue;
for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
struct per_cpu_pages *pcp;
pcp = &pset->pcp[i];
pcp->count -= free_pages_bulk(zone, pcp->count,
- &pcp->list, 0);
+ &pcp->list, 0, 0);
}
}
}
@@ -627,9 +632,11 @@ static void FASTCALL(free_hot_cold_page(
static void fastcall free_hot_cold_page(struct page *page, int cold)
{
struct zone_pagesets *zp;
- struct zone *zone = page_zone(page);
+ struct per_cpu_pageset *pset;
struct per_cpu_pages *pcp;
+ struct zone *zone = page_zone(page);
unsigned long flags;
+ int locked = 0;
arch_free_page(page, 0);
@@ -641,12 +648,23 @@ static void fastcall free_hot_cold_page(
preempt_disable();
zp = this_zone_pagesets();
- pcp = &zone_pageset(zp, zone)->pcp[cold];
- local_irq_save(flags);
+ pset = zone_pageset(zp, zone);
+ if (unlikely(!pset)) {
+ locked = 1;
+ pset = &zone->pageset;
+ spin_lock_irqsave(&zone->lock, flags);
+ } else
+ local_irq_save(flags);
+
+ pcp = &pset->pcp[cold];
if (pcp->count >= pcp->high)
- pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
+ pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list,
+ 0, locked);
list_add(&page->lru, &pcp->list);
pcp->count++;
+
+ if (unlikely(locked))
+ spin_unlock(&zone->lock);
local_irq_restore(flags);
preempt_enable();
}
@@ -683,22 +701,33 @@ buffered_rmqueue(struct zone *zone, int
int cold = !!(gfp_flags & __GFP_COLD);
if (order == 0) {
+ int locked = 0;
struct zone_pagesets *zp;
+ struct per_cpu_pageset *pset;
struct per_cpu_pages *pcp;
preempt_disable();
zp = this_zone_pagesets();
- pcp = &zone_pageset(zp, zone)->pcp[cold];
+ pset = zone_pageset(zp, zone);
+ if (unlikely(!pset)) {
+ locked = 1;
+ pset = &zone->pageset;
+ spin_lock_irqsave(&zone->lock, flags);
+ } else
+ local_irq_save(flags);
+
+ pcp = &pset->pcp[cold];
- local_irq_save(flags);
if (pcp->count <= pcp->low)
pcp->count += rmqueue_bulk(zone, 0,
- pcp->batch, &pcp->list);
+ pcp->batch, &pcp->list, locked);
if (pcp->count) {
page = list_entry(pcp->list.next, struct page, lru);
list_del(&page->lru);
pcp->count--;
}
+ if (unlikely(locked))
+ spin_unlock(&zone->lock);
local_irq_restore(flags);
preempt_enable();
}
@@ -1266,6 +1295,8 @@ void show_free_areas(void)
zp = cpu_zone_pagesets(cpu);
pageset = zone_pageset(zp, zone);
+ if (!pageset)
+ continue;
for (temperature = 0; temperature < 2; temperature++)
printk("cpu %d %s: low %d, high %d, batch %d\n",
@@ -1545,6 +1576,25 @@ void __init build_all_zonelists(void)
cpuset_init_current_mems_allowed();
}
+static void __init init_percpu_pageset(struct per_cpu_pageset *pset, int batch)
+{
+ struct per_cpu_pages *pcp;
+
+ pcp = &pset->pcp[0]; /* hot */
+ pcp->count = 0;
+ pcp->low = 2 * batch;
+ pcp->high = 6 * batch;
+ pcp->batch = 1 * batch;
+ INIT_LIST_HEAD(&pcp->list);
+
+ pcp = &pset->pcp[1]; /* cold */
+ pcp->count = 0;
+ pcp->low = 0;
+ pcp->high = 2 * batch;
+ pcp->batch = 1 * batch;
+ INIT_LIST_HEAD(&pcp->list);
+}
+
void __init build_percpu_pagelists(void)
{
pg_data_t *pgdat;
@@ -1573,28 +1623,16 @@ void __init build_percpu_pagelists(void)
if (batch < 1)
batch = 1;
+ init_percpu_pageset(&zone->pageset, batch);
for (cpu = 0; cpu < NR_CPUS; cpu++) {
struct zone_pagesets *zp;
struct per_cpu_pageset *pageset;
- struct per_cpu_pages *pcp;
zp = cpu_zone_pagesets(cpu);
pageset = alloc_bootmem_node(pgdat, sizeof(*pageset));
+ init_percpu_pageset(pageset, batch);
zp->p[NODEZONE(nid, j)] = pageset;
- pcp = &pageset->pcp[0]; /* hot */
- pcp->count = 0;
- pcp->low = 2 * batch;
- pcp->high = 6 * batch;
- pcp->batch = 1 * batch;
- INIT_LIST_HEAD(&pcp->list);
-
- pcp = &pageset->pcp[1]; /* cold */
- pcp->count = 0;
- pcp->low = 0;
- pcp->high = 2 * batch;
- pcp->batch = 1 * batch;
- INIT_LIST_HEAD(&pcp->list);
}
printk(KERN_DEBUG " %s zone: %lu pages, LIFO batch:%lu\n",
zone_names[j], zone->present_pages, batch);
next prev parent reply other threads:[~2005-04-09 13:24 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-04-09 13:23 [patch 1/4] pcp: zonequeues Nick Piggin
2005-04-09 13:24 ` [patch 2/4] pcp: dynamic lists Nick Piggin
2005-04-09 13:24 ` Nick Piggin [this message]
2005-04-09 13:25 ` [patch 4/4] pcp: only local pagesets Nick Piggin
2005-04-09 13:28 ` [patch 1/4] pcp: zonequeues Nick Piggin
2005-04-09 15:25 ` Nick Piggin
2005-04-12 16:15 ` Jack Steiner
2005-04-13 1:34 ` Nick Piggin
2005-04-12 19:02 ` Christoph Lameter
2005-04-13 1:40 ` Nick Piggin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4257D78F.7020609@yahoo.com.au \
--to=nickpiggin@yahoo.com.au \
--cc=linux-mm@kvack.org \
--cc=steiner@sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.