Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision 1a1744ec1103a45c20bd4031d645eaf84be2bb5f)
+++ kernel/generic/src/mm/frame.c	(revision d987fd7b2c19e5d3b03a6f6ffdd7564c01fc2469)
@@ -110,7 +110,8 @@
  * available.
  */
-mutex_t zones_mtx;
-condvar_t zones_cv;
-int new_freed_mem = false;
+mutex_t mem_avail_mtx;
+condvar_t mem_avail_cv;
+unsigned long mem_avail_frames = 0;	/**< Number of available frames. */
+unsigned long mem_avail_gen = 0;	/**< Generation counter. */
 
 /********************/
@@ -141,5 +142,5 @@
 /** Initialize frame structure.
  *
- * @param framei	Frame structure to be initialized.
+ * @param frame		Frame structure to be initialized.
  */
 static void frame_initialize(frame_t *frame)
@@ -540,5 +541,5 @@
 
 /** Return frame from zone. */
-static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx)
+static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx)
 {
 	ASSERT(frame_idx < zone->count);
@@ -559,4 +560,8 @@
 	ASSERT(link);
 	zone->free_count--;
+
+	mutex_lock(&mem_avail_mtx);
+	mem_avail_frames--;
+	mutex_unlock(&mem_avail_mtx);
 }
 
@@ -736,5 +741,5 @@
 		goto errout;
 	/* We can join only 2 zones with none existing inbetween */
-	if (z2-z1 != 1)
+	if (z2 - z1 != 1)
 		goto errout;
 
@@ -797,5 +802,5 @@
 
 	while (zones.count > 1 && --count) {
-		zone_merge(0,1);
+		zone_merge(0, 1);
 		break;
 	}
@@ -894,6 +899,6 @@
 	 */
 	confcount = SIZE2FRAMES(zone_conf_size(count));
-	if (confframe >= start && confframe < start+count) {
-		for (;confframe < start + count; confframe++) {
+	if (confframe >= start && confframe < start + count) {
+		for (; confframe < start + count; confframe++) {
 			addr = PFN2ADDR(confframe);
 			if (overlaps(addr, PFN2ADDR(confcount),
@@ -929,4 +934,8 @@
 		return -1;
 
+	mutex_lock(&mem_avail_mtx);
+	mem_avail_frames += count;
+	mutex_unlock(&mem_avail_mtx);
+
 	/* If confdata in zone, mark as unavailable */
 	if (confframe >= start && confframe < start + count)
@@ -934,4 +943,5 @@
 			zone_mark_unavailable(z, i - z->base);
 		}
+	
 	return znum;
 }
@@ -947,5 +957,5 @@
 	ASSERT(zone);
 
-	zone_get_frame(zone, pfn-zone->base)->parent = data;
+	zone_get_frame(zone, pfn - zone->base)->parent = data;
 	spinlock_unlock(&zone->lock);
 }
@@ -978,4 +988,5 @@
 	pfn_t v;
 	zone_t *zone;
+	unsigned long gen = 0;
 	
 loop:
@@ -1009,15 +1020,28 @@
 		
 #ifdef CONFIG_DEBUG
-		printf("Thread %" PRIu64 " falling asleep, low memory.\n", THREAD->tid);
+		unsigned long avail;
+
+		mutex_lock(&mem_avail_mtx);
+		avail = mem_avail_frames;
+		mutex_unlock(&mem_avail_mtx);
+
+		printf("Thread %" PRIu64 " waiting for %u frames, "
+		    "%u available.\n", THREAD->tid, 1ULL << order, avail);
 #endif
 
-		mutex_lock(&zones_mtx);
-		if (!new_freed_mem)
-			condvar_wait(&zones_cv, &zones_mtx);
-		new_freed_mem = false;
-		mutex_unlock(&zones_mtx);
+		mutex_lock(&mem_avail_mtx);
+		while ((mem_avail_frames < (1ULL << order)) ||
+		    gen == mem_avail_gen)
+			condvar_wait(&mem_avail_cv, &mem_avail_mtx);
+		gen = mem_avail_gen;
+		mutex_unlock(&mem_avail_mtx);
 
 #ifdef CONFIG_DEBUG
-		printf("Thread %" PRIu64 " woken up, memory available.\n", THREAD->tid);
+		mutex_lock(&mem_avail_mtx);
+		avail = mem_avail_frames;
+		mutex_unlock(&mem_avail_mtx);
+
+		printf("Thread %" PRIu64 " woken up, %u frames available.\n",
+		    THREAD->tid, avail);
 #endif
 
@@ -1030,4 +1054,9 @@
 
 	spinlock_unlock(&zone->lock);
+	
+	mutex_lock(&mem_avail_mtx);
+	mem_avail_frames -= (1ULL << order);
+	mutex_unlock(&mem_avail_mtx);
+
 	interrupts_restore(ipl);
 
@@ -1066,8 +1095,9 @@
 	 * Signal that some memory has been freed.
 	 */
-	mutex_lock(&zones_mtx);	
-	new_freed_mem = true;
-	condvar_broadcast(&zones_cv);
-	mutex_unlock(&zones_mtx);
+	mutex_lock(&mem_avail_mtx);
+	mem_avail_frames++;
+	mem_avail_gen++;
+	condvar_broadcast(&mem_avail_cv);
+	mutex_unlock(&mem_avail_mtx);
 
 	interrupts_restore(ipl);
@@ -1125,4 +1155,6 @@
 		zones.count = 0;
 		spinlock_initialize(&zones.lock, "zones.lock");
+		mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE);
+		condvar_initialize(&mem_avail_cv);
 	}
 	/* Tell the architecture to create some memory */
@@ -1149,7 +1181,4 @@
 		frame_mark_unavailable(0, 1);
 	}
-
-	mutex_initialize(&zones_mtx, MUTEX_ACTIVE);	/* mimic spinlock */
-	condvar_initialize(&zones_cv);
 }
 
