EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Making a function safe for use in an ISR

Started by joshc January 24, 2007
So during an interview for an embedded software position, I was asked
to write any function I wanted in C. I chose an iterative factorial
function like this:

int iterative_factorial(int i) {
  int f;
  f = 1;

  while (i != 0) {
    f = i * f;
    i--;
  }
  return(f);
}

I was then asked what I would have to worry about or fix to make the
function safe to use in an ISR. I really could not think of anything
wrong with this function as it seems reentrant and I don't see any
concurrency issues. Can anyone think of anything that might make this
function unsafe to use in an ISR?

Thanks,

Josh

joshc wrote:

> So during an interview for an embedded software position, I was asked > to write any function I wanted in C.
Such a stupid request should've been answered with: void any_function (void) { } ...then let them base any further questions on that function... -- Mark McDougall, Engineer Virtual Logic Pty Ltd, <http://www.vl.com.au> 21-25 King St, Rockdale, 2216 Ph: +612-9599-3255 Fax: +612-9599-3266
joshc wrote:
> So during an interview for an embedded software position, I was asked > to write any function I wanted in C. I chose an iterative factorial > function like this: > > I was then asked what I would have to worry about or fix to make the > function safe to use in an ISR. I really could not think of anything
Exceptions of all types are usually handled with a totally separate stack from mainline code. It's not expected that vast amounts of data will be saved on the stack inside an ISR - you want to get in quickly, and get out quickly. Also, in many architectures, entering an ISR disables interrupts automatically. Often, to simplify concurrency analysis, firmware will intentionally not re-enable interrupts inside an ISR. (It can be really hard to analyze nested interrupts and debug any problems you encounter). Calling this function under those circumstances could send the processor off for a long, long time and impact realtime foreground tasks. Therefore I would not use an iterative function inside an ISR unless the entry conditions were constrained to prevent stack blowout, and the latency issues were very well understood.
On Jan 24, 11:12 pm, "larwe" <zwsdot...@gmail.com> wrote:
> joshc wrote: > > So during an interview for an embedded software position, I was asked > > to write any function I wanted in C. I chose an iterative factorial > > function like this: > > > I was then asked what I would have to worry about or fix to make the > > function safe to use in an ISR. I really could not think of anythingExceptions of all types are usually handled with a totally separate > stack from mainline code. It's not expected that vast amounts of data > will be saved on the stack inside an ISR - you want to get in quickly, > and get out quickly. >
...
> > Therefore I would not use an iterative function inside an ISR unless > the entry conditions were constrained to prevent stack blowout, and the > latency issues were very well understood.
Are you confusing iterative and recursive when you talk of stack blowout? I don't see how entry conditions would affect the stack usage of this _iterative_ function. Thanks for the other points though.
joshc <josh.curtz@gmail.com> wrote:
> So during an interview for an embedded software position, I was asked > to write any function I wanted in C. I chose an iterative factorial > function like this: > > int iterative_factorial(int i) { > int f; > f = 1; > > while (i != 0) { > f = i * f; > i--; > } > return(f); > } > > I was then asked what I would have to worry about or fix to make the > function safe to use in an ISR. I really could not think of anything > wrong with this function as it seems reentrant and I don't see any > concurrency issues.
You're thinking like a high-level language programmer. ;)
> Can anyone think of anything that might make this > function unsafe to use in an ISR?
I'll not give you an answer, but some pointers to think about. Consider what the most complex operation in that function is, and how you'd implement it on a CPU that lacks native support for that operation. Look at code-generation strategies for compilers on 'baby micros' and you'll probably start to see why this function will probably be reentrant on a 'big' CPU but (unless the compiler-writers have been competent and generous to you) not on some small ones. I certainly know of (and have debugged customer code, and yelled at compiler vendors for failing to document things properly!) on C implementations where that code would break if reentered. Also, from a determinism point of view, I'd bounce any code with O(N) runtime that someone tried to put in an ISR. Activate a task to do the computation and get the hell out of the ISR ASAP! pete -- pete@fenelon.com "it made about as much sense as a polythene sandwich"
On Jan 25, 4:44 am, "joshc" <josh.cu...@gmail.com> wrote:

> So during an interview for an embedded software position, I was asked > to write any function I wanted in C. I chose an iterative factorial > function like this: > > int iterative_factorial(int i) { > int f; > f = 1; > > while (i != 0) { > f = i * f; > i--; > } > return(f); > > }I was then asked what I would have to worry about or fix to make the > function safe to use in an ISR. I really could not think of anything > wrong with this function as it seems reentrant and I don't see any > concurrency issues. Can anyone think of anything that might make this > function unsafe to use in an ISR?
As long as you perform an analysis to make sure that the time spent in that function does not exceed the limit for that interrupt, there's nothing intrinsically wrong. Since the time depends on the value of 'i', you'll need to determine and or limit its maximum value.
Le Wed, 24 Jan 2007 19:44:50 -0800, joshc a &#4294967295;crit&#4294967295;:

> So during an interview for an embedded software position, I was asked > to write any function I wanted in C. I chose an iterative factorial > function like this: > > int iterative_factorial(int i) { > int f; > f = 1; > > while (i != 0) { > f = i * f; > i--; > } > return(f); > } > > I was then asked what I would have to worry about or fix to make the > function safe to use in an ISR. I really could not think of anything > wrong with this function as it seems reentrant and I don't see any > concurrency issues. Can anyone think of anything that might make this > function unsafe to use in an ISR? > > Thanks, > > Josh
One never should be let say anything obviously stupid ! So I would have answered simply that this kind of function should not never be called in an ISR. It is besides what occurs in the true life. Habib.
In article <bapl84-m83.ln1@stratos.fenelon.com>, pete@fenelon.com 
says...
> joshc <josh.curtz@gmail.com> wrote: > > So during an interview for an embedded software position, I was asked > > to write any function I wanted in C. I chose an iterative factorial > > function like this: > > > > int iterative_factorial(int i) { > > int f; > > f = 1; > > > > while (i != 0) { > > f = i * f; > > i--; > > } > > return(f); > > } > > > > I was then asked what I would have to worry about or fix to make the > > function safe to use in an ISR. I really could not think of anything > > wrong with this function as it seems reentrant and I don't see any > > concurrency issues. > > You're thinking like a high-level language programmer. ;) > > > Can anyone think of anything that might make this > > function unsafe to use in an ISR? > > I'll not give you an answer, but some pointers to think about. > > Consider what the most complex operation in that function is, and how > you'd implement it on a CPU that lacks native support for that > operation. Look at code-generation strategies for compilers on 'baby > micros' and you'll probably start to see why this function will probably > be reentrant on a 'big' CPU but (unless the compiler-writers have been > competent and generous to you) not on some small ones. > > I certainly know of (and have debugged customer code, and yelled at > compiler vendors for failing to document things properly!) on C > implementations where that code would break if reentered. > > Also, from a determinism point of view, I'd bounce any code with O(N) > runtime that someone tried to put in an ISR. Activate a task to do the > computation and get the hell out of the ISR ASAP!
1. If you're going to call the function inside the ISR, I would hope that it's being done because the result is needed in the ISR. Can you then afford to delay the completion of the ISR while waiting for the task to run? 2. Just assuming that you have an RTOS and tasks to activate may immediately take you out of the baby micro area. Mark Borgerson
Mark Borgerson <mborgerson@comcast.net> wrote:
> > 1. If you're going to call the function inside the ISR, I would hope > that it's being done because the result is needed in the ISR. Can > you then afford to delay the completion of the ISR while waiting for > the task to run? >
I've seen code destined for (cough... a very major American auto manufacturer...) written by (cough... a very major semiconductor manufacturer...) that basically ran an entire engine controller either in the idle task or in interrupt handlers. They were a little dismayed when it fell over at around 1800rpm. Which is about as much use as a chocolate teapot. Working out what needs to be in the idle task, what needs to be in interrupts and what needs to be in tasks. ;)
> > 2. Just assuming that you have an RTOS and tasks to activate may > immediately take you out of the baby micro area.
It may; then again it may not. I've been involved in putting RTOSes on devices as small as the PIC18 and Freescale HCS08; I know companies that have gone even lower (8051, PIC16...) pete -- pete@fenelon.com "it made about as much sense as a polythene sandwich"
joshc wrote:
> So during an interview for an embedded software position, I was asked > to write any function I wanted in C. I chose an iterative factorial > function like this: > > int iterative_factorial(int i) { > int f; > f = 1; > > while (i != 0) { > f = i * f; > i--; > } > return(f); > } > > I was then asked what I would have to worry about or fix to make the > function safe to use in an ISR. I really could not think of anything > wrong with this function as it seems reentrant and I don't see any > concurrency issues. Can anyone think of anything that might make this > function unsafe to use in an ISR?
Hello, You did not say what kind of ISR. But I could think of the following things which should be considered: * Is the ISR a high level ISR or written in assembler? If it is in assembler you would have to make sure that when you call the C functions that all registers which are possibly modified by that ISR are stored on the stack. I had some of this issues with assembler written ISRs which did not push all modified registers on the stack. Since most ISRs are high level nowadays this might not be that common anymore. * If your compiler generates code for some instructions which make use of global variables. I don't see any of this in there but for example if you start using floating point and there is no hardware floating point implementation available this could be an issue. Anyhow using floats in an ISR is not a good idea. * As Arlet pointed out WCET is certainly an issue with this function and needs special consideration. Kind regards, Christian Walter
> > Thanks, > > Josh >
-- \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \\\\\\ \\ email: wolti@sil.at \ Friends don't let friends drink and su(1) web: www.freemodbus.org \ -- Kevin Harris

The 2024 Embedded Online Conference