aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swsusp.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2006-01-06 03:13:46 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:40 -0500
commit72a97e08394a3b2e75481ff680ec2a0591e3cba4 (patch)
treed8ba72d6e81ad31ed10876386d3d2067921979e3 /kernel/power/swsusp.c
parent7088a5c00103ef48782d6c359cd12b13a10666e6 (diff)
[PATCH] swsusp: improve freeing of memory
This patch makes swsusp free only as much memory as needed to complete the suspend and not as much as possible.  In the most of cases this should speed up the suspend and make the system much more responsive after resume, especially if a GUI (eg. X Windows) is used. If needed, the old behavior (ie to free as much memory as possible during suspend) can be restored by unsetting FAST_FREE in power.h Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@suse.cz> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r--kernel/power/swsusp.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index b09bd7c0998d..f77f9397a364 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -70,11 +70,13 @@
70#include "power.h" 70#include "power.h"
71 71
72#ifdef CONFIG_HIGHMEM 72#ifdef CONFIG_HIGHMEM
73unsigned int count_highmem_pages(void);
73int save_highmem(void); 74int save_highmem(void);
74int restore_highmem(void); 75int restore_highmem(void);
75#else 76#else
76static int save_highmem(void) { return 0; } 77static int save_highmem(void) { return 0; }
77static int restore_highmem(void) { return 0; } 78static int restore_highmem(void) { return 0; }
79static unsigned int count_highmem_pages(void) { return 0; }
78#endif 80#endif
79 81
80extern char resume_file[]; 82extern char resume_file[];
@@ -611,6 +613,52 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages)
611 return error; 613 return error;
612} 614}
613 615
616/**
617 * swsusp_shrink_memory - Try to free as much memory as needed
618 *
619 * ... but do not OOM-kill anyone
620 *
621 * Notice: all userland should be stopped before it is called, or
622 * livelock is possible.
623 */
624
625#define SHRINK_BITE 10000
626
627int swsusp_shrink_memory(void)
628{
629 long tmp;
630 struct zone *zone;
631 unsigned long pages = 0;
632 unsigned int i = 0;
633 char *p = "-\\|/";
634
635 printk("Shrinking memory... ");
636 do {
637#ifdef FAST_FREE
638 tmp = 2 * count_highmem_pages();
639 tmp += tmp / 50 + count_data_pages();
640 tmp += (tmp + PBES_PER_PAGE - 1) / PBES_PER_PAGE +
641 PAGES_FOR_IO;
642 for_each_zone (zone)
643 if (!is_highmem(zone))
644 tmp -= zone->free_pages;
645 if (tmp > 0) {
646 tmp = shrink_all_memory(SHRINK_BITE);
647 if (!tmp)
648 return -ENOMEM;
649 pages += tmp;
650 }
651#else
652 tmp = shrink_all_memory(SHRINK_BITE);
653 pages += tmp;
654#endif
655 printk("\b%c", p[i++%4]);
656 } while (tmp > 0);
657 printk("\bdone (%lu pages freed)\n", pages);
658
659 return 0;
660}
661
614int swsusp_suspend(void) 662int swsusp_suspend(void)
615{ 663{
616 int error; 664 int error;
@@ -1030,8 +1078,10 @@ static int read_suspend_image(struct pbe **pblist_ptr)
1030 /* Allocate memory for the image and read the data from swap */ 1078 /* Allocate memory for the image and read the data from swap */
1031 if (!error) 1079 if (!error)
1032 error = alloc_data_pages(pblist, GFP_ATOMIC, 1); 1080 error = alloc_data_pages(pblist, GFP_ATOMIC, 1);
1033 if (!error) 1081 if (!error) {
1082 release_eaten_pages();
1034 error = load_image_data(pblist, &handle, nr_pages); 1083 error = load_image_data(pblist, &handle, nr_pages);
1084 }
1035 if (!error) 1085 if (!error)
1036 *pblist_ptr = pblist; 1086 *pblist_ptr = pblist;
1037 } 1087 }