diff --git a/benchmarks/richards/RICHARDS_MAIL b/benchmarks/richards/RICHARDS_MAIL
new file mode 100644
index 0000000000000000000000000000000000000000..34e3e6a68d154a12006efeb1415603b33e42e76d
--- /dev/null
+++ b/benchmarks/richards/RICHARDS_MAIL
@@ -0,0 +1,63 @@
+Newsgroups: comp.lang.smalltalk
+Distribution: comp
+Subject: Smalltalk vs. C(++) performance
+
+Executive summary: a non-trivial benchmark written in C++ and
+Smalltalk is available from otis.stanford.edu; please send me your
+results.
+-------------------------------------------------------------------
+
+As some have pointed out, it is difficult to compare the runtime
+performance of Smalltalk programs with the performance of equivalent C
+programs.  One reason for this is that for most non-trivial programs
+there is no equivalent program written in the other language (because
+it would be a non-trivial effort to write it).
+
+The "best" benchmark I know of is the Richards benchmark, an operating
+system simulation.  It is written in an object-oriented style, uses
+polymorphism, and is reasonably non-trivial (700 lines).  It's
+probably not the world's greatest benchmark, but better than 
+micro-benchamrks, and it is available in Smalltalk, Self, T (an
+object-oriented version of Scheme) and C++.
+
+[Historical note: the Richards benchmark was originally written in
+BCPL by Mark Richards.  Many thanks to L. Peter Deutsch for the
+Smalltalk version.]
+
+The sources for Richards are available from otis.stanford.edu
+(36.22.0.201) in /pub/benchmarks.  I would be interested in
+comparisons of the performance of the C++ and Smalltalk versions on
+various systems.  We measured it a while ago for the Sun-3/4 versions
+of PP 2.4, and the difference was about a factor of 10.
+
+Disclaimer: Richards is *not* a typical application: it is relatively
+small and contains no graphics or other user interaction.  Thus it may
+not reflect the relative performance of Your Own Real-World (TM)
+Application, but I think it tests the efficiency of the basic language
+mechanisms fairly well.  If you think you have a better benchmark
+which is available both in ST-80 and C (or Fortran or...), please let
+me know.
+
+******* ADVERTISEMENT ******** 
+
+The goal of the Self project at Stanford is to improve the performance
+of dynamically-typed object-oriented languages such as Smalltalk and
+Self.  Though similar to Smalltalk, Self is simpler and more flexible.
+Our current system runs significantly faster than any Smalltalk
+implementation we know of.  For example, here are the numbers for
+Richards on a Sun-4/260:
+
+	C++  (-O2)	730ms
+	Self	       2160ms (Nov'90; 1940ms for an experimental system)
+	PP ST-80 2.4   7740ms
+	T	       9800ms (8100ms with some not-so-kosher "tuning")
+
+[On some other benchmarks, the Stanford Integer Benchmarks, Self
+actually looks even better, running at around 60-70% of the speed of
+optimized C.]
+
+More information (papers, documentation, how to get the current system)
+is available via anonymous ftp from otis.stanford.edu.
+
+******* END OF ADVERTISEMENT ******** 
+
diff --git a/benchmarks/richards/cbase.h b/benchmarks/richards/cbase.h
new file mode 100644
index 0000000000000000000000000000000000000000..d88baddea20adcb80c31521525e966b400859aa8
--- /dev/null
+++ b/benchmarks/richards/cbase.h
@@ -0,0 +1,15 @@
+/* cbase.h */
+
+#ifndef CBASE
+
+#define CBASE
+
+#define BOOLEAN int
+#define TRUE 1
+#define FALSE 0
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#endif
diff --git a/benchmarks/richards/rbase.h b/benchmarks/richards/rbase.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f4abbbaeaf754379d44bd3137048d9db9b8afc0
--- /dev/null
+++ b/benchmarks/richards/rbase.h
@@ -0,0 +1,16 @@
+/* rbase.h */
+#ifndef RBASE
+
+#define RBASE
+
+typedef enum {DevicePacket, WorkPacket} 
+	PacketKind;
+typedef enum {Idler, Worker, HandlerA, HandlerB, DeviceA, DeviceB}
+	Identity;
+
+#define NTASKS 6                        /* # elements of Identity */
+				 	/* = # of tasks		  */
+#define NoWork NULL
+#define NoTask NULL
+
+#endif
diff --git a/benchmarks/richards/richards.c b/benchmarks/richards/richards.c
new file mode 100644
index 0000000000000000000000000000000000000000..7c223cb3f47f4ef9a33248ff4bcd6482f8d9f954
--- /dev/null
+++ b/benchmarks/richards/richards.c
@@ -0,0 +1,235 @@
+/* richards.c - Richards Benchmark in C++ */
+/* uh 2/2/89 */
+
+#include <time.h>
+#define  clock_t long		/* because Sun library isn't ANSI */
+#define  CLK_TCK 1000000
+#include "richards.h"   
+
+
+/*
+// creation
+*/
+
+void RBench::CreateDevice (Identity id, int prio,  Packet *work,
+                           TaskState *state)
+{   DeviceTaskRec *data;
+    TaskControlBlock *t;
+
+    data = new DeviceTaskRec;
+    t = new DeviceTCB(taskList, id, prio, work, state, data);
+    EnterTask(id, t);
+}
+
+
+void RBench::CreateHandler(Identity id, int prio,  Packet *work,
+                           TaskState *state)
+{   HandlerTaskRec *data;
+    TaskControlBlock *t;
+
+    data = new HandlerTaskRec;
+    t = new HandlerTCB(taskList, id, prio, work, state, data);
+    EnterTask(id, t);
+}
+
+
+void RBench::CreateIdler  (Identity id, int prio,  Packet *work,
+                           TaskState *state)
+{   IdleTaskRec *data;
+    TaskControlBlock *t;
+
+    data = new IdleTaskRec;
+    t = new IdlerTCB(taskList, id, prio, work, state, data);
+    EnterTask(id, t);
+}
+
+
+void RBench::CreateWorker (Identity id, int prio,  Packet *work,
+                           TaskState *state)
+{   WorkerTaskRec *data;
+    TaskControlBlock *t;
+
+    data = new WorkerTaskRec;
+    t = new WorkerTCB(taskList, id, prio, work, state, data);
+    EnterTask(id, t);
+}
+
+
+void RBench::EnterTask(Identity id, TaskControlBlock *t)
+{
+    taskList = t;
+    taskTable[id] = t;
+}
+
+
+/*
+//private
+*/
+
+TaskControlBlock *RBench::FindTask(Identity id)
+{   TaskControlBlock *t;
+
+    t = taskTable[id];
+    if (t == NULL) printf("***error: FindTask failed! ");
+    return t;
+}
+
+
+TaskControlBlock *RBench::HoldSelf()
+{
+    holdCount++;
+    currentTask->SetTaskHolding(TRUE);
+    return currentTask->Link();
+}
+
+
+TaskControlBlock *RBench::QueuePacket(Packet *p)
+{   TaskControlBlock *t;
+
+    t = FindTask(p->Ident());
+    queuePacketCount++;
+    p->SetLink(NoWork);
+    p->SetIdent(currentTaskIdent);
+    return t->AddPacket(p, currentTask);
+}
+
+
+TaskControlBlock *RBench::Release(Identity id)
+{   TaskControlBlock *t;
+
+    t = FindTask(id);
+    t->SetTaskHolding(FALSE);
+    return (t->Priority() > currentTask->Priority()) ? t : currentTask;
+}
+
+
+void RBench::Trace(Identity id)
+{
+    if(! --layout) {printf("\n"); layout = 50;} 
+    printf("%d", id + 1);
+}
+
+
+TaskControlBlock *RBench::Wait()
+{
+    currentTask->SetTaskWaiting(TRUE);
+    return currentTask;
+}
+
+
+/*
+//scheduling
+*/
+
+void RBench::Schedule()
+{
+    currentTask = taskList;
+    while (currentTask != NoTask) {
+         if (currentTask->IsTaskHoldingOrWaiting()) 
+              currentTask = currentTask->Link();
+         else {
+              currentTaskIdent = currentTask->Ident();
+              if (tracing) Trace(currentTaskIdent);
+              currentTask = currentTask->RunTask();
+         }
+    }
+}
+
+/*
+//initializing
+*/
+
+void RBench::InitScheduler()
+{
+    queuePacketCount = 0;
+    holdCount = 0;
+    for (int i = 0; i < NTASKS; i++) {taskTable[i] = NoTask;}
+    taskList = NoTask;
+}
+
+
+void RBench::InitTrace()
+{   char c;
+
+    printf("Trace (y/n)? ");
+    c = getchar();
+    tracing = (_toupper(c) == 'Y');
+}
+
+
+void RBench::Start(BOOLEAN trace) {
+//    clock_t t1, t2, t3, t4;
+    TaskState *t;
+    Packet *workQ;
+
+    if (trace) InitTrace(); else tracing = FALSE;
+    InitScheduler();
+//    t1 = clock();
+//    printf("\nRichards benchmark: initializing...\n");
+    t = new TaskState; t->Running();				// Idler
+    CreateIdler(Idler, 0, NoWork, t);
+
+    workQ = new Packet(NoWork, Worker, WorkPacket);		// Worker
+    workQ = new Packet(workQ , Worker, WorkPacket);
+    t = new TaskState; t->WaitingWithPacket();
+    CreateWorker(Worker, 1000, workQ, t);
+
+    workQ = new Packet(NoWork, DeviceA, DevicePacket);		// HandlerA
+    workQ = new Packet(workQ , DeviceA, DevicePacket);
+    workQ = new Packet(workQ , DeviceA, DevicePacket);
+    t = new TaskState; t->WaitingWithPacket();
+    CreateHandler(HandlerA, 2000, workQ, t);
+
+    workQ = new Packet(NoWork, DeviceB, DevicePacket);		// HandlerB
+    workQ = new Packet(workQ , DeviceB, DevicePacket);
+    workQ = new Packet(workQ , DeviceB, DevicePacket);
+    t = new TaskState; t->WaitingWithPacket();
+    CreateHandler(HandlerB, 3000, workQ, t);
+
+    t = new TaskState; t->Waiting();				// DeviceA
+    CreateDevice(DeviceA, 4000, NoWork, t);
+    t = new TaskState; t->Waiting();				// DeviceB
+    CreateDevice(DeviceB, 5000, NoWork, t);
+
+//    printf("starting...\n");
+//    t2 = clock();
+    Schedule();
+//    t3 = clock();
+//    printf("done.\n");
+
+//    printf("QueuePacketCount = %d, HoldCount = %d.\nThese results are %s",
+//           queuePacketCount, holdCount,
+//           (queuePacketCount == 23246 && holdCount == 9297) ? 
+//                "correct." : "wrong!"
+//          );
+    if (! (queuePacketCount == 23246 && holdCount == 9297)) {
+      printf("error: richards results are incorrect\n");
+    }
+
+//    t4 = clock();
+//    printf("\nScheduler time = %g seconds, total time = %g\n",
+//           (double)(t3 - t2) / CLK_TCK,
+//           (double)(t4 - t1) / CLK_TCK);
+}
+
+
+#define ITER  10		/* # of iterations in main loop  */
+
+int main()
+{   clock_t t_start, t_stop;
+
+    t_start = clock();
+    for (int i = 0; i < ITER; i++) 
+        bm.Start(ITER == 1);
+    t_stop = clock();
+
+    clock_t diff = (t_stop - t_start)/ITER;
+
+    printf("richards: %d ms\n", diff/(CLK_TCK/1000));
+
+//    if (ITER > 1) 
+//         printf("\n*** %d iterations, average of %g secs / iteration.\n",
+//		ITER,
+//		(double)(t_stop - t_start) / (ITER * CLK_TCK));
+}
+
diff --git a/benchmarks/richards/richards.h b/benchmarks/richards/richards.h
new file mode 100644
index 0000000000000000000000000000000000000000..87f8191e6d2a2198c30c97947f2cce888a206bc5
--- /dev/null
+++ b/benchmarks/richards/richards.h
@@ -0,0 +1,52 @@
+/* richards.h */
+/* Richards benchmark in C++, translated from Smalltalk */
+/* uh 2/2/89  */
+
+#include "rbase.h" 
+#include "tasks.h"
+
+/*
+// RBench class definition
+*/
+
+class RBench {
+    private:
+         TaskControlBlock *taskList, *currentTask;
+         Identity currentTaskIdent;
+         TaskControlBlock *taskTable[NTASKS];
+         int layout;
+         int holdCount, queuePacketCount;
+
+         /* creation */
+         void CreateDevice (Identity id, int prio,  Packet *work,
+                           TaskState *state);
+         void CreateHandler(Identity id, int prio,  Packet *work,
+                           TaskState *state);
+         void CreateIdler  (Identity id, int prio,  Packet *work,
+                           TaskState *state);
+         void CreateWorker (Identity id, int prio,  Packet *work,
+                           TaskState *state);
+         void EnterTask(Identity id, TaskControlBlock *t);
+
+         /* scheduling */
+         void Schedule();
+
+         /* initializing */
+         void InitScheduler();
+         void InitTrace();
+    public:
+         /* task management */
+         TaskControlBlock *FindTask(Identity id);
+         TaskControlBlock *HoldSelf();
+         TaskControlBlock *QueuePacket(Packet *p);
+         TaskControlBlock *Release(Identity id);
+         TaskControlBlock *Wait();
+         /* tracing */
+         BOOLEAN tracing;
+         void Trace(Identity id);
+
+         void Start(BOOLEAN askTrace);
+};
+
+RBench bm;		// benchmark currently executing
+
diff --git a/benchmarks/richards/richards.lisp b/benchmarks/richards/richards.lisp
new file mode 100644
index 0000000000000000000000000000000000000000..cd29c02495c6489a0412825deda93bbbaad00e10
--- /dev/null
+++ b/benchmarks/richards/richards.lisp
@@ -0,0 +1,407 @@
+(in-package "USER")
+#+declare-unsafe
+(proclaim '(optimize speed (space 0) (safety 0) (compilation-speed 0)))
+
+(defconstant deviceA 5)
+(defconstant deviceB 6)
+(defconstant devicePacketKind 1)
+(defconstant handlerA 3)
+(defconstant handlerB 4)
+(defconstant idler 1)
+(defconstant noWork nil)
+(defconstant noTask nil)
+(defconstant worker 2)
+(defconstant workPacketKind 2)
+
+(defvar taskList noTask)
+(defvar currentTask nil)
+(defvar currentTaskIdentity nil)
+(defvar taskTable (make-array 6 :initial-element noTask))
+(proclaim '(simple-vector taskTable))
+(defvar tracing nil)
+(defvar layout 0)
+(defvar queuePacketCount 0)
+(defvar holdCount 0)
+(proclaim '(fixnum layout queuePacketCount holdCount))
+
+(declaim (inline make-taskControlBlock make-packet make-deviceTaskDataRecord
+		 make-handlerTaskDataRecord make-idleTaskDataRecord
+		 make-workerTaskDataRecord wait))
+
+(defstruct (taskControlBlock (:constructor make-taskControlBLock ()))
+  packetPending taskWaiting taskHolding link identity
+  (priority 0 :type fixnum)
+  input state handle)
+
+(defstruct (packet (:constructor make-packet ()))
+  link identity
+  (kind 0 :type fixnum)
+  (datum 0 :type fixnum) 
+  (data '#() :type simple-vector))
+
+(defstruct (deviceTaskDataRecord (:constructor make-deviceTaskDataRecord ()))
+  pending)
+
+(defstruct (handlerTaskDataRecord (:constructor make-handlerTaskDataRecord ()))
+  workIn deviceIn)
+
+(defstruct (idleTaskDataRecord (:constructor make-idleTaskDataRecord ()))
+  (control 0 :type fixnum)
+  (count 0 :type fixnum))
+
+(defstruct (workerTaskDataRecord (:constructor make-workerTaskDataRecord ()))
+  (destination 0 :type fixnum)
+  (count 0 :type fixnum))
+
+(defun wait ()
+  (setf (taskControlBlock-taskWaiting currentTask) t)
+  currentTask)
+
+#+cmu
+(declaim (ext:freeze-type taskControlBlock packet deviceTaskDataRecord
+			  handlerTaskDataRecord idleTaskDataRecord
+			  workerTaskDataRecord))
+#+cmu
+(declaim (ext:start-block richards))
+
+(defun deviceTaskDataRecord-run (self work)
+  (let ((functionWork work))
+    (if (eq noWork functionWork)
+	(progn
+	 (setq functionWork (deviceTaskDataRecord-pending self))
+	 (if (eq noWork functionWork)
+	     (wait)
+	   (progn
+	    (setf (deviceTaskDataRecord-pending self) noWork)
+	    (queuePacket functionWork))))
+      (progn
+       (setf (deviceTaskDataRecord-pending self) functionWork)
+       (if tracing (trace-it (packet-datum functionWork)))
+       (holdSelf)))))
+
+(defun handlerTaskDataRecord-run (self work)
+  (if (eq noWork work)
+      nil
+    (if (= workPacketKind (packet-kind work))
+	(workInAdd self work)
+      (deviceInAdd self work)))
+  (let ((workPacket (handlerTaskDataRecord-workIn self)))
+    (if (eq noWork workPacket)
+	(wait)
+      (let ((count (packet-datum workPacket)))
+	(if (> count 4)
+	    (progn
+	     (setf (handlerTaskDataRecord-workIn self)
+		   (packet-link workPacket))
+	     (queuePacket workPacket))
+	  (let ((devicePacket (handlerTaskDataRecord-deviceIn self)))
+	    (if (eq noWork devicePacket)
+		(wait)
+	      (progn
+	       (setf (handlerTaskDataRecord-deviceIn self)
+		     (packet-link devicePacket))
+	       (setf (packet-datum devicePacket)
+		     (svref (packet-data workPacket) (- count 1)))
+	       (setf (packet-datum workPacket) (+ count 1))
+	       (queuePacket devicePacket)))))))))
+
+(defun idleTaskDataRecord-run (self work)
+  (declare (ignore work))
+  (setf (idleTaskDataRecord-count self)
+	(- (idleTaskDataRecord-count self) 1))
+  (if (= 0 (idleTaskDataRecord-count self))
+      (holdSelf)
+    (if (= 0 (logand (idleTaskDataRecord-control self) 1))
+	(progn
+	 (setf (idleTaskDataRecord-control self)
+	       (floor (idleTaskDataRecord-control self) 2))
+	 (release deviceA))
+      (progn
+       (setf (idleTaskDataRecord-control self)
+	     (logxor (floor (idleTaskDataRecord-control self) 2)
+		     53256))
+       (release deviceB)))))
+
+(defun workerTaskDataRecord-run (self work)
+  (if (eq noWork work)
+      (wait)
+    (progn
+     (setf (workerTaskDataRecord-destination self)
+	   (if (= handlerA (workerTaskDataRecord-destination self))
+	       handlerB
+	     handlerA))
+     (setf (packet-identity work) (workerTaskDataRecord-destination self))
+     (setf (packet-datum work) 1)
+     (do ((i 0 (+ i 1)))
+	 ((> i 3) nil)
+       (declare (fixnum i))
+	 (setf (workerTaskDataRecord-count self)
+	       (+ (workerTaskDataRecord-count self) 1))
+	 (if (> (workerTaskDataRecord-count self) 256)
+	     (setf (workerTaskDataRecord-count self) 1))
+	 (setf (svref (packet-data work) i)
+	       (the fixnum
+		    (+ (char-code #\A)
+		       (- (workerTaskDataRecord-count self) 1)))))
+     (queuePacket work))))
+
+(defun appendHead (packet queueHead)
+  (setf (packet-link packet) noWork)
+  (if (eq noWork queueHead)
+      packet
+    (let ((mouse queueHead))
+      (let ((link (packet-link mouse)))
+	(do ()
+	    ((eq noWork link) nil)
+	    (setq mouse link)
+	    (setq link (packet-link mouse)))
+	(setf (packet-link mouse) packet)
+	queueHead))))
+
+(defun initialize-globals ()
+  (setq taskList noTask)
+  (setq currentTask nil)
+  (setq currentTaskIdentity nil)
+  (setq taskTable (make-array 6 :initial-element noTask))
+  (setq tracing nil)
+  (setq layout 0)
+  (setq queuePacketCount 0)
+  (setq holdCount 0))
+
+(defun richards ()
+  (initialize-globals)
+
+  (createIdler idler 0 noWork (running (make-taskControlBlock)))
+
+  (let ((workQ))
+
+    (setq workQ (createPacket noWork worker workPacketKind))
+    (setq workQ (createPacket workQ worker workPacketKind))
+    (createWorker worker 1000 workQ (waitingWithPacket))
+
+    (setq workQ (createPacket noWork deviceA devicePacketKind))
+    (setq workQ (createPacket workQ deviceA devicePacketKind))
+    (setq workQ (createPacket workQ deviceA devicePacketKind))
+    (createHandler handlerA 2000 workQ (waitingWithPacket))
+    
+    (setq workQ (createPacket noWork deviceB devicePacketKind))
+    (setq workQ (createPacket workQ deviceB devicePacketKind))
+    (setq workQ (createPacket workQ deviceB devicePacketKind))
+    (createHandler handlerB 3000 workQ (waitingWithPacket))
+    
+    (createDevice deviceA 4000 noWork (waiting))
+    (createDevice deviceB 5000 noWork (waiting))
+
+    )
+
+  (schedule)
+
+  (if (not (and (= queuePacketCount 23246) (= holdCount 9297)))
+      (error "richards results incorrect"))
+
+  nil)
+
+(defun schedule ()
+  (setq currentTask taskList)
+  (do ()
+      ((eq noTask currentTask) nil)
+    (if (isTaskHoldingOrWaiting currentTask)
+	(setq currentTask (taskControlBlock-link currentTask))
+	(progn
+	 (setq currentTaskIdentity (taskControlBlock-identity currentTask))
+	 (if tracing (trace-it currentTaskIdentity))
+	 (setq currentTask (runTask currentTask))))))
+
+(defun findTask (identity)
+  (declare (fixnum identity))
+  (let ((tk (svref taskTable (- identity 1))))
+    (if (eq noTask tk) (error "findTask failed"))
+    tk))
+
+(defun holdSelf ()
+  (setq holdCount (+ holdCount 1))
+  (setf (taskControlBlock-taskHolding currentTask) t)
+  (taskControlBlock-link currentTask))
+
+(defun queuePacket (packet)
+  (let ((tk (findTask (packet-identity packet))))
+    (if (eq noTask tk)
+	noTask
+	(progn
+	 (setq queuePacketCount (+ queuePacketCount 1))
+	 (setf (packet-link packet) noWork)
+	 (setf (packet-identity packet) currentTaskIdentity)
+	 (addInput tk packet currentTask)))))
+
+(defun release (identity)
+  (let ((tk (findTask identity)))
+    (if (eq noTask tk)
+	noTask
+	(progn
+	 (setf (taskControlBlock-taskHolding tk) nil)
+	 (if (> (taskControlBlock-priority tk)
+		(taskControlBlock-priority currentTask))
+	     tk
+	     currentTask)))))
+
+(defun trace-it (id)
+  (setq layout (- layout 1))
+  (if (>= 0 layout)
+      (progn
+       (format t "~%")
+       (setq layout 30)))
+  (format t "~a " id))
+
+(defun createDevice (identity priority work state)
+  (let ((data (create-deviceTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(defun createHandler (identity priority work state)
+  (let ((data (create-handlerTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(defun createIdler (identity priority work state)
+  (let ((data (create-idleTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(defun createWorker (identity priority work state)
+  (let ((data (create-workerTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(defun createTask (identity priority work state data)
+  (let ((tk (create-taskControlBlock
+	     taskList identity priority work state data)))
+    (setq taskList tk)
+    (setf (svref taskTable (- identity 1)) tk)))
+
+(defun createPacket (link identity kind)
+  (create-packet link identity kind))
+
+(defun running (tcb)
+  (setf (taskControlBlock-packetPending tcb) nil)
+  (setf (taskControlBlock-taskWaiting tcb) nil)
+  (setf (taskControlBlock-taskHolding tcb) nil)
+  tcb)
+
+(defun waiting ()
+  (let ((tcb (make-taskControlBlock)))
+    (setf (taskControlBlock-packetPending tcb) nil)
+    (setf (taskControlBlock-taskWaiting tcb) t)
+    (setf (taskControlBlock-taskHolding tcb) nil)
+    tcb))
+
+(defun waitingWithPacket ()
+  (let ((tcb (make-taskControlBlock)))
+    (setf (taskControlBlock-packetPending tcb) t)
+    (setf (taskControlBlock-taskWaiting tcb) t)
+    (setf (taskControlBlock-taskHolding tcb) nil)
+    tcb))
+
+(defun isTaskHoldingOrWaiting (tcb)
+  (or (taskControlBlock-taskHolding tcb)
+      (and (not (taskControlBlock-packetPending tcb))
+	   (taskControlBlock-taskWaiting tcb))))
+
+(defun isWaitingWithPacket (tcb)
+  (and (taskControlBlock-packetPending tcb)
+       (and (taskControlBlock-taskWaiting tcb)
+	    (not (taskControlBlock-taskHolding tcb)))))
+
+(defun packetNowPending (tcb)
+  (setf (taskControlBlock-packetPending tcb) t)
+  (setf (taskControlBlock-taskWaiting tcb) nil)
+  (setf (taskControlBlock-taskHolding tcb) nil)
+  tcb)
+
+(defun create-taskControlBlock
+  (link identity priority initialWorkQueue initialState privateData)
+  (let ((r (make-taskControlBlock)))
+    (setf (taskControlBlock-link r) link)
+    (setf (taskControlBlock-identity r) identity)
+    (setf (taskControlBlock-priority r) priority)
+    (setf (taskControlBlock-input r) initialWorkQueue)
+    (setf (taskControlBlock-packetPending r)
+	 (taskControlBlock-packetPending initialState))
+    (setf (taskControlBlock-taskWaiting r)
+	 (taskControlBlock-taskWaiting initialState))
+    (setf (taskControlBlock-taskHolding r)
+	 (taskControlBlock-taskHolding initialState))
+    (setf (taskControlBlock-handle r) privateData)
+    (setf (taskControlBlock-state r) nil)
+    r))
+
+(defun addInput (tcb packet oldTask)
+  (if (eq noWork (taskControlBlock-input tcb))
+      (progn
+       (setf (taskControlBlock-input tcb) packet)
+       (setf (taskControlBlock-packetPending tcb) t)
+       (if (> (taskControlBlock-priority tcb)
+	      (taskControlBlock-priority oldTask))
+	   tcb
+	   oldTask))
+      (progn
+       (setf (taskControlBlock-input tcb)
+	    (appendHead packet (taskControlBlock-input tcb)))
+       oldTask)))
+
+(defun runTask (tcb)
+  (let ((message nil))
+    (if (isWaitingWithPacket tcb)
+	(progn
+	  (setq message (taskControlBlock-input tcb))
+	  (setf (taskControlBlock-input tcb) (packet-link message))
+	  (if (eq noWork (taskControlBlock-input tcb))
+	      (running tcb)
+	    (packetNowPending tcb)))
+      (setq message noWork))
+    (run (taskControlBlock-handle tcb) message)))
+
+(defun run (self work)
+  (typecase self
+	    (deviceTaskDataRecord (deviceTaskDataRecord-run self work))
+	    (handlerTaskDataRecord (handlerTaskDataRecord-run self work))
+	    (idleTaskDataRecord (idleTaskDataRecord-run self work))
+	    (workerTaskDataRecord (workerTaskDataRecord-run self work))))
+
+(defun create-packet (link identity kind)
+  (let ((p (make-packet)))
+    (setf (packet-link p) link)
+    (setf (packet-identity p) identity)
+    (setf (packet-kind p) kind)
+    (setf (packet-datum p) 1)
+    (let ((v (make-array 4 :initial-element 0)))
+      (setf (packet-data p) v))
+    p))
+
+(defun create-deviceTaskDataRecord ()
+  (let ((tk (make-deviceTaskDataRecord)))
+    (setf (deviceTaskDataRecord-pending tk) noWork)
+    tk))
+
+(defun create-handlerTaskDataRecord ()
+  (let ((tk (make-handlerTaskDataRecord)))
+    (setf (handlerTaskDataRecord-workIn tk) noWork)
+    (setf (handlerTaskDataRecord-deviceIn tk) noWork)
+    tk))
+
+(defun deviceInAdd (tk packet)
+  (setf (handlerTaskDataRecord-deviceIn tk)
+       (appendHead packet (handlerTaskDataRecord-deviceIn tk)))
+  tk)
+
+(defun workInAdd (tk packet)
+  (setf (handlerTaskDataRecord-workIn tk)
+       (appendHead packet (handlerTaskDataRecord-workIn tk)))
+  tk)
+
+(defun create-idleTaskDataRecord ()
+  (let ((tk (make-idleTaskDataRecord)))
+    (setf (idleTaskDataRecord-control tk) 1)
+    (setf (idleTaskDataRecord-count tk) 10000)
+    tk))
+
+(defun create-workerTaskDataRecord ()
+  (let ((tk (make-workerTaskDataRecord)))
+    (setf (workerTaskDataRecord-destination tk) handlerA)
+    (setf (workerTaskDataRecord-count tk) 0)
+    tk))
diff --git a/benchmarks/richards/richards.t b/benchmarks/richards/richards.t
new file mode 100644
index 0000000000000000000000000000000000000000..4368dbfe4d685591906ce99acdd1f28f2be7b1ed
--- /dev/null
+++ b/benchmarks/richards/richards.t
@@ -0,0 +1,378 @@
+(herald richards)
+
+(define deviceA 5)
+(define deviceB 6)
+(define devicePacketKind 1)
+(define handlerA 3)
+(define handlerB 4)
+(define idler 1)
+(define noWork nil)
+(define noTask nil)
+(define worker 2)
+(define workPacketKind 2)
+
+(lset taskList noTask)
+(lset currentTask nil)
+(lset currentTaskIdentity nil)
+(lset taskTable (make-vector 6))
+(lset tracing nil)
+(lset layout 0)
+(lset queuePacketCount 0)
+(lset holdCount 0)
+
+(define-operation (run self work))
+
+(vector-fill taskTable noTask)
+
+(define (hash-obj l)
+  (if l (object-hash l) nil))
+
+(define-structure-type taskControlBlock
+  packetPending taskWaiting taskHolding link identity priority input state
+  handle)
+
+(define-structure-type packet
+  link identity kind datum data)
+
+(define-structure-type deviceTaskDataRecord
+  pending
+  (((run self work)
+    (lset functionWork work)
+    (if (equal? noWork functionWork)
+	(block
+	 (set functionWork (deviceTaskDataRecord-pending self))
+	 (if (equal? noWork functionWork)
+	     (wait)
+	     (block
+	      (set (deviceTaskDataRecord-pending self) noWork)
+	      (queuePacket functionWork))))
+	(block
+	 (set (deviceTaskDataRecord-pending self) functionWork)
+	 (if tracing (trace (packet-datum functionWork)))
+	 (holdSelf))))))
+
+(define-structure-type handlerTaskDataRecord
+  workIn deviceIn
+  (((run self work)
+    (if (equal? noWork work)
+	nil
+	(if (equal? workPacketKind (packet-kind work))
+	    (workInAdd self work)
+	    (deviceInAdd self work)))
+    (let ((workPacket (handlerTaskDataRecord-workIn self)))
+      (if (equal? noWork workPacket)
+	  (wait)
+	  (let ((count (packet-datum workPacket)))
+	    (if (> count 4)
+		(block
+		 (set (handlerTaskDataRecord-workIn self)
+		      (packet-link workPacket))
+		 (queuePacket workPacket))
+		(let ((devicePacket (handlerTaskDataRecord-deviceIn self)))
+		  (if (equal? noWork devicePacket)
+		      (wait)
+		      (block
+		       (set (handlerTaskDataRecord-deviceIn self)
+			    (packet-link devicePacket))
+		       (set (packet-datum devicePacket)
+			    (vref (packet-data workPacket) (- count 1)))
+		       (set (packet-datum workPacket) (+ count 1))
+		       (queuePacket devicePacket)))))))))))
+
+(define-structure-type idleTaskDataRecord
+  control count
+  (((run self work)
+    (ignorable work)
+    (set (idleTaskDataRecord-count self)
+	 (- (idleTaskDataRecord-count self) 1))
+    (if (equal? 0 (idleTaskDataRecord-count self))
+	(holdSelf)
+	(if (equal? 0 (logand (idleTaskDataRecord-control self) 1))
+	    (block
+	     (set (idleTaskDataRecord-control self)
+		  (quotient (idleTaskDataRecord-control self) 2))
+	     (release deviceA))
+	    (block
+	     (set (idleTaskDataRecord-control self)
+		  (logxor (quotient (idleTaskDataRecord-control self) 2)
+			  53256))
+	     (release deviceB)))))))
+
+(define-structure-type workerTaskDataRecord
+  destination count
+  (((run self work)
+    (if (equal? noWork work)
+	(wait)
+	(block
+	 (set (workerTaskDataRecord-destination self)
+	      (if (equal? handlerA (workerTaskDataRecord-destination self))
+		  handlerB
+		  handlerA))
+	 (set (packet-identity work) (workerTaskDataRecord-destination self))
+	 (set (packet-datum work) 1)
+	 (do ((i 0 (+ i 1)))
+	     ((> i 3) nil)
+	   (set (workerTaskDataRecord-count self)
+		(+ (workerTaskDataRecord-count self) 1))
+	   (if (> (workerTaskDataRecord-count self) 256)
+	       (set (workerTaskDataRecord-count self) 1))
+	   (vset (packet-data work) i
+		 (+ (char->ascii #\A)
+		    (- (workerTaskDataRecord-count self) 1))))
+	 (queuePacket work))))))
+
+(define (appendHead packet queueHead)
+  (set (packet-link packet) noWork)
+  (if (equal? noWork queueHead)
+      packet
+      (block
+       (lset mouse queueHead)
+       (lset link (packet-link mouse))
+       (do ()
+	   ((equal? noWork link) nil)
+	 (set mouse link)
+	 (set link (packet-link mouse)))
+       (set (packet-link mouse) packet)
+       queueHead)))
+
+(define (initialize-globals)
+  (set taskList noTask)
+  (set currentTask nil)
+  (set currentTaskIdentity nil)
+  (set taskTable (make-vector 6))
+  (set tracing nil)
+  (set layout 0)
+  (set queuePacketCount 0)
+  (set holdCount 0)
+  (vector-fill taskTable noTask))
+
+(define (richards)
+  (initialize-globals)
+
+  (createIdler idler 0 noWork (running (make-taskControlBlock)))
+
+  (lset workQ (createPacket noWork worker workPacketKind))
+  (set workQ (createPacket workQ worker workPacketKind))
+  (createWorker worker 1000 workQ (waitingWithPacket))
+
+  (set workQ (createPacket noWork deviceA devicePacketKind))
+  (set workQ (createPacket workQ deviceA devicePacketKind))
+  (set workQ (createPacket workQ deviceA devicePacketKind))
+  (createHandler handlerA 2000 workQ (waitingWithPacket))
+
+  (set workQ (createPacket noWork deviceB devicePacketKind))
+  (set workQ (createPacket workQ deviceB devicePacketKind))
+  (set workQ (createPacket workQ deviceB devicePacketKind))
+  (createHandler handlerB 3000 workQ (waitingWithPacket))
+
+  (createDevice deviceA 4000 noWork (waiting))
+  (createDevice deviceB 5000 noWork (waiting))
+
+  (schedule)
+
+  (if (not (and (equal? queuePacketCount 23246) (equal? holdCount 9297)))
+      (error "richards results incorrect"))
+
+  nil)
+
+(define (schedule)
+  (set currentTask taskList)
+  (do ()
+      ((equal? noTask currentTask) nil)
+    (if (isTaskHoldingOrWaiting currentTask)
+	(set currentTask (taskControlBlock-link currentTask))
+	(block
+	 (set currentTaskIdentity (taskControlBlock-identity currentTask))
+	 (if tracing (trace currentTaskIdentity))
+	 (set currentTask (runTask currentTask))))))
+
+(define (findTask identity)
+  (let ((tk (vref taskTable (- identity 1))))
+    (if (equal? noTask tk) (error "findTask failed"))
+    tk))
+
+(define (holdSelf)
+  (set holdCount (+ holdCount 1))
+  (set (taskControlBlock-taskHolding currentTask) t)
+  (taskControlBlock-link currentTask))
+
+(define (queuePacket packet)
+  (let ((tk (findTask (packet-identity packet))))
+    (if (equal? noTask tk)
+	noTask
+	(block
+	 (set queuePacketCount (+ queuePacketCount 1))
+	 (set (packet-link packet) noWork)
+	 (set (packet-identity packet) currentTaskIdentity)
+	 (addInput tk packet currentTask)))))
+
+(define (release identity)
+  (let ((tk (findTask identity)))
+    (if (equal? noTask tk)
+	noTask
+	(block
+	 (set (taskControlBlock-taskHolding tk) nil)
+	 (if (> (taskControlBlock-priority tk)
+		(taskControlBlock-priority currentTask))
+	     tk
+	     currentTask)))))
+
+(define (trace id)
+  (set layout (- layout 1))
+  (if (>= 0 layout)
+      (block
+       (format (debug-output) "~%")
+       (set layout 30)))
+  (format (debug-output) "~a " id))
+
+(define (wait)
+  (set (taskControlBlock-taskWaiting currentTask) t)
+  currentTask)
+
+(define (createDevice identity priority work state)
+  (let ((data (create-deviceTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(define (createHandler identity priority work state)
+  (let ((data (create-handlerTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(define (createIdler identity priority work state)
+  (let ((data (create-idleTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(define (createWorker identity priority work state)
+  (let ((data (create-workerTaskDataRecord)))
+    (createTask identity priority work state data)))
+
+(define (createTask identity priority work state data)
+  (let ((tk (create-taskControlBlock
+	     taskList identity priority work state data)))
+    (set taskList tk)
+    (vset taskTable (- identity 1) tk)))
+
+(define (createPacket link identity kind)
+  (create-packet link identity kind))
+
+(define (running tcb)
+  (set (taskControlBlock-packetPending tcb) nil)
+  (set (taskControlBlock-taskWaiting tcb) nil)
+  (set (taskControlBlock-taskHolding tcb) nil)
+  tcb)
+
+(define (waiting)
+  (let ((tcb (make-taskControlBlock)))
+    (set (taskControlBlock-packetPending tcb) nil)
+    (set (taskControlBlock-taskWaiting tcb) t)
+    (set (taskControlBlock-taskHolding tcb) nil)
+    tcb))
+
+(define (waitingWithPacket)
+  (let ((tcb (make-taskControlBlock)))
+    (set (taskControlBlock-packetPending tcb) t)
+    (set (taskControlBlock-taskWaiting tcb) t)
+    (set (taskControlBlock-taskHolding tcb) nil)
+    tcb))
+
+(define (isTaskHoldingOrWaiting tcb)
+  (or (taskControlBlock-taskHolding tcb)
+      (and (not (taskControlBlock-packetPending tcb))
+	   (taskControlBlock-taskWaiting tcb))))
+
+(define (isWaitingWithPacket tcb)
+  (and (taskControlBlock-packetPending tcb)
+       (and (taskControlBlock-taskWaiting tcb)
+	    (not (taskControlBlock-taskHolding tcb)))))
+
+(define (packetNowPending tcb)
+  (set (taskControlBlock-packetPending tcb) t)
+  (set (taskControlBlock-taskWaiting tcb) nil)
+  (set (taskControlBlock-taskHolding tcb) nil)
+  tcb)
+
+(define (create-taskControlBlock
+	 link identity priority initialWorkQueue initialState privateData)
+  (let ((r (make-taskControlBlock)))
+    (set (taskControlBlock-link r) link)
+    (set (taskControlBlock-identity r) identity)
+    (set (taskControlBlock-priority r) priority)
+    (set (taskControlBlock-input r) initialWorkQueue)
+    (set (taskControlBlock-packetPending r)
+	 (taskControlBlock-packetPending initialState))
+    (set (taskControlBlock-taskWaiting r)
+	 (taskControlBlock-taskWaiting initialState))
+    (set (taskControlBlock-taskHolding r)
+	 (taskControlBlock-taskHolding initialState))
+    (set (taskControlBlock-handle r) privateData)
+    (set (taskControlBlock-state r) nil)
+    r))
+
+(define (addInput tcb packet oldTask)
+  (if (equal? noWork (taskControlBlock-input tcb))
+      (block
+       (set (taskControlBlock-input tcb) packet)
+       (set (taskControlBlock-packetPending tcb) t)
+       (if (> (taskControlBlock-priority tcb)
+	      (taskControlBlock-priority oldTask))
+	   tcb
+	   oldTask))
+      (block
+       (set (taskControlBlock-input tcb)
+	    (appendHead packet (taskControlBlock-input tcb)))
+       oldTask)))
+
+(define (runTask tcb)
+  (lset message nil)
+  (if (isWaitingWithPacket tcb)
+      (block
+       (set message (taskControlBlock-input tcb))
+       (set (taskControlBlock-input tcb) (packet-link message))
+       (if (equal? noWork (taskControlBlock-input tcb))
+	   (running tcb)
+	   (packetNowPending tcb)))
+      (set message noWork))
+  (run (taskControlBlock-handle tcb) message))
+
+(define (create-packet link identity kind)
+  (let ((p (make-packet)))
+    (set (packet-link p) link)
+    (set (packet-identity p) identity)
+    (set (packet-kind p) kind)
+    (set (packet-datum p) 1)
+    (let ((v (make-vector 4)))
+      (vector-fill v 0)
+      (set (packet-data p) v))
+    p))
+
+(define (create-deviceTaskDataRecord)
+  (let ((tk (make-deviceTaskDataRecord)))
+    (set (deviceTaskDataRecord-pending tk) noWork)
+    tk))
+
+(define (create-handlerTaskDataRecord)
+  (let ((tk (make-handlerTaskDataRecord)))
+    (set (handlerTaskDataRecord-workIn tk) noWork)
+    (set (handlerTaskDataRecord-deviceIn tk) noWork)
+    tk))
+
+(define (deviceInAdd tk packet)
+  (set (handlerTaskDataRecord-deviceIn tk)
+       (appendHead packet (handlerTaskDataRecord-deviceIn tk)))
+  tk)
+
+(define (workInAdd tk packet)
+  (set (handlerTaskDataRecord-workIn tk)
+       (appendHead packet (handlerTaskDataRecord-workIn tk)))
+  tk)
+
+(define (create-idleTaskDataRecord)
+  (let ((tk (make-idleTaskDataRecord)))
+    (set (idleTaskDataRecord-control tk) 1)
+    (set (idleTaskDataRecord-count tk) 10000)
+    tk))
+
+(define (create-workerTaskDataRecord)
+  (let ((tk (make-workerTaskDataRecord)))
+    (set (workerTaskDataRecord-destination tk) handlerA)
+    (set (workerTaskDataRecord-count tk) 0)
+    tk))
diff --git a/benchmarks/richards/tasks.c b/benchmarks/richards/tasks.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d4b6ef637a67f93fe3ffdccd3e5ac8d50b4aab0
--- /dev/null
+++ b/benchmarks/richards/tasks.c
@@ -0,0 +1,153 @@
+/* tasks.c */
+
+#include "tasks.h"
+#include "richards.h"
+
+/*
+// TaskControlBlock
+*/
+
+TaskControlBlock::TaskControlBlock(TaskControlBlock *l, Identity id, int prio,
+                         Packet *initialWork, TaskState *initialState,
+                         void *privateData)
+{
+    link = l; ident = id; priority = prio; input = initialWork;
+    packetPending = initialState->IsPacketPending();
+    taskWaiting = initialState->IsTaskWaiting();
+    taskHolding = initialState->IsTaskHolding();
+    handle = privateData;
+}
+
+
+TaskControlBlock *TaskControlBlock::AddPacket(Packet *p,
+                                              TaskControlBlock *oldTask)
+{
+    if (input == NoWork) {
+         input = p;
+         packetPending = TRUE;
+         if (priority > oldTask->priority) return this;
+    }
+    else AddToList(input, p);
+    return oldTask;
+}
+
+
+TaskControlBlock *TaskControlBlock::RunTask()
+{   Packet *msg;
+
+    if (IsWaitingWithPacket()) {
+         msg = input;
+         input = input->Link();
+         if (input == NoWork)
+              Running();
+         else PacketPending();
+    }
+    else msg = NoWork;
+    return this->ActionFunc(msg, handle);
+}
+
+
+/*
+// action functions
+*/
+
+TaskControlBlock *TaskControlBlock::ActionFunc(Packet *p, void *handle)
+{
+    p, handle, 0;
+    printf("***error: virtual TaskControlBlock.ActionFunc called!\n");
+    return NoTask;
+}
+
+
+TaskControlBlock *DeviceTCB::ActionFunc(Packet *p, void *handle)
+{   DeviceTaskRec *data = (DeviceTaskRec *)handle;
+
+    if (p == NoWork) {
+         if ((p = data->Pending()) == NoWork)
+              return bm.Wait();
+         else {
+              data->SetPending(NoWork);
+              return bm.QueuePacket(p);
+         }
+    }
+    else {
+         data->SetPending(p);
+         if (bm.tracing) bm.Trace(p->Datum());
+         return bm.HoldSelf();
+    }
+}
+
+
+TaskControlBlock *HandlerTCB::ActionFunc(Packet *p, void *handle)
+{   HandlerTaskRec *data = (HandlerTaskRec *)handle;
+    Packet *work, *devicePacket;
+    int count;
+
+    if (p != NoWork) {
+         if (p->Kind() == WorkPacket)
+              data->WorkInAdd(p);
+         else data->DeviceInAdd(p);
+    }
+    if ((work = data->WorkIn()) == NoWork)
+         return bm.Wait();
+    else {
+         count = work->Datum();
+         if (count > 4) {
+              data->SetWorkIn(work->Link());
+              return bm.QueuePacket(work);
+         }
+         else {
+              if ((devicePacket = data->DeviceIn()) == NoWork)
+                   return bm.Wait();
+              else {
+                   data->SetDeviceIn(devicePacket->Link());
+                   devicePacket->SetDatum(work->Data()[count-1]);
+                   work->SetDatum(count + 1);
+                   return bm.QueuePacket(devicePacket);
+              }
+         }
+    }
+}
+
+
+TaskControlBlock *IdlerTCB::ActionFunc(Packet *p, void *handle)
+/* p is not used here */
+{   IdleTaskRec *data = (IdleTaskRec *)handle;
+
+    p, 0;
+
+    data->SetCount(data->Count() - 1);
+    if (data->Count() == 0)
+         return bm.HoldSelf();
+    else if ((data->Control() & 1) == 0) {
+              data->SetControl(data->Control() / 2);
+              return bm.Release(DeviceA);
+         }
+         else {
+              data->SetControl((data->Control() / 2) ^ 53256);
+              return bm.Release(DeviceB);
+         }
+}
+
+
+TaskControlBlock *WorkerTCB::ActionFunc(Packet *p, void *handle)
+{   WorkerTaskRec *data = (WorkerTaskRec *)handle;
+    Identity dest;
+
+    if (p == NoWork)
+         return bm.Wait();
+    else {
+         dest = (data->Destination() == HandlerA) ? HandlerB : HandlerA;
+         data->SetDestination(dest);
+         p->SetIdent(dest);
+         p->SetDatum(1);
+         for(int i = 0; i < 4; i++) {
+              data->SetCount(data->Count() + 1);
+              if (data->Count() > 26) data->SetCount(1);
+              p->Data()[i] = 'A' + data->Count();
+         }
+         return bm.QueuePacket(p);
+    }
+}
+
+
diff --git a/benchmarks/richards/tasks.h b/benchmarks/richards/tasks.h
new file mode 100644
index 0000000000000000000000000000000000000000..295bde66d51a37b0ff86450173c59c57615dd96e
--- /dev/null
+++ b/benchmarks/richards/tasks.h
@@ -0,0 +1,122 @@
+/* tasks.h - definitions of TaskState, TaskControlBlock and xxxTCB 
+ * The subclasses of TaskControlBlock differ only in their
+ * implementation of the action function 				  */
+
+#ifndef TASKS
+
+#define TASKS
+
+#include "types.h"
+
+/*
+// TaskState
+*/
+
+class TaskState {
+    protected:
+        BOOLEAN packetPending, taskWaiting, taskHolding;
+	
+    public:
+        /* initializing */
+        TaskState() {packetPending = TRUE; taskWaiting = taskHolding = FALSE;}
+	void PacketPending() {packetPending = TRUE; taskHolding = taskWaiting = FALSE;}
+	void Waiting() {packetPending = taskHolding = FALSE; taskWaiting = TRUE;}
+	void Running() {packetPending = taskWaiting = taskHolding = FALSE;}
+	void WaitingWithPacket() {packetPending = taskWaiting = TRUE; taskHolding = FALSE;}
+	/* accessing */
+	BOOLEAN IsPacketPending() {return packetPending;}
+	BOOLEAN IsTaskWaiting() {return taskWaiting;}
+	BOOLEAN IsTaskHolding() {return taskHolding;}
+	void SetTaskHolding(BOOLEAN state) {taskHolding = state;}
+	void SetTaskWaiting(BOOLEAN state) {taskWaiting = state;}
+	/* testing */
+	BOOLEAN IsRunning() {return !packetPending && !taskWaiting && !taskHolding;}
+	BOOLEAN IsTaskHoldingOrWaiting() {return taskHolding || !packetPending && taskWaiting;}
+	BOOLEAN IsWaiting() {return !packetPending && taskWaiting && !taskHolding;}
+	BOOLEAN IsWaitingWithPacket() {return packetPending && taskWaiting && !taskHolding;}
+};
+
+/*
+// TaskControlBlock
+*/
+
+class TaskControlBlock : public TaskState {
+
+    protected:
+        TaskControlBlock *link;
+	Identity ident;
+	int priority;
+	Packet *input;
+	void *handle;
+	
+    public:
+        /* initializing */
+        TaskControlBlock(TaskControlBlock *l, Identity id, int prio,
+                         Packet *initialWork, TaskState *initialState,
+                         void *privateData);
+	/* accessing */
+        Identity Ident() {return ident;}
+        int Priority() {return priority;}
+        TaskControlBlock *Link() {return link;}
+	/* scheduling */
+        TaskControlBlock *AddPacket(Packet *p, TaskControlBlock *old);
+        virtual TaskControlBlock *ActionFunc(Packet *p, void *handle);
+        TaskControlBlock *RunTask();
+};
+
+/*
+// DeviceTCB 
+*/
+
+class DeviceTCB : public TaskControlBlock {
+    public:
+        DeviceTCB(TaskControlBlock *l, Identity id, int prio,
+                  Packet *initialWork, TaskState *initialState,
+                  void *privateData) :
+                 (l, id, prio, initialWork, initialState, privateData){}
+        TaskControlBlock *ActionFunc(Packet *p, void *handle);
+};
+
+
+/*
+// HandlerTCB
+*/
+
+class HandlerTCB : public TaskControlBlock {
+    public:
+        HandlerTCB(TaskControlBlock *l, Identity id, int prio,
+                   Packet *initialWork, TaskState *initialState,
+                   void *privateData) :
+                  (l, id, prio, initialWork, initialState, privateData){}
+        TaskControlBlock *ActionFunc(Packet *p, void *handle);
+};
+
+
+/*
+// IdlerTCB
+*/
+
+class IdlerTCB : public TaskControlBlock {
+    public:
+        IdlerTCB(TaskControlBlock *l, Identity id, int prio,
+                 Packet *initialWork, TaskState *initialState,
+                 void *privateData) :
+                (l, id, prio, initialWork, initialState, privateData){}
+        TaskControlBlock *ActionFunc(Packet *p, void *handle);
+};
+
+
+/*
+// WorkerTCB
+*/
+
+class WorkerTCB : public TaskControlBlock {
+    public:
+        WorkerTCB(TaskControlBlock *l, Identity id, int prio,
+                  Packet *initialWork, TaskState *initialState,
+                  void *privateData) :
+                 (l, id, prio, initialWork, initialState, privateData){}
+        TaskControlBlock *ActionFunc(Packet *p, void *handle);
+};
+
+#endif
diff --git a/benchmarks/richards/types.c b/benchmarks/richards/types.c
new file mode 100644
index 0000000000000000000000000000000000000000..81bc9ef272bd9d1ed19abb520f5671bd601146e8
--- /dev/null
+++ b/benchmarks/richards/types.c
@@ -0,0 +1,28 @@
+/* types.c */
+
+#include "types.h"
+
+/*
+// AddToList - list utility (append elem at end of list, return head)
+*/
+Packet *AddToList(Packet *list, Packet *elem)
+{   Packet *p, *next;
+
+    elem->SetLink(NoWork);
+    if (list != NoWork) {
+         p = list;
+         while((next = p->Link()) != NoWork) p = next;
+         p->SetLink(elem);
+    }
+    else list = elem;
+    return list;
+}
+
+Packet::Packet(Packet *l, Identity id, PacketKind k)
+{
+    link = l;
+    ident = id;
+    kind = k;
+    datum = 1;
+    for(int i = 0; i < 4; i++) data[i] = 0;
+}
diff --git a/benchmarks/richards/types.h b/benchmarks/richards/types.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab9578b329fd44e637fcccc1efd4e6f528ac9c3f
--- /dev/null
+++ b/benchmarks/richards/types.h
@@ -0,0 +1,100 @@
+/* types.h -- basic classes (Packet, {Device,Idle,...}TaskRec)	*/
+
+#include "cbase.h"
+#include "rbase.h"
+
+/*
+// Packet
+*/
+
+class Packet {
+    private:
+        Packet *link;		// next packet in queue
+	Identity ident;		// Idle, Worker, DeviceA, ...
+	PacketKind kind;	// DevicePacket or WorkPacket
+	int datum;
+	char data[4];
+    public:
+        Packet(Packet *l, Identity id, PacketKind k);
+	char *Data() {return data;}
+	void SetData(char d[4]) {for(int i=0; i < 4; i++) data[i] = d[i];}
+        int Datum() {return datum;}
+        void SetDatum(int n) {datum = n;}
+	Identity Ident() {return ident;}
+	void SetIdent(Identity i) {ident = i;}
+	PacketKind Kind() {return kind;}
+	void SetKind(PacketKind k) {kind = k;}
+	Packet *Link() {return link;}
+	void SetLink(Packet *l) {link = l;}
+};
+
+/*
+// AddToList - list utility (append elem at end of list, return head)
+*/
+Packet *AddToList(Packet *list, Packet *elem);
+
+/*
+// DeviceTaskRec
+*/
+
+class DeviceTaskRec {
+    private:
+        Packet *pending;
+    public:
+        DeviceTaskRec() {pending = NoWork;}
+	Packet *Pending() {return pending;}
+	void SetPending(Packet *p) {pending = p;}
+};
+
+
+
+/*
+// IdleTaskRec 
+*/
+
+class IdleTaskRec {
+    private:
+        int control, count;
+    public:
+        IdleTaskRec() {control = 1; count = 10000;}
+        int Control() {return control;}
+        void SetControl(int n) {control = n;}
+        int Count() {return count;}
+        void SetCount(int n) {count = n;}
+};
+
+
+/*
+// HandlerTaskRec
+*/
+
+class HandlerTaskRec {
+    private:
+        Packet *workIn, *deviceIn;
+    public:
+        HandlerTaskRec() {workIn = deviceIn = NoWork;}
+        Packet *WorkIn() {return workIn;}
+        void SetWorkIn(Packet *p) {workIn = p;}
+        Packet *WorkInAdd(Packet *p) {return workIn = AddToList(workIn, p);}
+        Packet *DeviceIn() {return deviceIn;}
+        void SetDeviceIn(Packet *p) {deviceIn = p;}
+        Packet *DeviceInAdd(Packet *p) {return deviceIn = AddToList(deviceIn, p);}
+};
+
+
+/*
+// WorkerTaskRec
+*/
+
+class WorkerTaskRec {
+    private:
+        Identity destination;
+	int count;
+    public:
+        WorkerTaskRec() {destination = HandlerA; count = 0;}
+        int Count() {return count;}
+        void SetCount(int n) {count = n;}
+        Identity Destination() {return destination;}
+        void SetDestination(Identity d) {destination = d;}
+};
+