I am trying to get a grasp on this myself! I have programmed so much occam over the years that I was surprised when I rediscovered that it was possible to queue tasks, and that Ada in fact queued tasks on the entries. My "little green" Ada book by Burns from the eighties was clear on this. And now I learn that this is also so for Go.
A buffered channel has an associated message queue, but it does not need to have any associated process queue in each channel. In occam all channels are unidirectional one-to-one (since many-to-one are arranged as an array of one-to-one channels), and it does not allow output in ALT/select. So, when the only possible first process arrives on the channel, this is noted "in the channel" and not in any ready queue, and the process is descheduled and essentially forgotten. When the second comes on the channel, data is moved across and the first process is moved into the scheduler's ready queue. There may be one queue for each priority. But there is no process queue for each channel. The channel drives scheduling.
Observe that any CSP-type ALT/select scheduling will only take one cause, not several as in the Posix "select".
Now, if there is a many-to-one relationship in a single channel (and not an array of channels as in occam) (like I believe is so for Ada, Go and the JCSP library), when the first comes on the sender side, the scheme above would go. Store it in the channel and forget. But the second (an third etc..) on the sender side we need to deschedule but not forget. So, there has to be a queue in each channel listing which process that gets to send.
I am not sure how difficult it is to do required timing analysis in the second solution. That queue looks to me rather clean(?) But it has problems:
How should a receiver be able to "close the door" to the others during a session with one of them, if all the others are queued up? There has to be some kind of mask or filter for the channel scheduler to set those aside, so I guess it's possible. Basically a channel does not say "I want to listen to anyone who's at the sender side". It would say (occam) that it wants to communicate "on this channel", even on "myChan[i]". Hoare, in his original paper (1978 I think) made channel communication go between named processes, but later (1985, after the occam design that he also was involved with) made communication on named channels. A server in this case does not have to only engage in stateless communication with clients, since it is able to let a session go on with one, and shut the others out. This is a very powerful paradigm.
As a consequence we also have the problem of "fairness". Who controls fairness? In occam, the server could do it, by f.ex listen on the next indexed channel in an array of channels (modulo dimension of array), when one was finished with one. If this was not fair enough (to the clients), then it was up to the server to code it differently. With a queue with processes on the channel, the scheduler has to decide about fairness, or just don't care. Anyway, this important trait seems to be out of my hand, as aprogrammer?
Then there is buffering. If we have a buffered channel, there is no need for a process queue because there is no blocking - until the channel gets full, when the discussion above is again relevant. A buffered channel has the same problem with the queue, since there is no way to reason about how often the channel gets full. Never, some times, often? Safety critical system analysts will only accept good answers to this.
Then there is preemptive scheduling or not. The transputer (an occam virtual machine, so to say) scheduler let the channel do the scheduling, always. Everthing was connected to a channel: its four i/o links, its interrupt pin and even timers. The Ada Ravescar profile removes quite some nice things about Ada, but requires preemptive scheduling. But it also states that "However a similar profile could be defined that specified non-preemptive execution". I understand the latter, but not the first..
Now I haven't really touched Go much here. Will my ponderings also go for Go, or are there important differences or nuances? Since Go channels are based on CSP I assume that much of this is relevant? Are there any errors in my reasoning?
Øyvind Teig
Trondheim, Norway
kl. 07:06:21 UTC+2 mandag 25. juni 2012 skrev Ian Lance Taylor følgende:
Proving determinism is an important part of getting software certified for things like avionics. Features like garbage collection essentially make Go a nonstarter for these types of applications.
Øyvind Teig writes:
> Now, if there is a many-to-one relationship in a single channel (and not an
> array of channels as in occam) (like I believe is so for Ada, Go and the
> JCSP library), when the first comes on the sender side, the scheme above
> would go. Store it in the channel and forget. But the second (an third
> etc..) on the sender side we need to deschedule but not forget. So, there
> has to be a queue in each channel listing which process that gets to send.
I would describe Go channels as many-to-many. A channel can have many
goroutines queued to send, and the same channel could later have many
goroutines queued to receive.
> I am not sure how difficult it is to do required timing analysis in the
> second solution. That queue looks to me rather clean(?) But it has problems:
I don't know what you mean by "required timing analysis."
> How should a receiver be able to "close the door" to the others during a
> session with one of them, if all the others are queued up? There has to be
> some kind of mask or filter for the channel scheduler to set those aside,
> so I guess it's possible. Basically a channel does not say "I want to
> listen to *anyone* who's at the sender side". It would say (occam) that it
> wants to communicate "on this channel", even on "myChan[i]". Hoare, in his
> original paper (1978 I think) made channel communication go between named
> processes, but later (1985, after the occam design that he also was
> involved with) made communication on named channels. A server in this case
> does not have to only engage in stateless communication with clients, since
> it is able to let a session go on with one, and shut the others out. This
> is a very powerful paradigm.
In Go a receiver on a channel can not take control of the channel to
prevent other goroutines from receiving values on it. If you need to do
something like that in Go, you just create a new channel for the
specific communication.
> As a consequence we also have the problem of "fairness". Who controls
> fairness? In occam, the server could do it, by f.ex listen on the *next*indexed channel in an array of channels (modulo dimension of array), when
> one was finished with one. If this was not fair enough (to the clients),
> then it was up to the server to code it differently. With a queue with
> processes on the channel, the *scheduler* has to decide about fairness, or
> just don't care. Anyway, this important trait seems to be out of my hand,
> as aprogrammer?
In Go a goroutine dealing with multiple channels will use a select
statement, and select will choose among the channels pseudo-randomly.
That is where the Go runtime provides "fairness."
> Then there is preemptive scheduling or not. The transputer (an occam
> virtual machine, so to say) scheduler let the channel do the scheduling,
> always. Everthing was connected to a channel: its four i/o links, its
> interrupt pin and even timers. The Ada Ravescar profile removes quite some
> nice things about Ada, but requires preemptive scheduling. But it also
> states that "However a similar profile could be defined that specified
> non-preemptive execution". I understand the latter, but not the first..
The current Go scheduler is not preemptive, but channel I/O is not the
only place where goroutines can be scheduled. They can also be
scheduled at most system calls--i.e., most file or network I/O.
> Now I haven't really touched Go much here. Will my ponderings also go for
> Go, or are there important differences or nuances? Since Go channels are
> based on CSP I assume that much of this is relevant? Are there any errors
> in my reasoning?
Go channels are based on CSP, but they are not the same as CSP, or
Occam.
Ian
A realtime system does not require all software to be realtime. As you indicated, realtime means determinism. That you can guarantee an event will be processed in a given interval of time from when the event fired (not when you noticed it). There can be non-realtime software on the device as long as the realtime events take priority and the maximum length of time it takes for the non-realtime task to be interrupted is accounted for. Generally speaking, any possibility of general memory allocation or garbage collection in a code path would make that particular path non-realtime. Realtime code pre-allocates memory before it enters realtime mode.The article is no longer on CNET so I can't see where they said Java was used, but I can assure you 100% that the OS on the Spirit was an older version of VxWorks (they decide the software platform pretty much at the beginning of the project and don't do upgrades). The realtime code was almost certainly written in C, though compiled with a C++ compiler. I can believe there was java code there, but I do not believe it was handling the realtime events.Go could be used in a similar way, for the non-realtime aspects. This does leave out avionics and other certified sections.
-Paul
A realtime system does not require all software to be realtime. As you indicated, realtime means determinism. That you can guarantee an event will be processed in a given interval of time from when the event fired (not when you noticed it). There can be non-realtime software on the device as long as the realtime events take priority and the maximum length of time it takes for the non-realtime task to be interrupted is accounted for. Generally speaking, any possibility of general memory allocation or garbage collection in a code path would make that particular path non-realtime. Realtime code pre-allocates memory before it enters realtime mode.The article is no longer on CNET so I can't see where they said Java was used, but I can assure you 100% that the OS on the Spirit was an older version of VxWorks (they decide the software platform pretty much at the beginning of the project and don't do upgrades). The realtime code was almost certainly written in C, though compiled with a C++ compiler. I can believe there was java code there, but I do not believe it was handling the realtime events.
There was also hardware java processor with hardware memory management with zero time delay for garbage collection.
i knew some Java cpus, but do not know any hardware GCs so any references will be helpful.
May be you are referring to this series of articles http://www.ibm.com/developerworks/java/library/j-rtj1/