Копирую оригинал доков, чтобы не быть голословным.
Each fix-mapped linear address is represented by an integer index defined in the enum
fixed_addresses data structure:
enum fixed_addresses {
FIX_APIC_BASE,
FIX_IO_APIC_BASE_0,
[...]
__end_of_fixed_addresses
};
Fix-mapped linear addresses are placed at the end of the fourth gigabyte of linear
addresses. The fix_to_virt( ) function computes the constant linear address starting
from the index:
inline unsigned long fix_to_virt(const unsigned int idx)
{
if (idx >= _ _end_of_fixed_addresses)
__this_fixmap_does_not_exist( );
return (0xffffe000UL - (idx << PAGE_SHIFT));
}
Let's assume that some kernel function invokes fix_to_virt(FIX_IOAPIC_BASE_0).
Since the function is declared as "inline," the C compiler does not invoke fix_to_virt( ),
but just inserts its code in the calling function. Moreover, the check on the index value is
never performed at runtime. In fact, FIX_IOAPIC_BASE_0 is a constant, so the compiler
can cut away the if statement because its condition is false at compile time. Conversely, if
the condition is true or the argument of fix_to_virt( ) is not a constant, the compiler
issues an error during the linking phase because the symbol __this_fixmap_does_not_exist is not defined elsewhere. Eventually, the compiler
computes 0xffffe000-(1<<PAGE_SHIFT) and replaces the fix_to_virt( ) function
call with the constant linear address 0xffffd000.
Т.е., коротко говоря, компилер отрежет вызов __this_fixmap_does_not_exist().
А вот не получается у меня мой тестовый пример. См. ниже.
// inline.cpp
inline int mytest(const int i)
{
if (i > 3)
__bad_i();
return i;
}
int main()
{
int a = mytest(2);
}
Делаю gcc -O inline.cpp -o inline
Получаю:
/tmp/ccgxcQIG.o(.text+0x14): In function `mytest':
inline.c: undefined reference to `__bad_i'
collect2: ld returned 1 exit status
Вопрос: где же истина? Может быть, я что-то не так делаю?
Попробую объяснить получше.
Исходя из текста выше, компилятор оптимизирует код inline функции,
не вставляя заведомо ложные условия.
Когда я читал эти доки, то усомнился в том, что там написано.
Решил проверить, как это можно написать в коде вызов функции, которая
нигде не определена, и это ещё будет компилиться.
Получил ошибки линковки.
Однако, книжка серьёзная (Understanding the Linux kernel, 2nd ed.),
не должно быть таких грубых ошибок.
В моём примере if (i > 3) - заведомо ложное условие, потому как i при вызове = 2.
Может быть, дело в версии компилятора?
Да, в исходниках ядра всё это используется.
Видимо, я создаю неправильные условия для опыта:)
objdump показывает, что действительно исчезает вызов функции __bad_i
при ложном условии. Ладно, пусть так .... :)