To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.robotics.rcx.nqcOpen lugnet.robotics.rcx.nqc in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / RCX / NQC / 202
201  |  203
Subject: 
Sharing variables and using expressions (was Re: NQC 2.0 and some math questions
Newsgroups: 
lugnet.robotics.rcx.nqc
Date: 
Tue, 19 Oct 1999 20:00:22 GMT
Viewed: 
2256 times
  
I have discovered a somewhat non-intuitive feature of NQC (in my version, at
least, which is pre-2.0)

The statement:

  var = (20 * var) / 21;

gets compiled into the following:

  MUL var, 20   ; var = var * 20
  DIV var, 21   ; var = var / 21

rather than the more standard:

  SET tmp, var  ; tmp = var
  MUL tmp, 20   ; tmp = tmp * 20
  DIV tmp, 21   ; tmp = tmp / 21
  SET var, tmp  ; var = tmp

The reason this matters is that the value of "var" might be read by another
task. The traditional rules for inter-process communication via shared
variables allow simple (non-mutex) variable sharing as long as there is at most
one task that writes to the variable. (If there is more than one writing task,
semaphores must be used).

However, this simple rule relies on some more fundamental (and implied) rules
known mainly to compiler writers, namely:

  - each occurrance of a variable in a RHS (right-hand-side) context generates
at most one (atomic) read access, and

  - each occurrance of a variable in an LHS (left-hand-side) context generates
at most one (atomic) write access.

Usually implementation of these rules is easy because there is a stack, some
registers, and/or some other type of storage that is saved and restored on each
task context switch. NQC failure to comply is understandable in view of the
restrictions of the firmware.

The good news is that programmers using NQC can avoid this problem (if they
wish) by explicitly breaking their expressions up into pieces that compile into
a single firmware opcode, thereby preventing NQC from second-guessing. Such a
programmer would explicitly rewrite my example as:

  tmp = var;
  tmp *= 20;
  tmp /= 21;
  var = tmp;

There are additional inter-task issues with temp variables, which I assume NQC
avoids. For example, a seperate pool of temp variables must be allocated for
each task, lest two tasks interfere with one another by sharing the same temp
variable. If you are concerned about such issues, you could rewrite all of your
expressions as single operations and allocate all your temp variables
explicitly. Of course, you need to follow the same rules, and make sure to give
each task its own set of temp variables.

In lugnet.robotics.rcx.nqc, Dave Baum writes:
In article <37f16547.6612368@lugnet.com>, marcob@equalis.it wrote:

x = y % z

is equivalent to (where w is an temporary integer):

w = y / z;
x = y - z * w;


That's exaclty what I was thinking of doing.  Originally, the compiler had
no way of allocating temp variables which is why code for % couldn't be
emitted.  The temp allocator is now pretty good, so I could emit the above
sequence, but it just didn't occur to me until a few days ago.

There is one subtle problem.  The operations above won't happen
atomically, so there are some concurrency issues.  To be completely safe,
I'd have to latch both y and z into temps as well.  Without this, some
truly weird stuff can happen.  For example, lets say that intially y is a
multiple of z, and then you decrement y in-between the computation of w
and x.  The result will be that x is negative.  This is a result that is
inconsistient with the decrement happening either before or after the
entire mod calculation.

My personal feeling on this, however, is that if you're running around
changing y amd z in one task while calculating with them in another,
you're just asking for trouble.

- Robert Munafo                           http://www.mrob.com/
  LEGO: TC+++(8480) SW++ #+ S-- LS++ Hsp M+ A@ LM++ YB64m IC13



Message has 1 Reply:
  Re: Sharing variables and using expressions (was Re: NQC 2.0 and some math questions
 
The optimization was intentional (and quite a lot of work, actually). I know it breaks with multiple tasks, but I was more concerned with keeping the variable pool from being cluttered with temporaries. With only 32 vars to use, its quite easy to (...) (25 years ago, 20-Oct-99, to lugnet.robotics.rcx.nqc)

Message is in Reply To:
  Re: NQC 2.0 and some math questions
 
(...) That's exaclty what I was thinking of doing. Originally, the compiler had no way of allocating temp variables which is why code for % couldn't be emitted. The temp allocator is now pretty good, so I could emit the above sequence, but it just (...) (25 years ago, 30-Sep-99, to lugnet.robotics.rcx.nqc)

16 Messages in This Thread:




Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact

This Message and its Replies on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR