_enable/_disable

Are calls to _enable/_disable stacked?

If I have an call tree that looks like this

Interrupt:
_disable

FuncB

_enable
return

FuncB
_disable

_enable
return

When will interrupts be enabled again? After the FuncB _enable call?

FuncB actually gets the system time but is coded with _disable and _enable
and I am considering modifying it to use looping instead (i.e., do
value=get_value while get_value != value).

Thanks,

Richard

“Brown, Richard” <brownr@aecl.ca> wrote in message
news:9o4n9e$gsr$1@inn.qnx.com

Are calls to _enable/_disable stacked?

If I have an call tree that looks like this

Interrupt:
_disable

FuncB

_enable
return

FuncB
_disable

_enable
return

When will interrupts be enabled again? After the FuncB _enable call?

FuncB actually gets the system time but is coded with _disable and _enable
and I am considering modifying it to use looping instead (i.e., do
value=get_value while get_value != value).

from sys/inline.h:

extern unsigned disable(void);
extern unsigned enable(void);

#pragma aux disable = “pushfd” “cli” “pop eax” __parm [] __modify [eax];
#pragma aux enable = “pushfd” “sti” “pop eax” __parm [] __modify [eax];

→ no, they are not stacked and cannot be nested. this is not a kernel call
but just a x86 instruction. why it was done so guess better to ask folks who
designed it this way.

if you need some interface that would allow you to disable/enable interrupts
generation in safe way you can implement your own but afaik there’s no
already existing alike kernel service. or it’s undocumented. afaik it was
fixed in nto2 where you can ask kernel (clib ?) to disable or enable
interrupts in safe way.

// wbr

Brown, Richard <brownr@aecl.ca> wrote:

Are calls to _enable/_disable stacked?

No.

Also, you should be aware that if you are using them, that any
kernel call will result in interrupts being enabled. (And, a
goodly part of the library makes kernel calls.)

If I have an call tree that looks like this

Interrupt:
_disable

FuncB

_enable
return

FuncB
_disable

_enable
return

When will interrupts be enabled again? After the FuncB _enable call?

Yes.

FuncB actually gets the system time but is coded with _disable and _enable
and I am considering modifying it to use looping instead (i.e., do
value=get_value while get_value != value).

Probably a better choice.

-David

QNX Training Services
dagibbs@qnx.com

ian zagorskih <ianzag@novosoft-us.com> wrote:

from sys/inline.h:

extern unsigned disable(void);
extern unsigned enable(void);

#pragma aux disable = “pushfd” “cli” “pop eax” __parm [] __modify [eax];
#pragma aux enable = “pushfd” “sti” “pop eax” __parm [] __modify [eax];

→ no, they are not stacked and cannot be nested. this is not a kernel call
but just a x86 instruction. why it was done so guess better to ask folks who
designed it this way.

Actually, you can use these functions together with restore() to have
them nested.

From sys/inline.h:

#pragma aux restore = “push eax” “popfd” __parm [eax] __modify [];

Just do something like this:

unsigned flags = disable();

restore( flags );

Of course, it’s generally not a good idea to disable interrupts for a
long time. Even if you need interrupts disabled almost most of the
time for a while, you can improve overall interrupt latency by finding
places in the code where you can safely insert calls to enable() and
disable().


Wojtek Lerch QNX Software Systems Ltd.

“Wojtek Lerch” <wojtek_l@yahoo.ca> wrote in message
news:9o54pt$pgc$1@nntp.qnx.com

ian zagorskih <> ianzag@novosoft-us.com> > wrote:

from sys/inline.h:


Actually, you can use these functions together with restore() to have
them nested.

From sys/inline.h:

#pragma aux restore = “push eax” “popfd” __parm [eax] __modify
[];

Just do something like this:

unsigned flags = disable();

restore( flags );

assumed that all code both mine and written by someone else was written
according to the rules and no one dosn’t touch IF flag directly. only
enable()/disable() calls.

void third_party_fnc(void) {
disable();
/* … */
enable();
};

void my_fnc(void) {
unsigned old_flags;
/* enter critical section /
old_flags = disable();
/
/
third_party_fnc();
/
at this point, where’s the guarantee that interrupts are still been
disabled ? pure russian rulette… /
/
/
/
The Most Critical Part Is Here… maybe leading to the crash maybe
not… /
/
/
/
“leave critical section” */
restore(old_flags);
};

Of course, it’s generally not a good idea to disable interrupts for a
long time. Even if you need interrupts disabled almost most of the
time for a while, you can improve overall interrupt latency by finding
places in the code where you can safely insert calls to enable() and
disable().

well, agree that this is another question how disabled interrupts can
reflect on the overal system performance.


Wojtek Lerch QNX Software Systems Ltd.

// wbr

Is a general disable needed? That is, could you get by with just masking a
particular interrupt?

“Brown, Richard” wrote:

Are calls to _enable/_disable stacked?

If I have an call tree that looks like this

Interrupt:
_disable

FuncB

_enable
return

FuncB
_disable

_enable
return

When will interrupts be enabled again? After the FuncB _enable call?

FuncB actually gets the system time but is coded with _disable and _enable
and I am considering modifying it to use looping instead (i.e., do
value=get_value while get_value != value).

Thanks,

Richard

Dean Douthat <ddouthat@faac.com> wrote:

Is a general disable needed? That is, could you get by with just masking a
particular interrupt?

I guess it’s a matter of balance. A general disable or enable is just a
single opcode; a call to qnx_hint_mask() sends a message to Proc. If
you just want to disable interrupts for several opcodes, sending two
messages will slow you down a lot

OTOH, if you need to turn off interrupts for a substantial amount of
time, than it usually is important to avoid disabling interrupts that
don’t belong to you. In those cases, you need to disable the interrupt
selectively. Instead of calling qnx_hint_mask() it’s probably better
(and often much less expensive) to tell your hardware not to generate
interrupts. As a by-product, this will make it easier for your driver
to share the interrupt with other drivers.

\

Wojtek Lerch QNX Software Systems Ltd.

The _disable/_enable we are using is around the reading of the timesel so
its a very short time. The reason I asked is because I wanted to use it in
an interrupt handler that also calls _disable/_enable for a short period. I
guess I have three choices modify the legacy code, role a new one that loops
until no difference on consecutive reads or get the time at just before the
_disable in the interrupt code and add a BIG COMMENT.

Thanks to all who responded,

  • Richard

“Wojtek Lerch” <wojtek_l@yahoo.ca> wrote in message
news:9o5h28$3ku$1@nntp.qnx.com

Dean Douthat <> ddouthat@faac.com> > wrote:
Is a general disable needed? That is, could you get by with just
masking a
particular interrupt?

I guess it’s a matter of balance. A general disable or enable is just a
single opcode; a call to qnx_hint_mask() sends a message to Proc. If
you just want to disable interrupts for several opcodes, sending two
messages will slow you down a lot

OTOH, if you need to turn off interrupts for a substantial amount of
time, than it usually is important to avoid disabling interrupts that
don’t belong to you. In those cases, you need to disable the interrupt
selectively. Instead of calling qnx_hint_mask() it’s probably better
(and often much less expensive) to tell your hardware not to generate
interrupts. As a by-product, this will make it easier for your driver
to share the interrupt with other drivers.

\

Wojtek Lerch QNX Software Systems Ltd.

ian zagorskih <ianzag@novosoft-us.com> wrote:

“Wojtek Lerch” <> wojtek_l@yahoo.ca> > wrote in message
news:9o54pt$pgc$> 1@nntp.qnx.com> …

Just do something like this:

unsigned flags = disable();

restore( flags );

assumed that all code both mine and written by someone else was written
according to the rules and no one dosn’t touch IF flag directly. only
enable()/disable() calls.

void third_party_fnc(void) {
disable();
/* … */
enable();
};

void my_fnc(void) {
unsigned old_flags;
/* enter critical section /
old_flags = disable();
/
/
third_party_fnc();
/
at this point, where’s the guarantee that interrupts are still been
disabled ? pure russian rulette… /
/
/
/
The Most Critical Part Is Here… maybe leading to the crash maybe
not… /
/
/
/
“leave critical section” */
restore(old_flags);
};

You should minimize the amount of code that runs with interrupts
disabled. In particular, I don’t think it’s a good idea to disable
interrupts and then call a function that was not designed to run with
interrupts disabled. And things get even worse if it’s a kind of
function that disables interrupts itself – what if there’s code in it
that assumes that interrupts are enabled, and spins in a loop to wait
for an interrupt? :slight_smile:

It’s hard for me to come up with a realistic example of why you would
need to do anything like that. What kind of third-party code are you
talking about?

Personally, I wouldn’t feel comfortable calling a third-party function
with interrupts disabled, even if I knew that that function never
enables interrupts. Instead, I would try to re-arrange my code in such
a way that it would never need to disable interrupts for more than
several opcodes.

Keep in mind that QNX is a realtime OS, and even if your particular
setup does not require hard realtime, disabling interrupts for too long
may break some drivers that were not designed with that kind of a
situation in mind. It’s a situation that normally doesn’t occur under
QNX.

Of course, it’s generally not a good idea to disable interrupts for a
long time. Even if you need interrupts disabled almost most of the
time for a while, you can improve overall interrupt latency by finding
places in the code where you can safely insert calls to enable() and
disable().

well, agree that this is another question how disabled interrupts can
reflect on the overal system performance.

I wasn’t talking about the overall performance. I was talking about the
worst-case interrupt latency.

For instance, how long can you disable interrupts for before you start
getting overruns on the serial port? What about the network card or
other hardware?


Wojtek Lerch QNX Software Systems Ltd.