Reply by James Dow Allen●January 21, 20102010-01-21
On Jan 20, 11:46=A0pm, "Datesfat Chicks" <datesfat.chi...@gmail.com>
wrote:
> > On Fri, 15 Jan 2010 19:52:21 -0500, "Datesfat Chicks"
> > <datesfat.chi...@gmail.com> wrote:
> >> =A0 DI();
> >> =A0 sempahore++;
> >> =A0 EI();
> > The code above will always enable interrupts, even if they
> > were not enabled before the DI was executed.
I almost posted something like the following, but was busy stamping
out flames in another ng. :-)
> This problem is normally very easy to address. =A0It is normal to examine=
the
> interrupt mask and make the decision about whether to enable interrupts
> again based on whether they were enabled originally.
>
> im =3D imask(); //Built-in function supported by the compiler.
> DI();
> semaphore++;
> if (!im)
> =A0 =A0EI();
Nothing to add, except a True Anecdote(tm). Development of a peculiar
system(*) was getting behind schedule due to a very intermittent
bug. I came across the responsible programmer sitting next to a logic
analyzer reading a comic book or something. "Can't do anything until
the analyzer triggers again" was his answer. "Problem occurs only
once every several hours."
I showed him how to research by writing (the equivalent of)
assert(imask() =3D=3D ENABLED);
before the DI(); and thus make the system "fail" several times a
second instead of once every several hours. I'm sure he then
figured out the fix himself.
(* -- IIRC, it was a processor emulating a disk controller,
connected to a disk controller emulating a processor, or
some such. :-)
James Dow Allen
Reply by Nobody●January 21, 20102010-01-21
On Wed, 20 Jan 2010 09:39:39 -0500, Mr.C wrote:
>> DI();
>> sempahore++;
>> EI();
>
> Nobody has mentioned the problem with using the DI/EI pair in code
> segments where interrupts can some times be enabled and other times be
> disabled. The code above will always enable interrupts, even if they
> were not enabled before the DI was executed.
It's not a problem if you only use DI/EI around very small sections of
code so that you know that DI/EI will never nest.
For larger sections of code, you should probably be using mutexes,
semaphores, RCU, or whatever (which may need to use DI/EI in their
implementation).
Reply by Datesfat Chicks●January 20, 20102010-01-20
"Hans-Bernhard Br�ker" <HBBroeker@t-online.de> wrote in message
news:hj841g$ghb$02$1@news.t-online.com...
> Datesfat Chicks wrote:
>> This problem is normally very easy to address. It is normal to examine
>> the interrupt mask and make the decision about whether to enable
>> interrupts again based on whether they were enabled originally.
>
> Easy, yes. But potentially quite wrong, too. You can't implement a
> semaphore using a sequence of operations (store current interrupt mask,
> then disable interrupt) that itself needs to be protected by one to avoid
> untimely outside interference. That's an exercise in pulling yourself out
> of the pond by yanking on your own hair.
>
>> im = imask(); //Built-in function supported by the compiler.
>>
>> DI();
>
> And you'll be SOL if the interrupt mask gets changed by an interrupt
> happening in between those two instructions.
In most software architectures, the scenario you proposed can't occur. The
interrupt mask is typically a part of the PSW or CC register (same animal,
depends on who is doing the naming), and it is normally saved and restored
by the hardware when an interrupt occurs and when the ISR exits. In most
small microcontrollers, the interrupt mask is in the same register as the
carry flag, zero flag, overflow flag, etc., so it has to be restored on exit
from an ISR.
I suppose an enterprising ISR could reach into the stack and modify the
value that will be restored when the interrupt exits, but this is not done
by sane humans.
Generally, can't happen.
Datesfat
Reply by David Brown●January 20, 20102010-01-20
Hans-Bernhard Br�ker wrote:
> Datesfat Chicks wrote:
>> This problem is normally very easy to address. It is normal to
>> examine the interrupt mask and make the decision about whether to
>> enable interrupts again based on whether they were enabled originally.
>
> Easy, yes. But potentially quite wrong, too. You can't implement a
> semaphore using a sequence of operations (store current interrupt mask,
> then disable interrupt) that itself needs to be protected by one to
> avoid untimely outside interference. That's an exercise in pulling
> yourself out of the pond by yanking on your own hair.
>
>> im = imask(); //Built-in function supported by the compiler.
>>
>> DI();
>
> And you'll be SOL if the interrupt mask gets changed by an interrupt
> happening in between those two instructions.
It's an unusual system that will change the interrupt mask during an
interrupt, and not restore it on exit - and the situation can only be an
issue on processors with multiple interrupt levels and no global
interrupt flag (such as the m68k). There might be occasions when this
sequence is dangerous, but it is normally considered safe.
Reply by ●January 20, 20102010-01-20
Datesfat Chicks wrote:
> This problem is normally very easy to address. It is normal to examine
> the interrupt mask and make the decision about whether to enable
> interrupts again based on whether they were enabled originally.
Easy, yes. But potentially quite wrong, too. You can't implement a
semaphore using a sequence of operations (store current interrupt mask,
then disable interrupt) that itself needs to be protected by one to
avoid untimely outside interference. That's an exercise in pulling
yourself out of the pond by yanking on your own hair.
> im = imask(); //Built-in function supported by the compiler.
>
> DI();
And you'll be SOL if the interrupt mask gets changed by an interrupt
happening in between those two instructions.
Reply by Datesfat Chicks●January 20, 20102010-01-20
"Mr. C" <fakeemail@hotmail.com> wrote in message
news:3q4el5l74vhequ0u08tc6kl87tmt3n4ccp@4ax.com...
> On Fri, 15 Jan 2010 19:52:21 -0500, "Datesfat Chicks"
> <datesfat.chicks@gmail.com> wrote:
>
>> DI();
>> sempahore++;
>> EI();
>
> Nobody has mentioned the problem with using the DI/EI pair in code
> segments where interrupts can some times be enabled and other times be
> disabled. The code above will always enable interrupts, even if they
> were not enabled before the DI was executed.
This problem is normally very easy to address. It is normal to examine the
interrupt mask and make the decision about whether to enable interrupts
again based on whether they were enabled originally.
It is of course easy to do in assembly language, but some compilers allow
testing of the interrupt mask as well.
It might go something like this:
BOOLEAN im;
im = imask(); //Built-in function supported by the compiler.
DI();
semaphore++;
if (!im)
EI();
This is a fairly easy problem, and very common.
Did I miss something?
Datesfat
Reply by Mr. C●January 20, 20102010-01-20
On Fri, 15 Jan 2010 19:52:21 -0500, "Datesfat Chicks"
<datesfat.chicks@gmail.com> wrote:
> DI();
> sempahore++;
> EI();
Nobody has mentioned the problem with using the DI/EI pair in code
segments where interrupts can some times be enabled and other times be
disabled. The code above will always enable interrupts, even if they
were not enabled before the DI was executed.
Reply by Boudewijn Dijkstra●January 19, 20102010-01-19
Op Mon, 18 Jan 2010 10:04:56 +0100 schreef Niklas Holsti
<niklas.holsti@tidorum.invalid>:
> Boudewijn Dijkstra wrote:
>> Op Sat, 16 Jan 2010 01:52:21 +0100 schreef Datesfat Chicks
>> <datesfat.chicks@gmail.com>:
>>> One might have available functions or macros to disable or enable
>>> interrupts, so one might write:
>>>
>>> volatile int sempahore;
>>>
>>> DI();
>>> sempahore++;
>>> EI();
>> Imagine how a program with DI/EI all over the place can wreak havoc on
>> your worst-case interrupt latency.
>
> The effect on the worst-case interrupt latency does not depend on the
> number of DI/EI pairs "all over" the program, nor on how often they are
> executed. It depends only on the duration of the DI/EI pair that has the
> most code between the DI and the EI, in terms of the execution time of
> that code.
Right. But every DI/EI pair does increase _average_ interrupt latency,
for all interrupts, so even those that might be really important and
cannot even access that particular piece of shared data.
> But why do you, Boudewijn, criticize Datesfat for mentioning DI/EI, when
> Datesfat's very aim is to *avoid* DI/EI by making the compiler use an
> instruction that is intrinsically atomic?
I merely intended to point out a disadvantage of using DI/EI (which
horribly failed). In fact, in the context of his question, the widely
used DI/EI is very illustrative and it would be unwise to not mention it.
--
Gemaakt met Opera's revolutionaire e-mailprogramma:
http://www.opera.com/mail/
(remove the obvious prefix to reply by mail)
Reply by Boudewijn Dijkstra●January 19, 20102010-01-19
Op Mon, 18 Jan 2010 23:47:20 +0100 schreef D Yuniskis
<not.going.to.be@seen.com>:
> Datesfat Chicks wrote:
>
> [attributions elided]
>
>>>> Don't do that then. Use an OS service that ensures exclusive data
>>>> ownership, like a messaging interface.
>
> Even a messaging service has, at some level, a need for atomic
> operations. Putting it under a bushel doesn't cause it to
> cease to exist.
Absolutely right. But consider the differences between a solution written
and maintained by specialized people, and one by people with much less
experience.
>> The systems that I work on tend to have about 32K of FLASH memory and
>> 2K or so of RAM. There is no formal operating system that provides
>> such services.
That sounds as if there was no decision process for hardware & tools. I
would have expected something along the lines of: "it was decided to keep
hardware cost low and not use an OS."
>> The logic is typically just to execute a loop at a constant rate, with
>> interrupts happening at the same time based on timer compares or
>> overflows, received SCI characters, etc.
>>
>>> Such OS services tend to have longer interrupt-disabled regions than a
>>> simple "semaphore++" and thus more effect on the worst-case latency.
Since in your case an OS means richer hardware, then you might actually
reduce latency by having a faster processor. ;)
>>> And then we have the bare-board systems that use just background +
>>> interrupts with no OS to speak of.
>> The "no OS to speak of" describes the type of system I work on.
>>
>>> Finally, Datesfat's question and proposal are also applicable to the
>>> internals of OS services, which also could benefit from using
>>> intrinsically atomic instructions instead of DI/EI.
And some OSes do utilize these. Not by depending on the compiler, but
with plain assembler code.
--
Gemaakt met Opera's revolutionaire e-mailprogramma:
http://www.opera.com/mail/
(remove the obvious prefix to reply by mail)
Reply by Datesfat Chicks●January 18, 20102010-01-18
"D Yuniskis" <not.going.to.be@seen.com> wrote in message
news:hj2nrj$vra$1@speranza.aioe.org...
>
> Well, that's not entirely true, either. One can imagine
> having a piece of code that manipulates a boolean. And,
> some other piece of code EXECUTING IN THE SAME THREAD
> wants to check to see if that boolean is set and, regardless,
> set it thereafter.
You are correct. I didn't think of that scenario.
Datesfat