Как завершать программу?
От: Linuxoid  
Дата: 29.11.04 12:43
Оценка:
Где-то читал, что такой код — худшее что можно сделать для выхода из программы (типа расходуется процессорное время на постоянный опрос, подгружается переменная из памяти..). А как делать красиво/правильно?
Кстати, нужен ли здесь модификатор volatile?

volatile sig_atomic_t TerminationFlag = 0;


// main loop
void run ()
{
  //...
  while (!TerminationFlag)
  {
     // делаем че-нибудь умное
     // ...
  }
}
Re: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 13:06
Оценка:
Linuxoid wrote:

> Где-то читал, что такой код — худшее что можно сделать для выхода из программы (типа расходуется процессорное время на постоянный опрос, подгружается переменная из памяти..). А как делать красиво/правильно?


Ты, наверное, читал про spin blocking (когда поток ждет, постоянно опрашивая переменную) — это действительно, не очень хорошая штука.

Здесь же, если прога синглтредовая, этот способ правильный. Если же прога малитредовая, то тебе по-любому нужно будет защитить флаг мьютексом из-за memory visibility issues.

> Кстати, нужен ли здесь модификатор volatile?


Только в случае, когда TerminationFlag выставляет signal handler.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re: Как завершать программу?
От: TheBeard Россия  
Дата: 29.11.04 13:07
Оценка:
Всё это сильно зависит от логики программы. Можно, например,
воспользоваться семафором, запустить поток и ждать его завершения и т.д.
Иначе говоря, нужно правильно выделить объект синхронизации.

Linuxoid wrote:

> Где-то читал, что такой код — худшее что можно сделать для выхода из

> программы (типа расходуется процессорное время на постоянный опрос,
> подгружается переменная из памяти..). А как делать красиво/правильно?
Posted via RSDN NNTP Server 1.9 delta
Re: Как завершать программу?
От: Murr Россия  
Дата: 29.11.04 17:15
Оценка:
Здравствуйте, Linuxoid, Вы писали:

L>Где-то читал, что такой код — худшее что можно сделать для выхода из программы (типа расходуется процессорное время на постоянный опрос, подгружается переменная из памяти..). А как делать красиво/правильно?


Как минимум надо делать sched_yield, когда нечего делать умного (в смысле, что цикл холостой).
А еще лучше вместо (!TerminationFlag) написать какой-нибудь аналог wait_event.

L>Кстати, нужен ли здесь модификатор volatile?


Нужен. При этом имей в виду, что если ты не прописываешь memory барьеры, то
изменения переменных в SMP на втором процессоре могут быть видны в другом порядке.
Re[2]: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 17:35
Оценка:
Murr wrote:

[]

> L>Кстати, нужен ли здесь модификатор volatile?

>
> Нужен. При этом имей в виду, что если ты не прописываешь memory барьеры, то
> изменения переменных в SMP на втором процессоре могут быть видны в другом порядке.

Только если переменная изменяется обработчиком сигнала. В противном случае volatile как мертвому припарка.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[3]: Как завершать программу?
От: Murr Россия  
Дата: 29.11.04 17:49
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Murr wrote:


ME>[]


>> L>Кстати, нужен ли здесь модификатор volatile?

>>
>> Нужен. При этом имей в виду, что если ты не прописываешь memory барьеры, то
>> изменения переменных в SMP на втором процессоре могут быть видны в другом порядке.

ME>Только если переменная изменяется обработчиком сигнала. В противном случае volatile как мертвому припарка.


volatile — это модификатор, призванный (для GCC/i386) предотвратить кэширование переменной в регистрах. Соответственно, без него изменение переменной в обработчике сигнала или в другой нити не будет видно.

Если переменная может изменяться только как побочный эффект вызова функций в теле цикла, то — да, volatile необязателен, т.к. вызов функции в GCC — это глобальный барьер. Но, если честно, я не вижу в последнем варианте никакого смысла, в большинстве случаев, с которыми я сталкивался в аналогичной ситуации флажок выхода устанавливается асинхронно (да и настолько тривиальный это случай, что вопрос об этом был бы глупым).
Re[4]: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 18:17
Оценка:
Murr wrote:

> Здравствуйте, MaximE, Вы писали:

>
> ME>Murr wrote:
>
> ME>[]
>
>>> L>Кстати, нужен ли здесь модификатор volatile?
>>>
>>> Нужен. При этом имей в виду, что если ты не прописываешь memory барьеры, то
>>> изменения переменных в SMP на втором процессоре могут быть видны в другом порядке.
>
> ME>Только если переменная изменяется обработчиком сигнала. В противном случае volatile как мертвому припарка.
>
> volatile — это модификатор, призванный (для GCC/i386) предотвратить кэширование переменной в регистрах.

Поведение с и с++ программ рассматривается стандартом в терминах абстрактной машины. Предполагается, что состояние машины изменяется в sequence points. sequence points — это вызовы ф-ций. После sequence points компилятор не может делать никаких предположений о состояние программы и должен заново считывать из памяти значения переменных. Что делает volotile — так это то, что он вставляет sequence point перед обращением к переменной, заставляя компилятор считывать значение из памяти, даже если после предыдущего обращения не было вызова ф-ции.

> Соответственно, без него изменение переменной в обработчике сигнала


С точки зрения компилятора, асинхронная обработка сигнала — это не sequence point, и именно поэтому нужен volatile для переменных, которые будет изменять асинхронный обработчик сигнала и значения которых будут считывать не из обработчика.

> или в другой нити не будет видно.


А вот здесь volatile уже никак не поможет, хотя легко может сконфузить неискушенного читателя кода. Здесь нужен memory barrier. Кстати, именно потому, что в POSIX memory barriers предоставлены как функции (читать — sequence points), POSIX ни требует, ни рекомендует использовать ключевое слово volatile для переменных, разделяемых между потоками.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[5]: Как завершать программу?
От: Murr Россия  
Дата: 29.11.04 18:40
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Поведение с и с++ программ рассматривается стандартом в терминах абстрактной машины.


Поведение C и C++ программ определяется реализацией компилятора и особенностями аппаратуры.

>Что делает volotile — так это то, что он вставляет sequence point перед обращением к переменной, заставляя компилятор считывать значение из памяти, даже если после предыдущего обращения не было вызова ф-ции.


Чем это отличается от "запрета кэширования"? Или это вы не спорите, а пространно рассуждаете?

ME>С точки зрения компилятора, асинхронная обработка сигнала — это не sequence point, и именно поэтому нужен volatile для переменных, которые будет изменять асинхронный обработчик сигнала и значения которых будут считывать не из обработчика.


Да, он нужен именно для того, чтобы избежать кэширования переменных, о чем я и писал. О чем тут спорим?

>> или в другой нити не будет видно.


ME>А вот здесь volatile уже никак не поможет, хотя легко может сконфузить неискушенного читателя кода.


Еще раз повторяю: в GCC/i386 поможет и никого это не смущает.

>Здесь нужен memory barrier.Кстати, именно потому, что в POSIX memory barriers предоставлены как функции (читать — sequence points), POSIX ни требует, ни рекомендует использовать ключевое слово volatile для переменных, разделяемых между потоками.


У вас, похоже, какое-то другое определение memory барьеров. Вообще, я под ними понимаю то, как понимается в Linux: барьер памяти — это указание процессору не переупорядочивать чтение или запись в память через данную точку потока управления. Указание компилятору (GCC) не кэшировать переменную через данную точку называется compiler barrier и достигается либо явным asm("" :::"memory") либо использованием volatile.


ME>--

ME>Maxim Yegorushkin
Re[5]: Как завершать программу?
От: Murr Россия  
Дата: 29.11.04 18:43
Оценка:
Здравствуйте, MaximE, Вы писали:

>Кстати, именно потому, что в POSIX memory barriers предоставлены как функции


Жуть какая. Представляю как будет тормозить программа, которая для каждого
барьера вызывает функцию (фактически херит конвейер и делает кучу ненужных
глупостей).
Re[6]: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 18:58
Оценка:
Murr wrote:

> Здравствуйте, MaximE, Вы писали:

>
>> Кстати, именно потому, что в POSIX memory barriers предоставлены как функции
>
> Жуть какая. Представляю как будет тормозить программа, которая для каждого
> барьера вызывает функцию (фактически херит конвейер и делает кучу ненужных
> глупостей).

Here is what we can assume is safe to do when using POSIX (quoting [Butenhof]):
1. Whatever memory values a thread can see when it creates a new thread can also be seen by the new thread once it starts. Any data written to memory after the new thread is created may not necessarily be seen by the new thread, even if the write occurs before the thread starts.
2. Whatever memory values a thread can see when it unlocks a mutex (leaves a synchronized method or block in Java), either directly or by waiting on a condition variable (calling wait in Java), can also be seen by any thread that later locks the same mutex. Again, data written after the mutex is unlocked may not necessarily be seen by the thread that locks the mutex, even if the write occurs before the lock.
3. Whatever memory values a thread can see when it terminates, either by cancellation, returning from its run method, or exiting, can also be seen by the thread that joins with the terminated thread by calling join on that thread. And, of course, data written after the thread terminates may not necessarily be seen by the thread that joins, even if the write occurs before the join.
4. Whatever memory values a thread can see when it signals or broadcasts a condition variable (calling notify in Java) can also be seen by any thread that is awakened by that signal or broadcast. And, one more time, data written after the signal or broadcast may not necessarily be seen by the thread that wakes up, even if it occurs before it awakens.


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[6]: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 19:12
Оценка:
Murr wrote:

[]

> Да, он нужен именно для того, чтобы избежать кэширования переменных, о чем я и писал. О чем тут спорим?


Я не спорил, просто написал, что значит это "кэширование" и когда тот "кэш" становится невалидным — после sequence point.

>>> или в другой нити не будет видно.

>
> ME>А вот здесь volatile уже никак не поможет, хотя легко может сконфузить неискушенного читателя кода.
>
> Еще раз повторяю: в GCC/i386 поможет и никого это не смущает.

Это не так (- спорю ). Поиск в google groups по "volatile memory visibility" выдаст тебе море информации.

>> Здесь нужен memory barrier.Кстати, именно потому, что в POSIX memory barriers предоставлены как функции (читать — sequence points), POSIX ни требует, ни рекомендует использовать ключевое слово volatile для переменных, разделяемых между потоками.

>
> У вас, похоже, какое-то другое определение memory барьеров. Вообще, я под ними понимаю то, как понимается в Linux: барьер памяти — это указание процессору не переупорядочивать чтение или запись в память через данную точку потока управления.

Это не так. Определение барьеров (точнее их семантики) от нашей любимой компании: http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/Synchro_88127404-a394-403f-a289-d61c45ab81d5.xml.asp

> Указание компилятору (GCC) не кэшировать переменную через данную точку называется compiler barrier и достигается либо явным asm("" :::"memory") либо использованием volatile.


Это — да.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[7]: Как завершать программу?
От: Murr Россия  
Дата: 29.11.04 19:27
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Это не так (- спорю ). Поиск в google groups по "volatile memory visibility" выдаст тебе море информации.


Бррр. Давайте по порядку. volatile приводит к некэшированию переменной в регистрах.
Я не знаю, что написано в группах на эту тему, вероятно, про отложенную процессорную запись.
Это — отдельная песня и в этом нет ничего страшного, поскольку единственное, в чем один процессор
видит работу другого — это порядок обновления данных в общей памяти (и ни в коем случае не время)
и именно для этого и нужны барьеры — для форсирования порядка записи в память, но ни в коем случае
не сбросе буферов записи.

ME>Это не так.


Что именно не так? Я сказал, что в Linux используется такое определение барьеров памяти (оно дано Rusty Russel в документации к ядру). Вы с этим спорите или чем-то другим?

> Определение барьеров (точнее их семантики) от нашей любимой компании: http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/Synchro_88127404-a394-403f-a289-d61c45ab81d5.xml.asp


По ссылке не нашел ничего про барьеры, но, насколько я помню, у MS было точно такое же определение барьеров — точка, через которую не могут быть переупорядочены операции чтения или записи.
Re[7]: Как завершать программу?
От: Murr Россия  
Дата: 29.11.04 19:30
Оценка:
Здравствуйте, MaximE, Вы писали:

Any data written to memory after the new thread is created may not necessarily be seen by the new thread, even if the write occurs before the thread starts.


То есть с точки зрения POSIX одна нить всегда должна форсировать видимость изменения данных на других процессорах? Это уже слегка напоминает не shared memory, а обмен сообщениями.

Я не спорю, что при доступе к shared memory нужна синхронизация, но не до такой же степени.
Re[8]: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 19:42
Оценка:
Murr wrote:

> Здравствуйте, MaximE, Вы писали:

>
> ME>Это не так (- спорю ). Поиск в google groups по "volatile memory visibility" выдаст тебе море информации.
>
> Бррр. Давайте по порядку. volatile приводит к некэшированию переменной в регистрах.
> Я не знаю, что написано в группах на эту тему, вероятно, про отложенную процессорную запись.

Примерно. Что volatile связывает руки только компилятору, но не запрещает процессору переупорядочивать инструкции.

> Это — отдельная песня и в этом нет ничего страшного, поскольку единственное, в чем один процессор

> видит работу другого — это порядок обновления данных в общей памяти (и ни в коем случае не время)
> и именно для этого и нужны барьеры — для форсирования порядка записи в память, но ни в коем случае
> не сбросе буферов записи.
>
> ME>Это не так.

То, что на x86 volatile чем то может помочь. http://rsdn.ru/Forum/?mid=902621
Автор: MaximE
Дата: 17.11.04


> Что именно не так? Я сказал, что в Linux используется такое определение барьеров памяти (оно дано Rusty Russel в документации к ядру). Вы с этим спорите или чем-то другим?


Не знаком с его определением.

>> Определение барьеров (точнее их семантики) от нашей любимой компании: http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/Synchro_88127404-a394-403f-a289-d61c45ab81d5.xml.asp

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

Мемори барьер в POSIX — это точка, после которой все операции над памятью, выполненные потоком, становятся видны другим потокам (release semantics из ссылки с мс). Об эффекте этих точек как раз и пишет процитированный Бутенхоф.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[8]: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 19:52
Оценка:
Murr wrote:

[]

Моя позиция такова — volatile бесполезен в малтитредовых программах из-за того, что он не обеспечивает никаких гарантий memory visibility. Конкретно для x86 — архитектура такова, что там memory visibility issues не играют никакой роли, так как состояние памяти для всех потоков всегда когерентно и volatile не играет никакой роли.

Есть один вырожденный случай без sequence points, где volatile на x86 играет роль:

volatile int x;
while(!x) /*do nothing*/;


Но такой код всегда является ошибкой — непереносим и бесполезно расходует ресурсы процессора.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[8]: Как завершать программу?
От: MaximE Великобритания  
Дата: 29.11.04 19:58
Оценка:
Murr wrote:

> Здравствуйте, MaximE, Вы писали:

>
>

Any data written to memory after the new thread is created may not necessarily be seen by the new thread, even if the write occurs before the thread starts.

>
> То есть с точки зрения POSIX одна нить всегда должна форсировать видимость изменения данных на других процессорах? Это уже слегка напоминает не shared memory, а обмен сообщениями.
>
> Я не спорю, что при доступе к shared memory нужна синхронизация, но не до такой же степени.

MS говорит то же самое:

An operation has acquire semantics if other processors will always see its effect before any subsequent operation's effect. An operation has release semantics if other processors will see every preceding operation's effect before the effect of the operation itself.


Т.е. один процессор заставляет другие процессоры наблюдать эффекты своих операций.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[9]: Как завершать программу?
От: Murr Россия  
Дата: 30.11.04 10:12
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Murr wrote:


ME>[]


ME>Моя позиция такова — volatile бесполезен в малтитредовых программах из-за того, что он не обеспечивает никаких гарантий memory visibility. Конкретно для x86 — архитектура такова, что там memory visibility issues не играют никакой роли, так как состояние памяти для всех потоков всегда когерентно и volatile не играет никакой роли.


Во-первых, насчет когерентности памяти на x86 — не совсем верно. Память на x86 не когерентна в полном смысле этого слова, поскольку процессор использует write buffering. Но, запись не может откладываться до бесконечности — FIFO буфер выпихивается в память в свободные циклы шины (асинхронно).

Во-вторых, вы пытаетесь представить проблему не так, какой она в реальности является. Не существует такой проблемы, как синхронизация представления памяти — все оптимизации в этой области выполняет процессор в слабо отложенной форме, но тем не менее некоторые процессоры могут агрессивно изменять порядок чтенния и записи памяти (как DEC Alpha), для чего и существуют барьеры.

ME>
ME>volatile int x;
ME>while(!x) /*do nothing*/;
ME>


ME>Но такой код всегда является ошибкой — непереносим и бесполезно расходует ресурсы процессора.


IMHO, этот код корректен. На какой архитектуре такой код не будет работать?

P.S. Если я заблуждаюсь, то буду благодарен, если подкинете ссылку, где подобное разжевывается подетальнее.
Re[9]: Как завершать программу?
От: Murr Россия  
Дата: 30.11.04 10:25
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Примерно. Что volatile связывает руки только компилятору, но не запрещает процессору переупорядочивать инструкции.


Так какая вам разница в каком порядке будет виден флаг?

Если есть какая-то зависимость по данным, то — да, барьеры нужны, об этом я написал в самом первом своем сообщении.

>> Это — отдельная песня и в этом нет ничего страшного, поскольку единственное, в чем один процессор

>> видит работу другого — это порядок обновления данных в общей памяти (и ни в коем случае не время)
>> и именно для этого и нужны барьеры — для форсирования порядка записи в память, но ни в коем случае
>> не сбросе буферов записи.
>>
>> ME>Это не так.

ME>То, что на x86 volatile чем то может помочь. http://rsdn.ru/Forum/?mid=902621
Автор: MaximE
Дата: 17.11.04


По вашей ссылке написано, что volatile и memory барьеры — это разные вещи. Я с этим никогда не спорил.
Собственно я и называл их compiler barriers и memory barriers. Про синхронное представление памяти на x86, вы, опять же, IMHO, заблуждаетесь. Существует синхронизация кэшей (MESI) на частоте шины, но это слишком медленно, поэтому у x86 процессоров есть write buffers. Тем не менее, "со временем" буферы сбрасываются (и не только на x86).

ME>Не знаком с его определением.


А я вот только с ним и знаком. Не считая ряда документов, которые нарыл в Google в свое время, которые не противоречили моим представлениям.

ME>Мемори барьер в POSIX — это точка, после которой все операции над памятью, выполненные потоком, становятся видны другим потокам (release semantics из ссылки с мс). Об эффекте этих точек как раз и пишет процитированный Бутенхоф.


IMHO, единственная непривилегированная операция на x86, которая приводит такому эффекту — это любая операция с префиксом lock, которая ждет цикла шины, полностью выталкивает write buffers, потом делает подпрефиксную операцию с памятью на шине. Т.е. это жутко тормозно.

А главное, что в модели процессора с цивилизованным (слабо отложенным) write buffering это не имеет смысла, поскольку один процессор видит работу другого только в порядке изменения данных в памяти (но не в коем случае не во времени).
Re[10]: Как завершать программу?
От: MaximE Великобритания  
Дата: 30.11.04 11:53
Оценка:
Murr wrote:

> ME>Моя позиция такова — volatile бесполезен в малтитредовых программах из-за того, что он не обеспечивает никаких гарантий memory visibility. Конкретно для x86 — архитектура такова, что там memory visibility issues не играют никакой роли, так как состояние памяти для всех потоков всегда когерентно и volatile не играет никакой роли.

>
> Во-первых, насчет когерентности памяти на x86 — не совсем верно. Память на x86 не когерентна в полном смысле этого слова, поскольку процессор использует write buffering. Но, запись не может откладываться до бесконечности — FIFO буфер выпихивается в память в свободные циклы шины (асинхронно).

Допускаю, что я здесь слишком упростил.

> Во-вторых, вы пытаетесь представить проблему не так, какой она в реальности является. Не существует такой проблемы, как синхронизация представления памяти — все оптимизации в этой области выполняет процессор в слабо отложенной форме, но тем не менее некоторые процессоры могут агрессивно изменять порядок чтенния и записи памяти (как DEC Alpha), для чего и существуют барьеры.


Проблема называется memory visibility, решается при помощи memory barriers.

[]

> P.S. Если я заблуждаюсь, то буду благодарен, если подкинете ссылку, где подобное разжевывается подетальнее.


deja.com -> "volatile memory visibility"

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[11]: Как завершать программу?
От: Murr Россия  
Дата: 30.11.04 12:21
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>deja.com -> "volatile memory visibility"


Я вообще-то ссылку попросил. Если нечего было дать, то зачем вообще было что-либо писать?
Ну да Бог с ним... я пошел по первой ссылке, с сообщением упомянутого Батенхофа.

>> Во-вторых, вы пытаетесь представить проблему не так, какой она в реальности является. Не существует такой проблемы, как синхронизация представления памяти — все оптимизации в этой области выполняет процессор в слабо отложенной форме, но тем не менее некоторые процессоры могут агрессивно изменять порядок чтенния и записи памяти (как DEC Alpha), для чего и существуют барьеры.


ME>Проблема называется memory visibility, решается при помощи memory barriers.


По вашей же ссылке:
On a high-performance modern SMP system, memory transactions are effectively 
pipelined. A memory barrier does not "flush to memory", but rather inserts 
barriers against reordering of operations in the memory pipeline. For this 
to have any meaning across processors there must be a critical sequence on 
EACH end of a transaction that's protected by appropriate memory barriers.


Есть у него и по поводу GCC.
If you have a way to generate inline barriers (or on a machine that doesn't 
require barriers), and you wish to build your own low-level protocol that 
doesn't rely on synchronization (e.g., a mutex), then your compiler might 
require that you use volatile -- but this is unspecified by either ANSI C 
or POSIX. (That is, ANSI C doesn't recognize parallelism and therefore 
doesn't apply, while POSIX applies no specific additional semantics to 
"volatile".) So IF you need volatile, your code is inherently nonportable.


Ну и напоследок:
A corollary is that if you wish to write portable code, you have no need for 
volatile. (Or at least, if you think you do have a need, it won't help you 
any.)

Реально проблема переносимости должна решаться на дополнениях к существующим стандартам C и C++.
Если volatile не означает ничего с точки зрения стандарта, то не проблема GCC в том, что он трактует
volatile несколько шире.
Re[12]: Как завершать программу?
От: MaximE Великобритания  
Дата: 30.11.04 17:44
Оценка:
Murr wrote:

[]

> ME>Проблема называется memory visibility, решается при помощи memory barriers.

>
> По вашей же ссылке:
>
> On a high-performance modern SMP system, memory transactions are effectively
> pipelined. A memory barrier does not "flush to memory", but rather inserts
> barriers against reordering of operations in the memory pipeline. For this
> to have any meaning across processors there must be a critical sequence on
> EACH end of a transaction that's protected by appropriate memory barriers.
>


Что это опровергает или подтверждает? Как это относится к volatile?

> Есть у него и по поводу GCC.


[]

> Реально проблема переносимости должна решаться на дополнениях к существующим стандартам C и C++.

> Если volatile не означает ничего с точки зрения стандарта, то не проблема GCC в том, что он трактует
> volatile несколько шире.

Каким именно gcc трактует volatile шире?

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[13]: Как завершать программу?
От: Murr Россия  
Дата: 30.11.04 19:22
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Murr wrote:


ME>[]


>> ME>Проблема называется memory visibility, решается при помощи memory barriers.

>>
>> По вашей же ссылке:
>>
>> On a high-performance modern SMP system, memory transactions are effectively
>> pipelined. A memory barrier does not "flush to memory", but rather inserts
>> barriers against reordering of operations in the memory pipeline. For this
>> to have any meaning across processors there must be a critical sequence on
>> EACH end of a transaction that's protected by appropriate memory barriers.
>>


ME>Что это опровергает или подтверждает? Как это относится к volatile?


Вы сказали (см.выше), что есть какая-то проблема "memory visibility", которая решается барьерами. Как это следует из моего сообщения и процитированного сообщения уважаемого иноземного сэра memory барьеры решают ровно одну проблему — relaxed memory ordering.

К volatile это никак не относится (и не планировалось, чтобы относилось).

>> Есть у него и по поводу GCC.


ME>Каким именно gcc трактует volatile шире?


Наверное, я не совсем правильно сказал "GCC трактует шире". Linux kernel трактует volatile как переменную, для форсирования видимости которой не нужен compiler barrier. Тот код, который не использует жестких compiler+memory барьеров, обычно либо:
a) полностью отдает данные на откуп компилятору и процессору (что меня и смутило в рассуждениях о проблеме memory visibility). Возможно, считается, что в какой-то момент форсируется запись в память (например, при возникновении аппаратного прерывания), но мне почему-то кажется, что попросту нет таких распространенных процессоров общего назначения, которые могут до бесконечности задерживать запись в память по своей инициативе (случай нечестного арбитража шины не рассматривается). IA32, насколько я знаю, сбрасывает write buffers в холостые циклы шины. Впрочем, этот вопрос интересный и я попробую найти что-нибудь в google на эту тему.
b) либо использует модификатор volatile при объявлении переменных
c) либо форсирует compiler barrier через asm("":::"memory")
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.