Subject:
|
Re: Sharing variables and using expressions (was Re: NQC 2.0 and some math questions
|
Newsgroups:
|
lugnet.robotics.rcx.nqc
|
Date:
|
Wed, 20 Oct 1999 00:56:40 GMT
|
Viewed:
|
2526 times
|
| |
| |
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 run out if every expression must first
evaluate into a temp, then assign to the destination.
I considered adding a #pragma to control this, but then figured that
anyone savvy enough to use the #pragma would also be savvy enough to work
around the problem another way.
I know this isn't ideal, but without a stack its really difficult to do
things "by the book".
This does warrant additional discussion in the manual, so I will add it
when I get some free time.
Dave Baum
In article <FJv8wM.99v@lugnet.com>, "Robert Munafo"
<munafo@gcctechNO.SPAMcom> wrote:
> 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
--
reply to: dbaum at enteract dot com
|
|
Message has 2 Replies:
Message is in Reply To:
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
|
|
|
|