Index: globals.h
===================================================================
RCS file: /home/cvs/l4/five/src/globals.h,v
retrieving revision 1.9
diff -u -r1.9 globals.h
--- globals.h	1998/10/02 13:21:44	1.9
+++ globals.h	1998/12/03 23:34:07
@@ -25,6 +25,8 @@
 __EXTERN thread_t *sigma0_thread, *kernel_thread, *nil_thread;
 __EXTERN space_t *sigma0;
 
+__EXTERN bool cli_pagefault_ok;
+
 #undef __EXTERN
 
 // helpers
Index: ipc.cc
===================================================================
RCS file: /home/cvs/l4/five/src/ipc.cc,v
retrieving revision 1.23.2.1
diff -u -r1.23.2.1 ipc.cc
--- ipc.cc	1998/10/23 21:32:06	1.23.2.1
+++ ipc.cc	1998/12/03 18:47:39
@@ -160,6 +160,8 @@
       while ((ret & 0x80000000)); // transient error
 				// re-enter loop even if !(state&polling)
 				// for error handling
+      assert(! in_sender_list());
+  
       if (timeout.is_set())
 	timeout.reset();
 
@@ -439,7 +441,10 @@
       // skipped receive operation
       state_del(Thread_receiving|Thread_waiting|Thread_ipc_in_progress);
 
-      return false;
+      if ((err & L4_IPC_ERROR_MASK) == L4_IPC_ENOT_EXISTENT)
+	return false;
+
+      return true;		// retry
     }
 
   err = do_receive(my_pager, L4_IPC_NEVER, &r);
@@ -451,9 +456,12 @@
 	  printf("page fault rcv error = 0x%x\n", err);
 	  kdb::ke("rcv from pager failed");
 	}
-      
-      return false;
     }
+
+  // XXX currently, we (Jochen-compatibly) ignore receive errors here
+  // and just retry the page fault.  However, maybe it would make
+  // sense to start exception handling (return false) when the pager
+  // returns something which is not a mapping?
 
   return true;
 }
Index: kmem_init.cc
===================================================================
RCS file: /home/cvs/l4/five/src/kmem_init.cc,v
retrieving revision 1.14.2.1
diff -u -r1.14.2.1 kmem_init.cc
--- kmem_init.cc	1998/10/23 21:32:06	1.14.2.1
+++ kmem_init.cc	1998/12/03 23:17:09
@@ -231,6 +231,9 @@
 
   // CPU initialization done
 
+  // get ready to take page faults: initialize global state
+  cli_pagefault_ok = false;
+
   // allocate a generic zero page
   zero_page = stupid_alloc(& himem);
 
Index: space.cc
===================================================================
RCS file: /home/cvs/l4/five/src/space.cc,v
retrieving revision 1.12
diff -u -r1.12 space.cc
--- space.cc	1998/08/15 09:38:13	1.12
+++ space.cc	1998/12/02 18:17:01
@@ -4,6 +4,7 @@
 #include "kmem.h"
 #include "thread.h"
 #include "globals.h"
+#include "kdb.h"
 
 #include "space.h"
 
@@ -187,6 +188,7 @@
 
       // upgrade from read-only to read-write
       *e |= INTEL_PTE_WRITE;
+      return Insert_warn_rw_upgrade;
     }
   else			// we don't have mapped anything
     {
@@ -255,6 +257,9 @@
 	  // no page dir entry -- warp to next page dir entry
 	  va = round_superpage(va + 1) - PAGE_SIZE;
 
+	  if (config::conservative)
+	    kdb::ke("v_delete unmapped pgtable");
+
 	  continue;
 	}
 
@@ -291,6 +296,9 @@
       else
 	e = static_cast<pt_entry_t *>(kmem::phys_to_virt(*p & ~PAGE_MASK))
 	  + ((va >> PTESHIFT) & PTEMASK);
+
+      if (config::conservative && !(*e & INTEL_PTE_VALID))
+	kdb::ke("v_delete unmapped page");
 
       if (read_only)
 	*e &= ~INTEL_PTE_WRITE;
Index: thread.cc
===================================================================
RCS file: /home/cvs/l4/five/src/thread.cc,v
retrieving revision 1.36.2.1
diff -u -r1.36.2.1 thread.cc
--- thread.cc	1998/10/23 21:32:08	1.36.2.1
+++ thread.cc	1998/12/04 01:29:03
@@ -97,6 +97,11 @@
   // dequeued from the ready list but then set ready again, so
   // that our "ready_next" pointer becomes invalid
   cli();
+  __USE_LOOP(
+	     if (in_ready_list() && (my_state & Thread_running))
+	       __USE(ready_next->my_prio);
+	     )
+
   if (in_ready_list())
     {
       if (! (my_state & Thread_running))
@@ -1054,6 +1059,7 @@
       // the thread's local page dir -- copy
 
       space()->kmem_update(pfa);
+      space()->switchin_context();
       return true;
     }
 
@@ -1086,6 +1092,7 @@
 	}
 
       space()->kmem_update(pfa);
+      space()->switchin_context();
       return true;
     }
 
@@ -1101,6 +1108,17 @@
 #if 0
   printf("*P[%x,%x,%x] ", pfa, error_code, (unsigned) __builtin_return_address(1));
 #endif
+
+#if 1
+  if (! (error_code & 4) && ! cli_pagefault_ok)	// in kernel?
+    {
+      unsigned *eflags;
+      asm("movl (%%ebp), %0 ; leal 12(%0), %0" : "=r" (eflags));
+      if (! (*eflags & EFL_IF))
+	kdb::ke("page fault in cli mode");
+    }
+#endif
+  cli_pagefault_ok = false;
 
   return current()->handle_page_fault(pfa, error_code);
 }
Index: thread_list.h
===================================================================
RCS file: /home/cvs/l4/five/src/thread_list.h,v
retrieving revision 1.4
diff -u -r1.4 thread_list.h
--- thread_list.h	1998/06/16 10:17:33	1.4
+++ thread_list.h	1998/12/04 01:27:13
@@ -3,6 +3,19 @@
 #ifndef THREAD_LIST_H
 #define THREAD_LIST_H
 
+#define __USE_LOOP(x) 				\
+  for (;;) 					\
+    {						\
+      cli_pagefault_ok = true;			\
+      { x }					\
+      cli_pagefault_ok = false;			\
+      break; 					\
+    }
+
+#define __USE(x)				\
+  { asm volatile("" : : "r" (x) : "memory");	\
+  if (! cli_pagefault_ok) continue; }
+
 // queue operations
 
 // XXX for now, synchronize via cli/sti pairs
@@ -17,6 +30,26 @@
 {
   unsigned flags = get_eflags();
   cli();
+
+  thread_t *sibling = 0;
+  unsigned i = my_prio;
+
+  __USE_LOOP(
+	      if (! in_ready_list())
+	        {
+		  do 
+		    {
+		      if (++i == 256) i = 0;
+		      sibling = prio_first[i];
+		    }
+		  while (! sibling);	
+		  // loop terminates at least at kernel_thread
+
+		  __USE(sibling->ready_prev);
+		  __USE(sibling->ready_prev->ready_next);
+		}
+	      )
+
   if (! in_ready_list())
     {
       if (! prio_first[my_prio])
@@ -29,16 +62,6 @@
 
       // enqueue as the last tcb of this prio, i.e., just before the
       // first tcb of the next prio
-      thread_t *sibling;
-      unsigned i = my_prio;
-
-      do 
-	{
-	  if (++i == 256) i = 0;
-	  sibling = prio_first[i];
-	}
-      while (! sibling);	// loop terminates at least at kernel_thread
-
       ready_next = sibling;
       ready_prev = sibling->ready_prev;
       sibling->ready_prev = this;
@@ -52,6 +75,15 @@
 {
   unsigned flags = get_eflags();
   cli();
+
+  __USE_LOOP(
+	     if (in_ready_list())
+	       {
+		 __USE(ready_prev->ready_next);
+		 __USE(ready_next->ready_prev);
+	       }
+	     )
+
   if (in_ready_list())
     {
       if (prio_first[my_prio] == this)
@@ -82,6 +114,15 @@
 {
   unsigned flags = get_eflags();
   cli();
+
+  __USE_LOOP(
+	     if (! in_present_list())
+	       {
+		 __USE(sibling->present_next);
+		 __USE(sibling->present_next->present_prev);
+	       }
+	     )
+
   if (! in_present_list())
     {
       present_next = sibling->present_next;
@@ -97,6 +138,15 @@
 {
   unsigned flags = get_eflags();
   cli();
+
+  __USE_LOOP(
+	     if (in_present_list())
+	       {
+		 __USE(present_prev->present_next);
+		 __USE(present_next->present_prev);
+	       }
+	     )
+
   if (in_present_list())
     {
       present_prev->present_next = present_next;
@@ -106,31 +156,6 @@
   set_eflags(flags);
 }
 
-#if 0
-inline sender_t *
-thread_t::sender_dequeue_first()
-{
-  unsigned flags = get_eflags();
-  cli();
-  
-  sender_t *r = sender_first;
-
-  if (r)
-    {
-      if (r->sender_next != r)
-	{
-	  r->sender_next->sender_prev = r->sender_prev;
-	  r->sender_prev->sender_next = r->sender_next;
-	}
-
-      r->sender_next = 0;
-    }
-  set_eflags(flags);
-
-  return r;
-}
-#endif
-
 inline bool 
 sender_t::in_sender_list()
 {
@@ -142,6 +167,19 @@
 {
   unsigned flags = get_eflags();
   cli();
+
+  __USE_LOOP(
+	     if (! in_sender_list()) 
+	       {
+		 __USE(r->sender_first);
+		 if (r->sender_first)
+		   {
+		     __USE(r->sender_first->sender_prev);
+		     __USE(r->sender_first->sender_prev->sender_next);
+		   }
+	       }
+	     )
+	     
   if (! in_sender_list())
     {
       if (r->sender_first)
@@ -164,6 +202,17 @@
 {
   unsigned flags = get_eflags();
   cli();
+
+  // page in stuff we use first;
+  __USE_LOOP(
+	     if (in_sender_list())
+	       {
+		 // __USE(r->sender_first);
+		 __USE(sender_next->sender_prev);
+		 __USE(sender_prev->sender_next);
+	       }
+	     )
+
   if (in_sender_list())
     {
       if (sender_next == this)	// are we alone in the list?
