LINUX.ORG.RU

Применение специальных возможностей GCC в ядре Linux

 ,


0

0

В ядре Linux® используется ряд особых возможностей набора компиляторов GNU (GCC) — от возможностей упрощения и более короткой записи до предоставления компилятору подсказок для оптимизации кода. Откройте для себя некоторые из этих особых возможностей GCC и узнайте, как их использовать в ядре Linux.

>>> Подробности

★★★

Проверено: Shaman007 ()
Ответ на: комментарий от zzo

>Это что за ересь?
>

>#define min(x, y) ({ \

> typeof(x) _min1 = (x); \

> typeof(y) _min2 = (y); \

> (void) (&_min1 == &_min2); \

> _min1 < _min2 ? _min1 : _min2; })

>

> Зачем, собсногря, так много букав?


Имеется в виду, что
#define min(x,y) ((x)<(y)?(x):(y))
не особо хорошо при таком использовании:
min(i++,j++)

rekub
()
Ответ на: комментарий от rekub

Ух ты! И правда, typeof(x++) работает как надо - x не инкрементирует. В статье, конечно же, такого не написано.

А зочем
(void) (&_min1 == &_min2);
?

zzo
()
Ответ на: комментарий от sS

>Можно и не так жестоко :)
>-pedantic или -ansi ;)


ну вперёд на грабли

{vl}[vl@tmp]$ gcc -ansi -pedantic -o t t.c
t.c: In function 'main':
t.c:5: error: 'sigset_t' undeclared (first use in this function)
t.c:5: error: (Each undeclared identifier is reported only once
t.c:5: error: for each function it appears in.)
t.c:5: error: expected ';' before 'newmask'
t.c:6: warning: ISO C90 forbids mixed declarations and code
t.c:8: error: 'newmask' undeclared (first use in this function)
{vl}[vl@tmp]$ cat t.c
#include <signal.h>

int main(int argc,char* argv[])
{
sigset_t newmask;
int ret;

ret = sigemptyset(&newmask);

return 0;
}


P.S. по теме - нестандартные возможности в gcc как раз и имеются, потому, что они нужны, а не потому что разработчикам страсть как хотелось создать какой-нибудь извращённый атрибут и надругаться над стандартом.

deadman ★★
()
Ответ на: комментарий от zzo

> А зочем
> (void) (&_min1 == &_min2);
> ?

Проверка типов?

[gusev@miranda ~]$ cat test.c
#include <stdint.h>

#define min(x, y) ({                            \
        typeof(x) _min1 = (x);                  \
        typeof(y) _min2 = (y);                  \
        (void) (&_min1 == &_min2);              \
        _min1 < _min2 ? _min1 : _min2; })

main()
{
        uint32_t x = 5;
        int64_t y = 10;

        min(x, y);
        x < y ? x : y;
}
[gusev@miranda ~]$ gcc test.c
test.c: In function ‘main’:
test.c:14: warning: comparison of distinct pointer types lacks a cast

ptomaine
()
Ответ на: комментарий от deadman

$ gcc -ansi -pedantic -Wall c.c
$ cat c.c
#define _XOPEN_SOURCE 500
#include <signal.h>

int main(int argc,char* argv[])
{
sigset_t newmask;
int ret;

ret = sigemptyset(&newmask);

return 0;
}

Manhunt ★★★★★
()
Ответ на: комментарий от anonimuos

> нестандартным возможностям - НЕТ
Молодому человеку советую сначала осилить C99 и GCC99 потом судить, аргументируя свое IMHO.

Если возможность реально:
*облегчает жизнь.
*упрощает код.
*делает код более понятным.
*позволяет проще поддерживать код.
*делает поведение компилятора более предсказуемым.

Значит она должна стать стандартом.

BTW. Инфа для размышления 50-60% GCC расширений уже давно стало стандартом. Остальные 40-50% скоро станут. Догадайтесь с 3 попыток на каком компиляторе гоняют то что станет стандартом.

PS. Статья не раскрыла большую часть C99 и других полезных расширений GCC.

alexr
()
Ответ на: комментарий от alexr

> Инфа для размышления 50-60% GCC расширений уже давно стало стандартом. Остальные 40-50% скоро станут.

Лолшто? Вы забыли о тех gnu extensions, которые сначала были объявлениы deprecated, а потом и вовсе выкинуты из компилятора. И если программа была гвоздями прибита к таким экстеншенам, то переход на новую версию gcc оборачивается реальной болью в заднице.

> Статья не раскрыла большую часть C99 и других полезных расширений GCC.

Лолшто? Давно c99 стал gcc-шным расширением? Ничего, что gcc до сих пор (10 лет спустя!!!) не поддерживает значительную часть стандарта c99?

> Молодому человеку советую сначала осилить

Сами ничего толком не умеете, и от того вам нравится разговаривать с другими в снисходительном тоне?

Manhunt ★★★★★
()
Ответ на: комментарий от skwish

> То, что майкрософт видите ли в MSVC расширяет стандарт - это отстой. А то, что GCC вводит ни с кем несовместимые расширения - это крутизна? Linux-way так сказать.

Ага, это верно, вы бы посмотрели про совместимость с C99 стандартом, сейчас никто из больших фирм типа МС или Борланда не поддерживает их, там чётко на странице стандартов об этом сказано. Единственный кто приблизился это GCC, и, возможно, от интел (но я не уверен).

МС и Борланд делают упор на C++98

Vest
()
Ответ на: комментарий от alexr

Если компилятор такой хороший, то почему ядро нельзя компилить с опцией О2? Почему оптимизацию кода доверяют разработчикам ядра, а не компилятору?

ИМХО большинство рюшечек gcc не имело смыла реализовывать, т.к. тоже самое разработчики кода ядра могли бы написать на ассемблере :D

yantux
()
Ответ на: комментарий от yantux

Разве это не разные языки?
C++98 - стандарт C++
C99 - стандарт C

Sova777
()
Ответ на: комментарий от A-234

> <trollmode>, так что остальные должны соответствовать или молчать в сторонке</trollmode>

Да так оно и есть. icc поддерживает кучу расширений gcc.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от yantux

>>А зачем ядро написно так, чтобы компилятор не мог использовать оптимизацию выше О2?

мля, ты представляешь себе вообще что такое оптимизация выше O2 ? Компилятору позволяется весьма многое, что в случае ядра просто не проканает.

# -O3: This is the highest level of optimization possible, and also the riskiest. It will take a longer time to compile your code with this option, and in fact it should not be used system-wide with gcc 4.x. The behavior of gcc has changed significantly since version 3.x. In 3.x, -O3 has been shown to lead to marginally faster execution times over -O2, but this is no longer the case with gcc 4.x. Compiling all your packages with -O3 will result in larger binaries that require more memory, and will significantly increase the odds of compilation failure or unexpected program behavior (including errors). The downsides outweigh the benefits; remember the principle of diminishing returns. Using -O3 is not recommended for gcc 4.x.

deadman ★★
()
Ответ на: комментарий от yantux

> Я принципиально против расширений, потому что девелоперу привыкшему к другому компилятору приходится тратить время на изучение рюшечек gcc, тратиться время и т.д.

ССЗБ -- не надо было привыкать к другому компилятору. Для таких сделан станадарт С.

> Зачем это надо?

Тебе возможно и не надо. А вот другим, кто хочет аналог template<typename T> T min(T a, T b) но на С, нужен typeof и прочие функциональные рюшки.

А еще через typeof пишутся -- что в статье не указали -- свои конструкции типа foreach( el, list) { делать делать что-то с el }

Причем оно есть в исходниках ядра.

> Если компилятор может лучше компилить, то уж лучше задать опции соответсвующие, чтобы это было закрыто от программиста.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

foreach( el, list) { делать делать что-то с el }

причем определить foreach как не макрос на с++ не напишешь (разве что на С++0х, но синтаксис будет другой).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Alve

>Давайте сделаем форк ядра на Моно. Уж там стандартов!...

Между прочим гомосексуализм не есть хорошо

daemontux
()
Ответ на: комментарий от deadman

Где грабли то ? :)

Таки вкури тему :)

sS ★★★★★
()
Ответ на: комментарий от yantux

> Если компилятор такой хороший, то почему ядро нельзя компилить с опцией О2?

Я собирал когда-то ядро с -O3. Работало без проблем. Что конкретно у вас поломалось от -O3?

Relan ★★★★★
()
Ответ на: комментарий от Vest

>Ага, это верно, вы бы посмотрели про совместимость с C99 стандартом, сейчас никто из больших фирм типа МС или Борланда не поддерживает их, там чётко на странице стандартов об этом сказано. Единственный кто приблизился это GCC, и, возможно, от интел (но я не уверен).

>МС и Борланд делают упор на C++98


Свои 5 копеек:
Не ставьте Борланд и МС в один ряд. Глава С++ направления бывшего Борланда - один из главных в группе стандартизации С++. И поверьте, опытным путем выяснял, что BCB стандарты держит гораздо лучше, чем VS. У МС в этом плане такие перлы видел...

Pavval ★★★★★
()
Ответ на: комментарий от Manhunt

>Ничего, что gcc до сих пор (10 лет спустя!!!) не поддерживает значительную часть стандарта c99?

"Значительную" это как? Хотя конечно если математика на уровне "один, два, много" то вопросов нет.

http://gcc.gnu.org/c99status.html

A-234 ★★★★★
()
Ответ на: комментарий от Relan

> Я собирал когда-то ядро с -O3. Работало без проблем. Что конкретно у вас поломалось от -O3?

Насколько я знаю, так ядро собирать не рекомендуется.

yantux
()
Ответ на: комментарий от A-234

Значительную, это:
wide character library support
variable-length arrays
complex (and imaginary) support
extended identifiers
extended integer types
treatment of error conditions by math library
IEC 60559 support
additional predefined macro names
standard pragmas

Manhunt ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Тоже самое нельзя сделать вставкой ассемблера? Обязательно компайлер курочить, устнавливать стандарты программирования?

Эти стандарты надо изучать, запоминать. Один год с ним не поработаешь - всё забудежь :( потом заного учиться :(

yantux
()
Ответ на: комментарий от Manhunt

Беда в том, что если я вот так же приведу список того что реализовано это сочтут флудом, намек понятен?

A-234 ★★★★★
()
Ответ на: комментарий от yantux

> Зачем придумали тупые стандарты С99 и С++98, если их поддерживает всего ТРИ компилятора в мире?

Можно поставить вопрос иначе: зачем понаписали тупых компиляторов, которые не соответствуют даже стандартам десятилетней давности?

Ответ такой: языки си и с++ значительно сложнее, чем тебе кажется издалека. Если не фиксировать свойства этих языков путем принятия стандартов, программирование превратится в кошмар. А так - _все_ компиляторы стремятся воплотить одни и те же стандарты. Кто-то делает это более успешно, кто-то менее успешно. Но в целом программист может учить сам язык, а не диалект этого языка, прибитый гвоздями к конкретному компилятору. И можно надеяться на переносимость.

Manhunt ★★★★★
()
Ответ на: комментарий от A-234

> Беда в том, что если я вот так же приведу список того что реализовано это сочтут флудом, намек понятен?

Давай вырежем тебе пару почек. Казалось бы, список уцелевших органов огро-оомный. Но тушка все равно не жилец. Намек понятен?

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

> Чем она - "хорошо"? Без нее ядро не успевает обрабатывать прерывания? Без нее ядро кушает 90% процессорного времени? Нафига она там?

Ну вот как станешь разработчиком ядра, так поймёшь ;)

mv ★★★★★
()
Ответ на: комментарий от Manhunt

> По сути вопроса можешь что-нибудь сказать?

Конечно! alignment и pack (особенно первый) - очевидная необходимость. deprecated - очень хорошая практика не дать толпе мантейнеров забыть о том, что функция N скоро исчезнет, и пора бы уже свой кусок переделать под новый интерфейс. builtin_expect - не так остро нужен, но в некоторых случаях позволяет объяснить компилятору, что он не прав без вставки ассемблерного чанка.

Собственно говоря, с таким охватом платформ, как у gcc, в opensource уже имеет смысл говорить "язык Си == компилятор gcc". Альтернатив-то всё равно даже близко нет.

mv ★★★★★
()
Ответ на: комментарий от alexr

> PS. Статья не раскрыла большую часть C99 и других полезных расширений GCC.

А зачем? Все расширения в документации должны быть описаны. А статья должна была показать несколько примеров и убедить читателя в их полезности.

skwish ★★
()

А нечего ядра на недоязыках писать.

Когда отцам захотелось написать революционно новый Юникс, они сели и написали для этого язык. Они мужики.

Шапиро захотел написать EROS, сел и придумал BitC. EROS, конечно, говно, и Шапиро мадук, но BitC крут.

А Линус - скрипт-кидди малолетний, взял, что старшие братья подкинули. Хорошо ещё, делфи в то время не было, а то так бы кнопочки на формочки и таскал.

tomodachi_ni_narimashou
()
Ответ на: комментарий от tomodachi_ni_narimashou

Мальчик, иди своё мультипликационное японское порно смотри. Тут суровые мужики серьёзные вещи обсуждают, твоему травмированному мозгу не понять.

mv ★★★★★
()
Ответ на: комментарий от mv

> alignment и pack (особенно первый) - очевидная необходимость.

pack, если нельзя обойтись побайтовым доступом, делается арифметикой с указателями

alignment очень удобен, но при желании также заменяется арифметикой с указателями

В целом о _необходимости_ речи не идет.

> deprecated - очень хорошая практика не дать толпе мантейнеров забыть о том, что функция N скоро исчезнет, и пора бы уже свой кусок переделать под новый интерфейс.

С этим соглашусь. На результаты компиляции аттрибут не влияет, так что и переносимость особо не портит.

> builtin_expect - не так остро нужен, но в некоторых случаях позволяет объяснить компилятору, что он не прав без вставки ассемблерного чанка.

А потом версия компилятора сменится, и ты будешь долго дебажиться, а потом ругать себя за то, что с самого начала не сделал асм-овую вставку. builtin_expect может помочь выгадать несколько процентов производительности на performance-critical участках кода, но это разговор уже совсем не про ядро. По большому счету, builtin_expect не нужен нигде.

Manhunt ★★★★★
()
Ответ на: комментарий от mv

> А ты с какова раёна?

Ржавый, ты Томадачу не трогай. Он нам сам мобилку отдаст, и уйдет. Правда, tomodachi_ni_narimashou?

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

>> alignment очень удобен, но при желании также заменяется арифметикой с указателями

> В целом о _необходимости_ речи не идет.

Не соглашусь. Пример из юзерспейса: руками кодируем sse-фильтр, хотим использовать быстрые команды, работающие с выровненными данными, и выдающие sigsegv/sigbus на невыровненных. Можно использовать медленные команды для невыровненных данных, но ведь можно вообще с ручной оптимизацией не заморачиваться. Написать на чистом Си и надеяться, что когда-нибудь, через несколько лет, компиляторостроение дойдёт до такой степени, что руками даже для sse писать уже не надо будет.

> А потом версия компилятора сменится, и ты будешь долго дебажиться, а потом ругать себя за то, что с самого начала не сделал асм-овую вставку.

Притянуто за уши. Если старый код планируется запускать на новых платформах (программных имеется в виду), то этот код должен мантейниться.

> builtin_expect может помочь выгадать несколько процентов производительности на performance-critical участках кода, но это разговор уже совсем не про ядро. По большому счету, builtin_expect не нужен нигде.

По большому счёту, компилятор очень-очень часто не имеет возможности знать, как нужно оптимизировать в том или ином месте переход, потому что эта информация содержится только в голове у программиста. Если производительность кода не важна, то никто с нестандартными расширениями и не заморачивается. Меня обламывает в обычном коде builtin_expect использовать. С другой стороны, когда просто так на 15% скорость критичного кода повысилась, то грех expect не вставить.

mv ★★★★★
()
Ответ на: комментарий от Manhunt

>> alignment и pack (особенно первый) - очевидная необходимость.

> pack, если нельзя обойтись побайтовым доступом, делается арифметикой с указателями

> alignment очень удобен, но при желании также заменяется арифметикой с указателями

Ы. Ты освоил арифметику с указателями, и решил на радостях этим понтоваться?

tailgunner ★★★★★
()
Ответ на: комментарий от mv

> руками кодируем sse-фильтр, хотим использовать быстрые команды, работающие с выровненными данными

Чтобы получить правильно выравненный массив, надо сказать posix_memalign().

> Притянуто за уши. Если старый код планируется запускать на новых платформах (программных имеется в виду), то этот код должен мантейниться.

Очень плохо, если код полагается на те свойства, которые не гарантирует ни стандарт, ни (в случае с builtin_expect) даже документация на компилятор.

> По большому счёту, компилятор очень-очень часто не имеет возможности знать, как нужно оптимизировать в том или ином месте переход, потому что эта информация содержится только в голове у программиста.

Для этого есть profile-guided optimisation. Которая даст компилятору сведения гораздо более точные и полные, чем догадки программиста.

> Если производительность кода не важна, то никто с нестандартными расширениями и не заморачивается.

А если она в самом деле важна, и возможности алгоритмической оптимизации исчерпаны, то дело пахнет переписыванием на асм-е. builtin_expect здесь как мертвому припарки.

> С другой стороны, когда просто так на 15% скорость критичного кода повысилась, то грех expect не вставить.

Краевых случаев, где 15% в действительности что-то решают, очень мало.

Manhunt ★★★★★
()
Ответ на: комментарий от tailgunner

> Ты освоил арифметику с указателями, и решил на радостях этим понтоваться?

Должен тебя огорчить: ты не угадал.

Manhunt ★★★★★
()
Ответ на: комментарий от mv

> С другой стороны, когда просто так на 15% скорость критичного кода повысилась, то грех expect не вставить.

Можешь запостить сюда простенький пример, где программа из-под gcc -O2 от добавления builtin_expect ускорялась бы аж на 15%? Скажем, вместо 60 секунд успевала бы отработать за 52? Мне кажется, что получить такой заметный выгрыш можно только на очень извратном коде...

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

> Чтобы получить правильно выравненный массив, надо сказать posix_memalign().

Unix-specific.

> Для этого есть profile-guided optimisation. Которая даст компилятору сведения гораздо более точные и полные, чем догадки программиста.

Догадки? Хорошие программисты *знают*. При недостатке опыта, конечно, помогает, но гуру ещё до написания кода уже знают, где будут затыки. PGO в виде performance counter'ов помогают только при отладке нового железа. Оно и появилось-то непосредственно для отлова ошибок в процессорах.

> А если она в самом деле важна, и возможности алгоритмической оптимизации исчерпаны, то дело пахнет переписыванием на асм-е. builtin_expect здесь как мертвому припарки.

На асме x86 переписать обычный, невекторный код лучше, чем это делает gcc (4.4 особенно) - весьма нетривиальная задача. К тому же, отличное знание ассемблера - это редкий скилл, обладатель которого хочет больше денег. Таким образом, expect на производстве обходится значительно дешевле :)

> Краевых случаев, где 15% в действительности что-то решают, очень мало.

Да любая долгообсчитываемая расчётная задача. Если вместо недели расчёт обсчитается за 5 дней, то тут уже и премией попахивает =) Можно переписать на ассемблере, и оно будет считаться, скажем, 4 дня, но вот сама разработка займёт в 10 раз больше, чем на сях.

mv ★★★★★
()
Ответ на: комментарий от mv

> Конечно! alignment и pack (особенно первый) - очевидная необходимость. deprecated - очень хорошая практика не дать толпе мантейнеров забыть о том, что функция N скоро исчезнет, и пора бы уже свой кусок переделать под новый интерфейс. builtin_expect - не так остро нужен, но в некоторых случаях позволяет объяснить компилятору, что он не прав без вставки ассемблерного чанка.

Собственно говоря, с таким охватом платформ, как у gcc, в opensource уже имеет смысл говорить "язык Си == компилятор gcc". Альтернатив-то всё равно даже близко нет.

Почему это нельзя заменить ассемблером?

yantux
()
Ответ на: комментарий от Manhunt

> Можешь запостить сюда простенький пример, где программа из-под gcc -O2 от добавления builtin_expect ускорялась бы аж на 15%? Скажем, вместо 60 секунд успевала бы отработать за 52? Мне кажется, что получить такой заметный выгрыш можно только на очень извратном коде...

Поиск тегов при разборе плохо структурированного потока. Продукт проприетарный, код не дам :) Да и нет уже его у меня.

mv ★★★★★
()
Ответ на: комментарий от yantux

> Почему это нельзя заменить ассемблером?

Вперёд, заменяй!

mv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.