Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 148676
b: refs/heads/master
c: fe41953
h: refs/heads/master
v: v3
  • Loading branch information
Rafael J. Wysocki committed Jun 12, 2009
1 parent 8d2f28b commit 1203665
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 82 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c6f37f12197ac3bd2e5a35f2f0e195ae63d437de
refs/heads/master: fe419535d82724314bbf1244a0e740e4ea1bd3ae
4 changes: 1 addition & 3 deletions trunk/kernel/power/power.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ extern asmlinkage int swsusp_arch_resume(void);

extern int create_basic_memory_bitmaps(void);
extern void free_basic_memory_bitmaps(void);
extern unsigned int count_data_pages(void);
extern int swsusp_shrink_memory(void);

/**
* Auxiliary structure used for reading the snapshot image data and
Expand Down Expand Up @@ -149,7 +149,6 @@ extern int swsusp_swap_in_use(void);

/* kernel/power/disk.c */
extern int swsusp_check(void);
extern int swsusp_shrink_memory(void);
extern void swsusp_free(void);
extern int swsusp_read(unsigned int *flags_p);
extern int swsusp_write(unsigned int flags);
Expand All @@ -176,7 +175,6 @@ extern int pm_notifier_call_chain(unsigned long val);
#endif

#ifdef CONFIG_HIGHMEM
unsigned int count_highmem_pages(void);
int restore_highmem(void);
#else
static inline unsigned int count_highmem_pages(void) { return 0; }
Expand Down
80 changes: 78 additions & 2 deletions trunk/kernel/power/snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ static int swsusp_page_is_free(struct page *);
static void swsusp_set_page_forbidden(struct page *);
static void swsusp_unset_page_forbidden(struct page *);

/*
* Preferred image size in bytes (tunable via /sys/power/image_size).
* When it is set to N, swsusp will do its best to ensure the image
* size will not exceed N bytes, but if that is impossible, it will
* try to create the smallest image possible.
*/
unsigned long image_size = 500 * 1024 * 1024;

/* List of PBEs needed for restoring the pages that were allocated before
* the suspend and included in the suspend image, but have also been
* allocated by the "resume" kernel, so their contents cannot be written
Expand Down Expand Up @@ -840,7 +848,7 @@ static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn)
* pages.
*/

unsigned int count_highmem_pages(void)
static unsigned int count_highmem_pages(void)
{
struct zone *zone;
unsigned int n = 0;
Expand Down Expand Up @@ -902,7 +910,7 @@ static struct page *saveable_page(struct zone *zone, unsigned long pfn)
* pages.
*/

unsigned int count_data_pages(void)
static unsigned int count_data_pages(void)
{
struct zone *zone;
unsigned long pfn, max_zone_pfn;
Expand Down Expand Up @@ -1058,6 +1066,74 @@ void swsusp_free(void)
buffer = NULL;
}

/**
* swsusp_shrink_memory - Try to free as much memory as needed
*
* ... but do not OOM-kill anyone
*
* Notice: all userland should be stopped before it is called, or
* livelock is possible.
*/

#define SHRINK_BITE 10000
static inline unsigned long __shrink_memory(long tmp)
{
if (tmp > SHRINK_BITE)
tmp = SHRINK_BITE;
return shrink_all_memory(tmp);
}

int swsusp_shrink_memory(void)
{
long tmp;
struct zone *zone;
unsigned long pages = 0;
unsigned int i = 0;
char *p = "-\\|/";
struct timeval start, stop;

printk(KERN_INFO "PM: Shrinking memory... ");
do_gettimeofday(&start);
do {
long size, highmem_size;

highmem_size = count_highmem_pages();
size = count_data_pages() + PAGES_FOR_IO + SPARE_PAGES;
tmp = size;
size += highmem_size;
for_each_populated_zone(zone) {
tmp += snapshot_additional_pages(zone);
if (is_highmem(zone)) {
highmem_size -=
zone_page_state(zone, NR_FREE_PAGES);
} else {
tmp -= zone_page_state(zone, NR_FREE_PAGES);
tmp += zone->lowmem_reserve[ZONE_NORMAL];
}
}

if (highmem_size < 0)
highmem_size = 0;

tmp += highmem_size;
if (tmp > 0) {
tmp = __shrink_memory(tmp);
if (!tmp)
return -ENOMEM;
pages += tmp;
} else if (size > image_size / PAGE_SIZE) {
tmp = __shrink_memory(size - (image_size / PAGE_SIZE));
pages += tmp;
}
printk("\b%c", p[i++%4]);
} while (tmp > 0);
do_gettimeofday(&stop);
printk("\bdone (%lu pages freed)\n", pages);
swsusp_show_speed(&start, &stop, pages, "Freed");

return 0;
}

#ifdef CONFIG_HIGHMEM
/**
* count_pages_for_highmem - compute the number of non-highmem pages
Expand Down
76 changes: 0 additions & 76 deletions trunk/kernel/power/swsusp.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,6 @@

#include "power.h"

/*
* Preferred image size in bytes (tunable via /sys/power/image_size).
* When it is set to N, swsusp will do its best to ensure the image
* size will not exceed N bytes, but if that is impossible, it will
* try to create the smallest image possible.
*/
unsigned long image_size = 500 * 1024 * 1024;

int in_suspend __nosavedata = 0;

/**
Expand Down Expand Up @@ -195,74 +187,6 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
kps / 1000, (kps % 1000) / 10);
}

/**
* swsusp_shrink_memory - Try to free as much memory as needed
*
* ... but do not OOM-kill anyone
*
* Notice: all userland should be stopped before it is called, or
* livelock is possible.
*/

#define SHRINK_BITE 10000
static inline unsigned long __shrink_memory(long tmp)
{
if (tmp > SHRINK_BITE)
tmp = SHRINK_BITE;
return shrink_all_memory(tmp);
}

int swsusp_shrink_memory(void)
{
long tmp;
struct zone *zone;
unsigned long pages = 0;
unsigned int i = 0;
char *p = "-\\|/";
struct timeval start, stop;

printk(KERN_INFO "PM: Shrinking memory... ");
do_gettimeofday(&start);
do {
long size, highmem_size;

highmem_size = count_highmem_pages();
size = count_data_pages() + PAGES_FOR_IO + SPARE_PAGES;
tmp = size;
size += highmem_size;
for_each_populated_zone(zone) {
tmp += snapshot_additional_pages(zone);
if (is_highmem(zone)) {
highmem_size -=
zone_page_state(zone, NR_FREE_PAGES);
} else {
tmp -= zone_page_state(zone, NR_FREE_PAGES);
tmp += zone->lowmem_reserve[ZONE_NORMAL];
}
}

if (highmem_size < 0)
highmem_size = 0;

tmp += highmem_size;
if (tmp > 0) {
tmp = __shrink_memory(tmp);
if (!tmp)
return -ENOMEM;
pages += tmp;
} else if (size > image_size / PAGE_SIZE) {
tmp = __shrink_memory(size - (image_size / PAGE_SIZE));
pages += tmp;
}
printk("\b%c", p[i++%4]);
} while (tmp > 0);
do_gettimeofday(&stop);
printk("\bdone (%lu pages freed)\n", pages);
swsusp_show_speed(&start, &stop, pages, "Freed");

return 0;
}

/*
* Platforms, like ACPI, may want us to save some memory used by them during
* hibernation and to restore the contents of this memory during the subsequent
Expand Down

0 comments on commit 1203665

Please sign in to comment.