Recommended practices for re-entrant code in C, C++
Asked Answered
Q

4

7

I was going through a re-entrancy guide on recommended practices when writing re-entrant code.

What other references and resources cover this topic?

What lint-like tools can be used to check for these issues?

Quinte answered 13/7, 2010 at 18:30 Comment(2)
That guide pretty much has everything you need to know. It's not a very subtle thing. Don't use data that you weren't passed in the function call, don't store any state in the function.Cranwell
That guide has numerous errors in it, from a definition of reentrancy that's actually multithreading (though the signal processing examples are true reentrancy) to bad advice (mutexes... hello deadlock) to just plain bugginess (sigsuspend(&zeromask) .. you've just allowed processing interrupts that your caller disabled for a reason, try sigsuspend(&oldmask) instead).Thorn
A
0

The guide is sufficient.

My personal rule of thumbs are only 2 for re-reentering code:

  1. take only pass by value parameters, used only value passed in as parameters in the function.

  2. if I need to use any global parameters or pointer (for performance or storage sake), use a mutex or semaphore to control access to it.

Arrowy answered 14/7, 2010 at 2:4 Comment(17)
If you need complex types, make them immutable if possibleOperose
Hi fmark: can you explain a further? Or point me to something related to this statement?Arrowy
no No NO! Reentrancy != Threading. Mutexes and semaphores will deadlock reentrant code, or else silently fail to do their job and leave data corruption.Thorn
@Ben Voigt: agree to your point. "Both concepts of reentrancy and thread safety relate to the way functions handle resources. However, they are not the same." "Reentrancy is a more fundamental property than thread-safety and by definition, leads to thread-safety: Every reentrant function is thread-safe; however, not every thread-safe function is reentrant."Arrowy
The difference between thread safety and reentrancy: blogs.msdn.com/b/oldnewthing/archive/2004/06/29/…Intendance
Just more clarification here: 1. reentrancy - allow function to execute concurrently (e.g. by threads) without blocking on share resources (but a snapshot of the values) or do not need any share resources(result of multiplication of 2 numbers) 2. thread safety - arbitrate access to share resources which will cause blocking/queuing in access to resourceArrowy
@ttchong: No, not every reentrant function is thread-safe. Reentrance is often synchronous, in that there are only a few controlled points in the code where recursion can occur (or even with asynchronous signals, they may be masked during portions of the code). And signals run fully before the original call resumes. But in concurrent (multi-threaded) environments a second instance of the function can exist anywhere in the execution and both can make progress at the same time, there's no chance for the second invocation to restore state before the first continues.Thorn
No, that's not what reentrancy means. Concurrency (threads) are not necessary for reentrance. Signals and callbacks are also sources of reentrance.Thorn
This other question also has a bunch of useful information: #2799523Thorn
@Ben Voigt: don't quite get your second comment. I do some research to make sure my understanding on concurrency before posting this inquiry. Can you clarify further or point me to something? Thanks.Arrowy
Also look at Raymond Chen's blog post that Adam linked to, there are more examples there of functions than are either reentrant or thread-safe but not both.Thorn
Here's another example of code that is reentrant but not thread-safe. Let's suppose I have two functions that adjust the FPU control word (one needs exceptions enabled, the other needs them disabled). Both functions save the current state of the FPU control word on entry and restore it on exit. Now, these two functions can mutually recurse all day long, you can use them safely from signal handlers too -- they are reentrant. But they are definitely not thread-safe.Thorn
@BenVoigt it depends on the definition of re-entrant code. If it include re-entry from other threads, it would imply that re-entrant code are automatically thread safe.Shawnshawna
@Chethan: If you use incorrect definitions of standard terminology, you can make any statement correct. But also meaningless.Thorn
@BenVoigt as wikipaedia says, the term was defined long ago there there were only single threaded environments and interrupts. If you want to stick to that definition - sure. Please read the re-entrancy guide in the Q.Shawnshawna
@Chethan: Please read my comment on this Q. That guide is not worth the bits it's encoded in.Thorn
Point number 2 in this answer is dangerous! If your function needs to take a mutex then it is not re-entrant (consider the case where a signal arrives while your function holds the mutex, and then the signal handler calls your function).Royceroyd
T
2
  • Do use local variables.
  • Don't use static locals or global variables, even TLS will not help you with recursion / reentrancy.
  • Restore all your invariants before doing callbacks.
  • Don't hold locks while you do callbacks. If you absolutely must (and I would still go looking for a way to avoid it) then make sure you know what happens if you try to re-enter your lock on the thread that already holds it. At a minimum you have to test for this, otherwise depending on the lock you'll get deadlocks or broken invariants (i.e. corruption).
Thorn answered 14/7, 2010 at 2:14 Comment(0)
N
1

None really. Writting non-reentering code is usually more difficult than re-entring. Just follow those simple guidelines and don't try to do anything too waky and you'll be fine.

Non-reentering code is usually written for high-performance issues.

Nagaland answered 13/7, 2010 at 18:44 Comment(0)
A
0

The guide is sufficient.

My personal rule of thumbs are only 2 for re-reentering code:

  1. take only pass by value parameters, used only value passed in as parameters in the function.

  2. if I need to use any global parameters or pointer (for performance or storage sake), use a mutex or semaphore to control access to it.

Arrowy answered 14/7, 2010 at 2:4 Comment(17)
If you need complex types, make them immutable if possibleOperose
Hi fmark: can you explain a further? Or point me to something related to this statement?Arrowy
no No NO! Reentrancy != Threading. Mutexes and semaphores will deadlock reentrant code, or else silently fail to do their job and leave data corruption.Thorn
@Ben Voigt: agree to your point. "Both concepts of reentrancy and thread safety relate to the way functions handle resources. However, they are not the same." "Reentrancy is a more fundamental property than thread-safety and by definition, leads to thread-safety: Every reentrant function is thread-safe; however, not every thread-safe function is reentrant."Arrowy
The difference between thread safety and reentrancy: blogs.msdn.com/b/oldnewthing/archive/2004/06/29/…Intendance
Just more clarification here: 1. reentrancy - allow function to execute concurrently (e.g. by threads) without blocking on share resources (but a snapshot of the values) or do not need any share resources(result of multiplication of 2 numbers) 2. thread safety - arbitrate access to share resources which will cause blocking/queuing in access to resourceArrowy
@ttchong: No, not every reentrant function is thread-safe. Reentrance is often synchronous, in that there are only a few controlled points in the code where recursion can occur (or even with asynchronous signals, they may be masked during portions of the code). And signals run fully before the original call resumes. But in concurrent (multi-threaded) environments a second instance of the function can exist anywhere in the execution and both can make progress at the same time, there's no chance for the second invocation to restore state before the first continues.Thorn
No, that's not what reentrancy means. Concurrency (threads) are not necessary for reentrance. Signals and callbacks are also sources of reentrance.Thorn
This other question also has a bunch of useful information: #2799523Thorn
@Ben Voigt: don't quite get your second comment. I do some research to make sure my understanding on concurrency before posting this inquiry. Can you clarify further or point me to something? Thanks.Arrowy
Also look at Raymond Chen's blog post that Adam linked to, there are more examples there of functions than are either reentrant or thread-safe but not both.Thorn
Here's another example of code that is reentrant but not thread-safe. Let's suppose I have two functions that adjust the FPU control word (one needs exceptions enabled, the other needs them disabled). Both functions save the current state of the FPU control word on entry and restore it on exit. Now, these two functions can mutually recurse all day long, you can use them safely from signal handlers too -- they are reentrant. But they are definitely not thread-safe.Thorn
@BenVoigt it depends on the definition of re-entrant code. If it include re-entry from other threads, it would imply that re-entrant code are automatically thread safe.Shawnshawna
@Chethan: If you use incorrect definitions of standard terminology, you can make any statement correct. But also meaningless.Thorn
@BenVoigt as wikipaedia says, the term was defined long ago there there were only single threaded environments and interrupts. If you want to stick to that definition - sure. Please read the re-entrancy guide in the Q.Shawnshawna
@Chethan: Please read my comment on this Q. That guide is not worth the bits it's encoded in.Thorn
Point number 2 in this answer is dangerous! If your function needs to take a mutex then it is not re-entrant (consider the case where a signal arrives while your function holds the mutex, and then the signal handler calls your function).Royceroyd
C
0
  1. A reentrant function may not use variables in a non-atomic way unless they are stored on the stack of the calling task or are the private variables of that task.
  2. A reentrant function may not call other functions which are not reentrant.
  3. A reentrant function may not use the hardware in a non-atomic way.

Ref: Page 462 [AN INTRODUCTION USING THE RENESAS RX62N MICROCONTROLLER] [James M. Conrad]

Castled answered 9/10, 2014 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.