On Sun, Mar 2, 2014, at 02:29 PM, Michael Haberler wrote:
> 
> Am 02.03.2014 um 15:21 schrieb John Kasunich <jmkasun...@fastmail.fm>:
> 
> 
> > There are several variables that are used to communicate
> > between the two parts.  The faster part was written assuming
> > that those variables would not change during any single
> > execution of the code.  Allowing the slower thread to have a
> > higher priority (and thus to interrupt) the faster thread would
> > break that assumption. 
> 
> 
> I have read up on the data flow in stepgen.c and I found the following for 
> normal (i.e. not disabled, and setup disregarded):
> 
> make_pulses reads:
>       stepgen->accum 
>       stepgen->target_addval
>       stepgen->deltalim
>       
> make_pulses writes:
>       stepgen->accum
> 
> update_freq reads:
>       stepgen->accum 
> 
> update_freq writes:
>       stepgen->target_addval
>       stepgen->deltalim
> 
> Now stepgen->accum can be taken out of the picture for considering 
> transactions since that is the single scalar value read back by update_freq 
> (it could be replaced by an atomic 64bit fetch which is supported on all 
> architectures, but that is a side issue).
> 
> The interesting case are the two values which update_freq writes. I assume 
> you are referring to those?

I wasn't referring to anything that specific, I haven't looked at
that code in years and could not tell you what the variable are
or what they are used for (although now that you have listed 
them I'm starting to remember some parts of it).  I would clearly
have to study the code to refresh my memory.

But that is a detail.  I was simply stating that an assumption
was made when the code was written.  If we are planning to
change that assumption now, then every piece of code that
relied on the assumption needs to be identified, checked, and
if neccessary revised.

There are other reasons for retaining rate-monotonic scheduling,
such as the latency impact of allowing a slow servo thread to
block a faster base thread.  I strongly believe that we should
preserve rate-monotonic scheduling for multiple reasons.

> 
> I can see how scheduling comes in here the way this is coded, but I think 
> this is basically a complicated way to achieve an atomic message transmit 
> from update_freq to make_pulses.

How is it complicated?  There is no messaging system,
there is simply rate-monotonic scheduling, and code 
written to work properly in that environment.

> Assume there were a way to send records from update_freq to make_pulses in an 
> atomic fashion, and such an update record contains stepgen->target_addval, 
> and stepgen->deltalim. make_pulses would check if a new record is available; 
> if so, consume it and base the current calculation on the values contained 
> therein. If not, it would use the values recorded from the previous update 
> message, and proceed alike.
> 
> In that case it would become meaningless what threads do in relation to each 
> other, since the result cannot be influenced by that.
> 
> Note "Assume there were a way" is already present in entirety, it is Pavel's 
> ringbuffer code which does exactly that, see below.
> 
> This is my hypothesis: 
> 
>    we can replace thread interaction of compound values like above by 
> ringbuffer communications, and can forget about this scheduling rate and 
> priority business altogether.
> 
> Can anybody falsify this hypothesis, and how? Really interested.

Atomic transfers from faster threads to slower ones is 
only one result of rate monotonic scheduling.  There are
others that are far more important.

I've never seen real-time control code that didn't use rate-
monotonic scheduling.  For example, at my current employer
we are working on a motor drive.  There is a 33uS thread
that does the core current loop, a 500uS thread that does
protection and speed loop, a 2.5mS thread for application
specific outer loops, and background code for non-time-
critical stuff.  

The background can be interrupted by any of the other
threads.  The 2.5mS thread can be interrupted by the
500uS and 33uS, and the 500uS can be interrupted by
the 33uS.  That is absolutely neccessary if the the
time critical stuff in the faster threads is to be completed
when it should be.

I acknowledge that when you start running each thread
on a different core, or CPU, or a completely different
processor or device, then things get more complicated.

In 2003-2005, we "solved" that problem by putting all
realtime threads on the same CPU/core, so that the
rate-monotonic assumptions would hold true.  Maybe
in 2014 that solution isn't good enough anymore.

But to the extent that threads _might_ be on the same
core, fast threads damn well better have priority over
slow ones.



> - Michael
> 
> the ringbuffer code is here: 
> http://git.linuxcnc.org/gitweb?p=linuxcnc.git;a=blob;f=src/rtapi/ring.h;h=874c7793fe2d00c1c8002f2a04b1c742e785c02d;hb=refs/heads/unified-build-candidate-3#l266
> 
> The required operations are:
> 
> record_write_begin() - allocate space for a message in the rb but do not 
> commit the write yet
> record_write_end() - commit the write operation
> record_next_size()  - check data available and operate on same
> record_shift()   - consume the record.

I didn't spend a lot of time studying that code.  But a few things
made me cringe.

>From the code:

/* record_write_begin():
 * begin a zero-copy write operation for at least sz bytes. This povides a 
buffer
 * to write to within free ringbuffer space.
 * return 0 if there is sufficient space for the requested size 
 * return EAGAIN if there is currently insufficient space
 * return ERANGE if the write size exceeds the ringbuffer size.

So, tell me what update_freq() should do if the function returns
anything other than zero?  It seems to me that you MUST be
absolutely sure that it will always return zero.  And if you are
sure (because you allocated the appropriate size buffer, etc,),
then the tests are simply wasting time - after all, you made
sure they would never fail.

I have no doubt that Pavel's ringbuffer code is well thought
out and serves the general purpose atomic transfer problem
well.  But it is overkill (and bloated) if the system has been
properly designed to ensure that you never have allocation
problems.  If you do have allocation problems, then you are
screwed in a real-time control application.

-- 
  John Kasunich
  jmkasun...@fastmail.fm

------------------------------------------------------------------------------
Subversion Kills Productivity. Get off Subversion & Make the Move to Perforce.
With Perforce, you get hassle-free workflows. Merge that actually works. 
Faster operations. Version large binaries.  Built-in WAN optimization and the
freedom to use Git, Perforce or both. Make the move to Perforce.
http://pubads.g.doubleclick.net/gampad/clk?id=122218951&iu=/4140/ostg.clktrk
_______________________________________________
Emc-developers mailing list
Emc-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-developers

Reply via email to