RE: ServiceLoop() Revisited

From: Russell Vreeland <vreeland_at_.....>
Date: Thu Apr 21 2005 - 16:20:16 PDT
Per, I'm out of time today, but a quick comment on the first item:  my
thinking reg'd SL() and determinism is colored by the fact that we never,
ever use the input ready protocol. The "ReceiveReady"s of all my
SceMiMessageInPorts in hw are always wired to 1'b1.

So when you include
   3) The HDL side stops the cclocks whenever it is requesting a
      message (input ports) or wants to send one (output port).
and...
   6) Now assume the HDL side for whatever reason is requesting a
      message on input I2.  According to (3) the cclocks are now
      stopped and the processing required to generate the output
      message is frozen in time.

as part of the problem you're trying to explain, I have to stop right there
due to unfamiliarity on my part, because my HDL side never requests a
message from C (unless indirectly by sending a message via an output port).

This difference probably affects the way we view and use SL() and the rules
we have for insuring deterministic operation. I will say that my thinking
task reg'd all this becomes much simpler than yours. :)


---------------------------------------
---    Russ Vreeland (949)926-6143  ---
---    vreeland@broadcom.com        ---
---    Senior Principal Engineer    ---
---    Broadcom Corporation         ---
---------------------------------------



> -----Original Message-----
> From: owner-itc@eda.org [mailto:owner-itc@eda.org] On Behalf 
> Of Per Bojsen
> Sent: Thursday, April 21, 2005 2:04 PM
> To: vreeland@broadcom.com; 'Per Bojsen'; itc@eda.org
> Subject: Re: ServiceLoop() Revisited
> 
> 
> >I.e., my g() function is:
> >// "g" function for Service Loop, used to cause blocking until a 
> >message is received int sLoophandler( void * context, bool 
> pending ) {
> >  return pending ? 0 : 1;
> >}
> >
> >which I believe is the one defined in the spec for this purpose.
> >
> >It would have been great if this were the default mode, rather than 
> >polling, as it would lead to more serendipitous 
> deterministic operation 
> >outcomes by users.
> 
> I'm wondering why you think so?  I've always thought that the 
> easiest way to achieve fully deterministic and repeatable 
> behavior including across platforms is to use `sane' clock 
> control coupled with the default behavior of ServiceLoop().  
> `Sane' clock control is where the user stops the cclocks 
> whenever he wants to transfer a message.  On input ports this 
> means deasserting ReadyForCclock at the same time as 
> asserting ReceiveReady and reasserting ReadyForCclock when 
> ReceiveReady is deasserted upon receiving the next input 
> message.  On output ports the same applies but for 
> TransmitReady.  At Zaiq we have achieved excellent 
> performance and completely repeatable and deterministic tests 
> with this approach.  I'm stressing the performance issue here 
> as some people might think that applying this kind of clock 
> control mechanism will impact performance too much.
> 
> The problem with making the blocking use model the default is 
> that it is possible to deadlock the system.  Consider the 
> following scenario:
> 
>    1) There are two input ports I1 and I2 and an output port O1.
> 
>    2) The HDL side is constructed such that a message sent to the
>       input port I1 directly or indirectly eventually causes a message
>       to be sent to the output port.  The processing requires cclocks
>       to go by.
> 
>    3) The HDL side stops the cclocks whenever it is requesting a
>       message (input ports) or wants to send one (output port).
> 
>    4) The C side has three threads: two threads T1 and T2 that does
>       Send() (T1 to I1, T2 to I2) and a thread TS that executes
>       ServiceLoop().
> 
>    5) Assume a message has been sent to I1 and the HDL side has not
>       yet reached the point where it generates a message for the
>       output port.
> 
>    6) Now assume the HDL side for whatever reason is requesting a
>       message on input I2.  According to (3) the cclocks are now
>       stopped and the processing required to generate the output
>       message is frozen in time.
> 
>    7) Assume a cooperatively scheduled threading model such as
>       SystemC's on the software side.
> 
>    8) On the software side, now assume the ServiceLoop() thread gets
>       scheduled to run before T2.  ServiceLoop() is entered, no
>       input messages are currently queued, so the hardware side
>       does not get to restart the cclocks.  ServiceLoop() then
>       enters the loop looking for pending output messages, but
>       since the cclocks are stopped the next output message will
>       not be created.  Hence, the g() function will cause 
> ServiceLoop()
>       to block forever.  The T2 thread will not get to run since
>       threads are not preempted in the cooperatively scheduled
>       threading model.
> 
> Phew!  That was more complicated to explain than I thought.  
> First, let me clarify: I'm not saying your particular 
> application suffers from this potential deadlock.  The let me 
> ask if you agree that the above scenario actually does lead 
> to a deadlock.  I think the above example does not represent 
> a far-fetched use scenario at all.  I.e., it is common to use 
> multiple threads, and have output ports that send messages in 
> response to input port messages.
> 
> So if the default mode of ServiceLoop() was the blocking 
> mode, many users might be bitten by this deadlock.
> 
> The current default behavior avoids the deadlock because it 
> processes all currently pending messages and then exits, 
> allowing another pass through the input message queue(s) 
> again.  Of course, the user could still deadlock their 
> application if they did not properly allow for thread 
> switching.  The point is that with the blocking model it is 
> possible to deadlock even with thread switching 
> 
> The simplest default behavior of ServiceLoop() in my mind 
> would be a `fire-and-forget' mode where you call it once and 
> it just goes until your test is done.  Unfortunately, there 
> is no way for the
> ServiceLoop() to know that the test is finished, so the next 
> best thing is the current default behavior: process 
> everything that's pending and return to the user.  
> 
> >I thought it was in your original email: "Now, assume an 
> implementation 
> >which only transfers input messages in ServiceLoop()". Did you mean 
> >"only transfers input messages in SL() <as opposed to 
> immediately when 
> >Send() is
> >called>  -OR- "ONLY transfers input messages in SL(), 
> nothing else -- 
> >called> such
> >as waiting for output messages"?
> 
> Oh, sorry, yes, I meant the former, i.e., input message are 
> only transferred by ServiceLoop() not Send(), or in other 
> words, what Duaine called buffered.
> 
> >I'm not sure we solved the ambiguity. We could write the 
> spec that way, 
> >but I'm not sure we were in consensus on this?
> 
> Oh, I didn't hear you protest when Duaine was suggesting to 
> add a note to the spec so I assumed you were OK with that :-)
> 
> >There is an advantage in
> >simplicity if input messages are non-buffered and occur in 
> series (on 
> >the HDL side).
> 
> True, and I'm assuming you also want to require a strict 
> ordering such that
> Send() to port A followed by Send() to port B comes out in 
> that order on the hardware side as well?  I think this is 
> where it gets sticky as each vendor obviously wants as much 
> freedom as possible to implement the transport.  And as you 
> pointed out, series reception does not really protect you much.
> 
> >In our spare time :) ???
> 
> Yep!
> 
> -- 
> Per Bojsen                                Email: <bojsen@zaiqtech.com>
> Zaiq Technologies, Inc.                   WWW:   
> http://www.zaiqtech.com
> 78 Dragon Ct.                             Tel:   781 721 8229
> Woburn, MA 01801                          Fax:   781 932 7488
> 
Received on Thu Apr 21 16:20:41 2005

This archive was generated by hypermail 2.1.8 : Thu Apr 21 2005 - 16:21:24 PDT