patch-2.4.0-test5 linux/mm/page_alloc.c
Next file: linux/mm/vmscan.c
Previous file: linux/mm/mmap.c
Back to the patch index
Back to the overall index
- Lines: 114
- Date:
Fri Jul 21 21:42:13 2000
- Orig file:
v2.4.0-test4/linux/mm/page_alloc.c
- Orig date:
Fri Jul 14 12:12:16 2000
diff -u --recursive --new-file v2.4.0-test4/linux/mm/page_alloc.c linux/mm/page_alloc.c
@@ -64,7 +64,8 @@
* Hint: -mask = 1+~mask
*/
-void __free_pages_ok (struct page *page, unsigned long order)
+static void FASTCALL(__free_pages_ok (struct page *page, unsigned long order));
+static void __free_pages_ok (struct page *page, unsigned long order)
{
unsigned long index, page_idx, mask, flags;
free_area_t *area;
@@ -217,7 +218,7 @@
*/
struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order)
{
- zone_t **zone = zonelist->zones;
+ zone_t **zone;
extern wait_queue_head_t kswapd_wait;
/*
@@ -228,21 +229,6 @@
* in a higher zone fails.
*/
- for (;;) {
- zone_t *z = *(zone++);
- if (!z)
- break;
- if (!z->size)
- BUG();
-
- /* If there are zones with a lot of free memory allocate from them */
- if (z->free_pages > z->pages_high) {
- struct page *page = rmqueue(z, order);
- if (page)
- return page;
- }
- }
-
zone = zonelist->zones;
for (;;) {
zone_t *z = *(zone++);
@@ -264,6 +250,21 @@
}
}
+ /* Three possibilities to get here
+ * - Previous alloc_pages resulted in last zone set to have
+ * zone_wake_kswapd and start it. kswapd has not been able
+ * to release enough pages so that one zone does not have
+ * zone_wake_kswapd set.
+ * - Different sets of zones (zonelist)
+ * previous did not have all zones with zone_wake_kswapd but
+ * this one has... should kswapd be woken up? it will run once.
+ * - SMP race, kswapd went to sleep slightly after it as running
+ * in 'if (waitqueue_active(...))' above.
+ * + anyway the test is very cheap to do...
+ */
+ if (waitqueue_active(&kswapd_wait))
+ wake_up_interruptible(&kswapd_wait);
+
/*
* Ok, we don't have any zones that don't need some
* balancing.. See if we have any that aren't critical..
@@ -313,6 +314,50 @@
fail:
/* No luck.. */
return NULL;
+}
+
+/*
+ * Common helper functions.
+ */
+unsigned long __get_free_pages(int gfp_mask, unsigned long order)
+{
+ struct page * page;
+
+ page = alloc_pages(gfp_mask, order);
+ if (!page)
+ return 0;
+ return page_address(page);
+}
+
+unsigned long get_zeroed_page(int gfp_mask)
+{
+ struct page * page;
+
+ page = alloc_pages(gfp_mask, 0);
+ if (page) {
+ unsigned long address = page_address(page);
+ clear_page((void *)address);
+ return address;
+ }
+ return 0;
+}
+
+void __free_pages(struct page *page, unsigned long order)
+{
+ if (put_page_testzero(page))
+ __free_pages_ok(page, order);
+}
+
+void free_pages(unsigned long addr, unsigned long order)
+{
+ unsigned long map_nr;
+
+#ifdef CONFIG_DISCONTIGMEM
+ if (addr == 0) return;
+#endif
+ map_nr = MAP_NR(addr);
+ if (map_nr < max_mapnr)
+ __free_pages(mem_map + map_nr, order);
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)