Index: kernel/test/synch/rcu1.c
===================================================================
--- kernel/test/synch/rcu1.c	(revision 1066041e4e1803c9b6506af8a869b03669a25957)
+++ kernel/test/synch/rcu1.c	(revision 2e16033115d5c1a9a9095d87b471d2db4bf1dc88)
@@ -33,4 +33,5 @@
 #include <proc/thread.h>
 #include <macros.h>
+#include <str.h>
 
 #include <synch/rcu.h>
@@ -237,4 +238,5 @@
 
 static atomic_t nop_callbacks_cnt = {0};
+/* Must be even. */
 static const int nop_updater_iters = 10000;
 
@@ -247,5 +249,5 @@
 static void nop_updater(void *arg)
 {
-	for (int i = 0; i < nop_updater_iters; ++i){
+	for (int i = 0; i < nop_updater_iters; i += 2){
 		rcu_item_t *a = malloc(sizeof(rcu_item_t), 0);
 		rcu_item_t *b = malloc(sizeof(rcu_item_t), 0);
@@ -264,7 +266,10 @@
 {
 	atomic_set(&nop_callbacks_cnt, 0);
-	
-	TPRINTF("\nRun %zu thr: post many no-op callbacks, no readers.\n", 
-		get_thread_cnt());
+
+	size_t exp_cnt = nop_updater_iters * get_thread_cnt();
+	size_t max_used_mem = sizeof(rcu_item_t) * exp_cnt;
+	
+	TPRINTF("\nRun %zu thr: post %zu no-op callbacks (%zu B used), no readers.\n", 
+		get_thread_cnt(), exp_cnt, max_used_mem);
 	
 	run_all(nop_updater);
@@ -273,5 +278,4 @@
 	
 	size_t loop_cnt = 0, max_loops = 15;
-	size_t exp_cnt = 2 * nop_updater_iters * get_thread_cnt();
 
 	while (exp_cnt != atomic_get(&nop_callbacks_cnt) && loop_cnt < max_loops) {
@@ -309,7 +313,11 @@
 	
 	item_w_cookie_t *item = malloc(sizeof(item_w_cookie_t), 0);
-	item->cookie = magic_cookie;
-	
-	rcu_call(&item->rcu_item, one_cb_done);
+	
+	if (item) {
+		item->cookie = magic_cookie;
+		rcu_call(&item->rcu_item, one_cb_done);
+	} else {
+		TPRINTF("\n[out-of-mem]\n");
+	}
 	
 	thread_sleep(1);
@@ -330,5 +338,5 @@
 	TPRINTF("\nJoined one-cb reader, wait for cb.\n");
 	size_t loop_cnt = 0;
-	size_t max_loops = 4;
+	size_t max_loops = 4; /* 200 ms */
 	
 	while (!one_cb_is_done && loop_cnt < max_loops) {
@@ -385,5 +393,5 @@
 			atomic_count_t start_time = atomic_postinc(&cur_time);
 			
-			for (volatile size_t d = 0; d < 10*i; ++d ){
+			for (volatile size_t d = 0; d < 10 * i; ++d ){
 				/* no-op */
 			}
@@ -403,5 +411,5 @@
 		
 		/* Updater */
-		for (size_t i = 0; i < work->update_cnt; i += 2) {
+		for (size_t i = 0; i < work->update_cnt; ++i) {
 			seq_item_t *a = malloc(sizeof(seq_item_t), 0);
 			seq_item_t *b = malloc(sizeof(seq_item_t), 0);
@@ -414,7 +422,8 @@
 				rcu_call(&b->rcu, seq_cb);
 			} else {
-				/* can leak a bit of mem */
 				TPRINTF("\n[out-of-mem]\n");
 				seq_test_result = ENOMEM;
+				free(a);
+				free(b);
 				return;
 			}
@@ -435,14 +444,27 @@
 	seq_work_t item[MAX_THREADS];
 	
+	size_t total_cbs = 0;
+	size_t max_used_mem = 0;
+	
 	get_seq(0, total_cnt, get_thread_cnt(), read_cnt);
 	
+
 	for (size_t i = 0; i < get_thread_cnt(); ++i) {
 		item[i].update_cnt = total_cnt - read_cnt[i];
 		item[i].read_cnt = read_cnt[i];
 		item[i].iters = iters;
-	}
-	
-	TPRINTF("\nRun %zu th: check callback completion time in readers. ~%zu cbs/"
-		"thread. Be patient.\n", get_thread_cnt(),	iters * total_cnt * 2);
+		
+		total_cbs += 2 * iters * item[i].update_cnt;
+	}
+	
+	max_used_mem = total_cbs * sizeof(seq_item_t);
+
+	const char *mem_suffix;
+	uint64_t mem_units;
+	bin_order_suffix(max_used_mem, &mem_units, &mem_suffix, false);
+	
+	TPRINTF("\nRun %zu th: check callback completion time in readers. "
+		"%zu callbacks total (max %" PRIu64 " %s used). Be patient.\n", 
+		get_thread_cnt(), total_cbs, mem_units, mem_suffix);
 	
 	for (size_t i = 0; i < get_thread_cnt(); ++i) {
@@ -796,4 +818,5 @@
 	/* 5 us * 1000 * 1000 iters == 5 sec per updater thread */
 	delay(5);
+	free(item);
 }
 
@@ -808,4 +831,5 @@
 			rcu_call(item, stress_cb);
 		
+		/* Print a dot if we make progress of 1% */
 		if (s->master && 0 == (i % (s->iters/100 + 1)))
 			TPRINTF(".");
@@ -825,7 +849,15 @@
 	size_t reader_cnt = thread_cnt;
 	size_t updater_cnt = thread_cnt;
-
-	TPRINTF("\nStress: Run %zu nop-readers and %zu updaters. %zu cbs/updater. "
-		"Be very patient.\n", reader_cnt, updater_cnt, cb_per_thread);
+	
+	size_t exp_upd_calls = updater_cnt * cb_per_thread;
+	size_t max_used_mem = exp_upd_calls * sizeof(rcu_item_t);
+	
+	const char *mem_suffix;
+	uint64_t mem_units;
+	bin_order_suffix(max_used_mem, &mem_units, &mem_suffix, false);
+
+	TPRINTF("\nStress: Run %zu nop-readers and %zu updaters. %zu callbacks "
+		" total (max %" PRIu64 " %s used). Be very patient.\n", 
+		reader_cnt, updater_cnt, exp_upd_calls, mem_units, mem_suffix);
 	
 	for (size_t k = 0; k < reader_cnt; ++k) {
@@ -872,4 +904,5 @@
 		_rcu_call(e->expedite, &e->r, expedite_cb);
 	} else {
+		/* Do not touch any of e's mem after we declare we're done with it. */
 		memory_barrier();
 		e->count_down = 0;
@@ -937,4 +970,6 @@
 			TPRINTF("\nSubtest %s() skipped.\n", test_func[i].desc);
 			continue;
+		} else {
+			TPRINTF("\nRunning subtest %s.\n", test_func[i].desc);
 		}
 		
