cancel
Showing results for 
Search instead for 
Did you mean: 

Reentrant syscalls

ccowdery9
Associate III
Posted on March 23, 2009 at 08:17

Reentrant syscalls

9 REPLIES 9
ccowdery9
Associate III
Posted on May 17, 2011 at 13:06

Good Afternoon all,

I am integrating the Newlib calls into my firmware, and have included sufficient to allow printf() & friends to work OK.

I have noticed that the functions I have implemented are the _r variants, which makes me think that the library is reentrant. However my code is not reentrant, and it makes no use of the void *reent structure.

- Should these functions be reentrant for embedded code?

- How does one make a reentrant routine, e.g. writing a character to the USART?

I understand what a reentrant routine is, but I don't understand how it can be applied to I/O handling.

Any clues?

Thanks,

Chris.

trevor1
Associate II
Posted on May 17, 2011 at 13:06

I guess the first question is ''does your code need to be re-entrant?''. Are you using an OS?

If you are writing to UART under interrupt then the Tx interrupt typically takes a byte out of your buffer (probably a circular one) and puts it in the USART TX register. The Tx interrupt will not interrupt itself so this is safe.

If you are not using interrupts and you are using a pre-emptive OS (RTOS) then you need to learn about mutexes in order to write reentrant code. I presume the Newlib reent struct needs to be provided with a pointer to a mutex or something that you must provide for your OS. The other lazy option is to disable interrupts around reentrant code but this will lead to disaster if the code takes any time to run.

Maybe you could describe your system more so we're not guessing what you might have e.g.

RTOS ?

using interrupts for serial Tx and Rx etc ?

Trevor

ccowdery9
Associate III
Posted on May 17, 2011 at 13:06

Hi Trevor,

Thanks for your comments.

My project has no RTOS, or any OS at all. It's a very much modified (now probably

The UART stuff is not done under interrupts, it's a simple poll for free buffer, then write to buffer. (or poll for RX char, then read buffer).

What would be nice (for example) is if printf() and friends could safely be called from interrupts & main().

The next step is to link EFSL (an SD card FAT filesystem driver) with Newlib, so I can use the standard C calls (e.g. fopen, etc.). However, I have some interrupt routines (one plays a WAV file from SD card), and it would be nice to know that I can open & read files from an interrupt at the same time as main() is doing the same. I think if the reentrancy is handled properly, all this should just work!!!

What do you think?

Thanks,

Chris.

trevor1
Associate II
Posted on May 17, 2011 at 13:07

Hi Chris,

I would strongly advise that you don't printf, fread, fwrite etc or anything else that takes significant time to execute from an interrupt. In general interrupt processing should be kept as short as possible. In my code I never do any of the above in an interrupt.

If you must then you will need to disable interrupts and then restore interrupts to there original state around critical sections of code. This is further complicated if your using nested interrupts which the Cortex supports. All in all not a trivial task.

Is the printf for debug? You could just use IO pins and a scope instead in an interrupt.

Regards

Trevor

ccowdery9
Associate III
Posted on May 17, 2011 at 13:07

Hi Trevor,

I guess what I mean is that if I can use printf() from an interrupt safely, then all the reentrancy conditions must be met?

I accept that it is likely to be much slower, and I already have

uart_puts(char *), uart_putint(u32) etc. And I wouldn't use printf() except for debug, and even then I'm much more likely to use my uart_ routines.

I am sure I can cobble an implementation together that maps newlib to my uart and EFSL, but what I really need to understand is whether I have met all the reentrancy conditions for the calls. If I do it right to start with, then it won't bite me in the future! The problem is that I don't really know what these conditions are. One day I might have multiple threads running, and I'd like to be confident that it's all in order.....

Or I might put my code out for other people, but I'd like it to be right first! (I hate debugging other peoples code!, e.g. the EFSL uSD driver)

Thanks,

Chris.

trevor1
Associate II
Posted on May 17, 2011 at 13:07

Not quite true. Most code that is described as reentrant cannot be run from an interrupt. For example if you call a mutex lock function or OS event wait function from inside an interrupt the OS will often jump to it's exception handler as this is an invalid operation (you cannot wait for an event to happen from inside an interrupt). But mutexes and event waits are used in multi-threaded code to make it reentrant when it uses a shared resource (e.g. hardware).

If you want to write code that can be run from an interrupt you will have to disable interrupts and restore to original interrupt state around any code that uses global or static variables or code that uses a common resource such as a processor register. But this code will not be code you would want to share with others or use threads as you mention below.

Then you will have the big problem with making sure that interrupts are not disabled for too long because when you do start using threads you will be using interrupts to receive data and if interrupts are disabled for too long you will loose data.

Regards

Trevor

picguy
Associate II
Posted on May 17, 2011 at 13:07

You could use a queue - ISR source, task sink. Task sees a type code selecting a printf parameter list to call. What do you do when the queue is full and you have something else to send? Solve this “little� problem first.

ISRs “drinking from the fire hose� can not be resolved inside the ISR.

ccowdery9
Associate III
Posted on May 17, 2011 at 13:07

So in my case, with no OS, provided I don't call anything I shouldn't under interrupts, reentrancy is not required or even relevant.

I think I'll just put in some comments to the effect that re-entrancy isn't supported in my _r calls!

Thanks for comments.

Chris.

trevor1
Associate II
Posted on May 17, 2011 at 13:07

Hi Chris,

Yes you are correct, this is one of the advantages in not using an RTOS (if you can).

You get the same advantage when using a non-pre-emptive OS which is refereed to as a cooperative OS but that is probably a story for another day.

Good luck

Trevor