Is extern inline -> static inline OK?
Pardon my ignorance...
Under what conditions is it NOT OK to convert "extern inline" to "static inline"?
Quoted 9 lines · Linus once
- "static inline" means "we have to have this function, if you use it but don't inline it, then make a static version of it in this compilation unit"
- "extern inline" means "I actually _have_ an extern for this function, but if you want to inline it, here's the inline-version"
... we should just convert
all current users of "extern inline" to "static inline".
But Richard Henderson rejected (in 2002) the following patch (excerpt):
-#define __EXTERN_INLINE extern inline
+#define __EXTERN_INLINE static inline
presumably because the exact semantics of extern inline were required. I can only find __EXTERN_INLINE in the alpha architecture. Is the requirement to use 'extern' rather than 'static' unique to alpha?
Thanks for any illumination on this.
=============================
Tim Bird
Architecture Group Co-Chair, CE Linux Forum
Senior Staff Engineer, Sony Electronics
E-mail: [email protected]
=============================
Followup to: <[email protected]> By author: Tim Bird <[email protected]> In newsgroup: linux.dev.kernel
Quoted 6 lines
Pardon my ignorance...
Under what conditions is it NOT OK to convert "extern inline" to "static inline"?
When the code is broken if it doesn't inline.
-hpa
Quoted 4 lines · H. Peter Anvin
Followup to: <[email protected]> By author: Tim Bird <[email protected]> In newsgroup: linux.dev.kernel
Quoted 8 lines
Quoted 5 lines
Pardon my ignorance...
Under what conditions is it NOT OK to convert "extern inline" to "static inline"?
When the code is broken if it doesn't inline.
Thanks!
From what I have read, for either 'extern inline' or 'static inline' the compiler is free to not inline the code. Is this wrong?
It is my understanding that...
In the 'static inline' case the compiler may create a function in the local compilation unit. But in the 'extern inline' case an extern non-inline function must exist. If the compiler decides not to inline the function, and a non-inline function does not exist, you get a linker error. Are you saying that, therefore, 'extern inline' functions are used (without definition of extern non-inline functions to back them) in order to guarantee that NO non-inline version of the function exists?
Or are you saying that the non-inline version of the function may be written differently than the inline version?
Sorry to be so dense... I really appreciate your help.
=============================
Tim Bird
Architecture Group Co-Chair, CE Linux Forum
Senior Staff Engineer, Sony Electronics
E-mail: [email protected]
=============================
Quoted 6 lines · Tim Bird
Thanks!
From what I have read, for either 'extern inline' or 'static inline'
the compiler is free to not inline the code. Is this wrong?
Quoted 9 lines
It is my understanding that...
In the 'static inline' case the compiler may create a function in the local compilation unit. But in the 'extern inline' case an extern non-inline function must exist. If the compiler decides not to inline the function, and a non-inline function does not exist, you get a linker error. Are you saying that, therefore, 'extern inline' functions are used (without definition of extern non-inline functions to back them) in order to guarantee that NO non-inline version of the function exists?
Yes; the final link will fail with an undefined symbol if "extern inline" fails to inline.
-=hpa
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 5 lines · Richard Henderson
Quoted 2 lines · Tim Bird
Under what conditions is it NOT OK to convert "extern inline" to "static inline"?
When... I arrange for an external version to exist.
Richard - thanks for responding.
As you probably know, many people use extern inline incorrectly in the kernel. Your construction appears correct.
Quoted 2 lines
... Grep for
EXTERN_INLINEinarch/alpha/kernelto see how it is used. If you can't figure it out, don't try to change anything.
I can see how it is used, but I can only guess the "why". The only comment I can find about this usage is:
/* Do not touch, this should *NOT* be static inline */
There are a few different reasons someone might use extern inline rather than static inline. Some affect code correctness and some don't. Based on the strength of the wording in your comment, I would guess that the related code would suffer code correctness issues if changed. However just examining the EXTERN_INLINE usage itself did not reveal where the code would be incorrect if static inline were used.
One type of usage which affects code correctness is when the extern function definition differs from the inline function definition. This type of usage of "extern inline" is just plain wrong, since it RELIES on the compiler to use a particular version of the function (either the extern one or the inline one), and the compiler is supposed to be free to make this choice. This does not appear to be the case with your code, since your construct uses the same source code to create the extern functions as the extern inline definitions. (But maybe I missed something.)
Other reasons for using extern inline are to minimize code footprint by avoiding extra function copies in different compilation units, and to increase cache hotness by reusing the same code, when the compiler decides to not inline a function. This last benefit is usually unlikely, since uninlined code in the same compilation unit as the currently executing code is much more likely to be in-cache than uninlined code in some other compilation unit.
Finally, another reason for using extern inline is to avoid pointer comparison mismatch for function pointers to uninlined functions.
In any event, it is difficult to tell what incorrectness is (presumably) introduced in the alpha code by using 'static inline' vs. 'extern inline', for the functions so designated. Maybe you have specific code that breaks, or maybe you just saw broken behaviour with the code compiled differently.
If you could indicate WHY the alpha code must be 'extern inline', it might be helpful to me, and instructive for others who need to be educated on this same issue.
1) have different definitions for functions with same name
2) avoid wasting space with multiple function copies
3) increased instruction cache effectiveness
4) function pointers comparisons
5) some other reason I still don't understand
If anyone else can tell me if they are aware of cases of either
1) or 5) for other uses of 'extern inline' in the kernel, that would be helpful.
BTW - I'm trying to figure this out because an instrumentation system I'm working with uses gcc's -finstrument-functions, which doesn't deal well with extern inlines that don't really have extern definitions. I'm trying to get a grip on which 'extern inlines' it's OK to change, and which aren't, and how to deal with the ones which shouldn't be changed.
Thanks,
=============================
Tim Bird
Architecture Group Co-Chair, CE Linux Forum
Senior Staff Engineer, Sony Electronics
E-mail: [email protected]
=============================
Quoted 1 line · Tim Bird
2) avoid wasting space with multiple function copies
Mostly this one. The translation units that do the EXTERN_INLINE defines also define tables containing (among other things) pointers to all of these functions. So we *know* that we require one out-of-line copy in one translation unit, so we might as well make that version the canonical out-of-line copy.
Also, I seem to recall some multiply-defined symbol something or other the last time someone messed with our inlining construct.
r~