diff -Naur otp_src_R12B-5/erts/emulator/beam/erl_gc.c otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_gc.c
--- otp_src_R12B-5/erts/emulator/beam/erl_gc.c	2008-11-04 11:51:44.000000000 +0100
+++ otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_gc.c	2009-01-14 10:03:47.000000000 +0100
@@ -341,7 +341,6 @@
 {
     Uint reclaimed_now = 0;
     int done = 0;
-    Uint saved_status = p->status;
     Uint ms1, s1, us1;
 
     if (IS_TRACED_FL(p, F_TRACE_GC)) {
@@ -349,6 +348,7 @@
     }
 
     erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+    p->gcstatus = p->status;
     p->status = P_GARBING;
     if (erts_system_monitor_long_gc != 0) {
 	get_now(&ms1, &s1, &us1);
@@ -384,7 +384,7 @@
     ErtsGcQuickSanityCheck(p);
 
     erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
-    p->status = saved_status;
+    p->status = p->gcstatus;
     erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
     if (IS_TRACED_FL(p, F_TRACE_GC)) {
         trace_gc(p, am_gc_end);
@@ -449,7 +449,6 @@
 void
 erts_garbage_collect_hibernate(Process* p)
 {
-    Uint saved_status = p->status;
     Uint heap_size;
     Eterm* heap;
     Eterm* htop;
@@ -466,6 +465,7 @@
      * Preliminaries.
      */
     erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+    p->gcstatus = p->status;
     p->status = P_GARBING;
     erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
     erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
@@ -580,7 +580,7 @@
     ErtsGcQuickSanityCheck(p);
 
     erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
-    p->status = saved_status;
+    p->status = p->gcstatus;
     erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
     erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
 }
@@ -589,7 +589,6 @@
 void
 erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
 {
-    Uint saved_status = p->status;
     Uint byte_lit_size = sizeof(Eterm)*lit_size;
     Uint old_heap_size;
     Eterm* temp_lit;
@@ -605,6 +604,7 @@
      * Set GC state.
      */
     erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+    p->gcstatus = p->status;
     p->status = P_GARBING;
     erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
     erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
@@ -708,7 +708,7 @@
      * Restore status.
      */
     erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
-    p->status = saved_status;
+    p->status = p->gcstatus;
     erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
     erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
 }
diff -Naur otp_src_R12B-5/erts/emulator/beam/erl_message.c otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_message.c
--- otp_src_R12B-5/erts/emulator/beam/erl_message.c	2008-09-01 14:51:20.000000000 +0200
+++ otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_message.c	2009-01-14 10:03:47.000000000 +0100
@@ -295,10 +295,27 @@
 
     ACTIVATE(receiver);
 
-    if (receiver->status == P_WAITING) {
-	add_to_schedule_q(receiver);
-    } else if (receiver->status == P_SUSPENDED) {
+    switch (receiver->status) {
+    case P_GARBING:
+	switch (receiver->gcstatus) {
+	case P_SUSPENDED:
+	    goto suspended;
+	case P_WAITING:
+	    goto waiting;
+	default:
+	    break;
+	}
+	break;
+    case P_SUSPENDED:
+    suspended:
 	receiver->rstatus = P_RUNABLE;
+	break;
+    case P_WAITING:
+    waiting:
+	add_to_schedule_q(receiver);
+	break;
+    default:
+	break;
     }
 
     if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
diff -Naur otp_src_R12B-5/erts/emulator/beam/erl_process.c otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_process.c
--- otp_src_R12B-5/erts/emulator/beam/erl_process.c	2008-11-04 11:51:10.000000000 +0100
+++ otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_process.c	2009-01-14 10:03:47.000000000 +0100
@@ -473,21 +473,33 @@
 static ERTS_INLINE void
 resume_process(Process *p)
 {
+    Uint32 *statusp;
     ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_STATUS & erts_proc_lc_my_proc_locks(p));
-    /* We may get called from trace([suspend], false) */
-    if (p->status != P_SUSPENDED)
+    switch (p->status) {
+    case P_SUSPENDED:
+	statusp = &p->status;
+	break;
+    case P_GARBING:
+	if (p->gcstatus == P_SUSPENDED) {
+	    statusp = &p->gcstatus;
+	    break;
+	}
+	/* Fall through */
+    default:
 	return;
+    }
+
     ASSERT(p->rcount > 0);
 
     if (--p->rcount > 0)  /* multiple suspend i.e trace and busy port */
 	return;
     switch(p->rstatus) {
     case P_RUNABLE:
-	p->status = P_WAITING;  /* make add_to_schedule_q work */
+	*statusp = P_WAITING;  /* make add_to_schedule_q work */
 	add_to_schedule_q(p);
 	break;
     case P_WAITING:
-	p->status = P_WAITING;
+	*statusp = P_WAITING;
 	break;
     default:
 	erl_exit(1, "bad state in resume_process()\n");
@@ -1548,8 +1560,16 @@
     else
 	sq->last->next = p;
     sq->last = p;
-    if (p->status != P_EXITING) {
+
+    switch (p->status) {
+    case P_EXITING:
+	break;
+    case P_GARBING:
+	p->gcstatus = P_RUNABLE;
+	break;
+    default:
 	p->status = P_RUNABLE;
+	break;
     }
 
     runq_len++;
@@ -2925,6 +2945,7 @@
     p->max_gen_gcs = 0;
     p->min_heap_size = 0;
     p->status = P_RUNABLE;
+    p->gcstatus = P_RUNABLE;
     p->rstatus = P_RUNABLE;
     p->rcount = 0;
     p->id = ERTS_INVALID_PID;
diff -Naur otp_src_R12B-5/erts/emulator/beam/erl_process.h otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_process.h
--- otp_src_R12B-5/erts/emulator/beam/erl_process.h	2008-11-04 11:51:11.000000000 +0100
+++ otp_src_R12B-5_OTP-7738/erts/emulator/beam/erl_process.h	2009-01-14 10:03:47.000000000 +0100
@@ -207,6 +207,7 @@
 				 * Only valid for the current process.
 				 */
     Uint32 status;		/* process STATE */
+    Uint32 gcstatus;		/* process gc STATE */
     Uint32 rstatus;		/* process resume STATE */
     Uint32 rcount;		/* suspend count */
     Eterm id;			/* The pid of this process */
