Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!ames!eos!shelby!lindy!news
From: BR.SJE@forsythe.stanford.edu (Steve Eastman)
Newsgroups: comp.lang.modula2
Subject: TRANSFER(p1,p2) In a Clock Tick ISR
Message-ID: <4887@lindy.Stanford.EDU>
Date: 25 Sep 89 20:06:51 GMT
Sender: news@lindy.Stanford.EDU (News Service)
Distribution: na
Lines: 61

Remember, in M2 things of type PROCESS must function in a
certain way, else the thing you've got isn't M2.  If the
thing you've got isn't M2, you won't be able to use any one
else's modules in a program of your own.

Hereafter I will call Modula-2 processes "threads".  This
term may help reduce the confusion that I think exists for
UNIX programmers that use M2.  Usually a thing called a
"process" has its own address space and communicates with
other processes in a way that coordinates both processes at
the time of the communication--when data transfer takes
place.  Threads on the other hand are low overhead, low
level, things.  They have nothing to do with processes
(except they me be used as part of the implementation of
processes).

In the definition of Modula-2 a thread (or as Wirth calls
them "process") must be sequential.  That is, they must not
be mutually preemptive.  The exception is that an interrupt
service routines (ISR) thread may preempt another thread of
lower priority.

A monitor (priority module) must protect its shared
variables against alteration during its execution.  When a
monitor contains an ISR a very interesting state of affairs
develops.

All ISRs have at least one shared variable which they
alter.  This variable is passed to it when an interrupt
occurs--the thing pointed to by the pointer that is the
second parameter to the IOTRANSFER procedure--the
interrupted thread.  The way in which the variable is
altered is that it is changed to the "not running" state.
When the ISR is done it will change the state of the
interrupted thread back to "running" via IOTRANSFER.  It can
only make this second change with impunity because it knows
the thread was in the "running" state in the beginning and
has protected it from alteration through out its execution.

Therefore, all ISRs must execute in such a way that the
state of the interrupted thread is not altered in any way,
then execute the interrupted thread.  The only way to make
sure of this is to (A) not transfer to any other thread, or
(B) transfer only to threads in the same priority module as
the ISR such that the priority level never is lowered.  The
reason for this is that if the thread being transferred to
is of a lower priority, then the owner of the interrupted
thread could come back into control and change the state of
the interrupted thread to "not running" or destroy it
altogether.  Then, when the ISR comes back into control, the
ISR would, believing the thread to be runnable as a matter
of course, IOTRANSFER to it.  Thus, it would have
transferred to and made "running" a thread which its owner
believes to be "blocked" or nonexistent.  This conflict as
to the state of an interrupted process probably will have
tragic consequences on the execution of a program.

Until I discovered the above described tangle of threads, my
multi-threaded system had some very weird bugs: threads
running when they were "blocked", programs running away,
etc..