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&#4294967295;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&#4294967295;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