volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: riYu  
Дата: 10.09.09 17:45
Оценка:
Собственно вопрос.

Если при доступе к переменной я окружаю код вызовами pthread_mutex_lock()/pthread_mutex_unlock(), то нужно ли при ее объявлении использовать квалификатор volatile?

Где-то слышал, что компиляторы гарантируют, что после вызова функции в регистрах не окажется закэшированного значения переменной, но не уверен, так ли это. Да и даже если так, то что тогда произойдет, если pthread_mutex_lock() — inline-функция или макроопределение?

Вообще, судя по http://alenacpp.blogspot.com/2006/04/volatile.html#comment-1976129473176086084 volatile все-таки стоит ставить. В таком случае встречный вопрос — а как быть с GTK в многопоточных приложениях? В отдельном потоке я могу создать виджеты с volatile, вызвать gdk_threads_enter()/gdk_threads_leave(), но GTK-то ничего знать о них не будет...

Просветите, пожалуйста.
volatile gtk threads
Re: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 11.09.09 05:41
Оценка:
Здравствуйте, riYu, Вы писали:

Y>Собственно вопрос.


Y>Если при доступе к переменной я окружаю код вызовами pthread_mutex_lock()/pthread_mutex_unlock(), то нужно ли при ее объявлении использовать квалификатор volatile?


В общем таки желательно.

Y>Где-то слышал, что компиляторы гарантируют, что после вызова функции в регистрах не окажется закэшированного значения переменной, но не уверен, так ли это.


Это так. Но вообще-то если Вы про "закэшированное", то связь с функциями lock/unlock тут иная. Не буду сильно вдаваться в подробности, но есть вопрос переупорядочения машинных команд по желанию процессора, и взятие лока должно быть гарантированно отработано до работы с данными, защищёнными этим локом, а освобождение лока — после такой работы. Думаю, Вам вспомнилось что-то из этой области.

Y> Да и даже если так, то что тогда произойдет, если pthread_mutex_lock() — inline-функция или макроопределение?


А какая нафиг разница? pthread_mutex_lock — нечто, что обязано выполнить операцию захвата мьютекса до начала выполнения кода за ним. Точка. Как оно при этом реализовано — вопрос десятый. А вот то, что компилятор в принципе может не знать про то, что в природе есть какие-то нити (треды) — вопрос серьёзный, и volatile — общий метод сказать ему "чувак, тут может вмешаться кто-то посторонний, так что ты не думай, что можешь сэкономить".

Y>Вообще, судя по http://alenacpp.blogspot.com/2006/04/volatile.html#comment-1976129473176086084 volatile все-таки стоит ставить.


Угумс.

Y> В таком случае встречный вопрос — а как быть с GTK в многопоточных приложениях? В отдельном потоке я могу создать виджеты с volatile, вызвать gdk_threads_enter()/gdk_threads_leave(), но GTK-то ничего знать о них не будет...


А в чём специфика ситуации? Расскажите. С GTK не работал.
The God is real, unless declared integer.
Re: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: ДимДимыч Украина http://klug.org.ua
Дата: 11.09.09 09:39
Оценка:
Здравствуйте, riYu, Вы писали:

Y>Если при доступе к переменной я окружаю код вызовами pthread_mutex_lock()/pthread_mutex_unlock(), то нужно ли при ее объявлении использовать квалификатор volatile?


Эти средства относятся к разным областям и никак не связаны.

Y>Где-то слышал, что компиляторы гарантируют, что после вызова функции в регистрах не окажется закэшированного значения переменной, но не уверен, так ли это.


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

Y>Вообще, судя по http://alenacpp.blogspot.com/2006/04/volatile.html#comment-1976129473176086084 volatile все-таки стоит ставить.


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

Y>В таком случае встречный вопрос — а как быть с GTK в многопоточных приложениях? В отдельном потоке я могу создать виджеты с volatile, вызвать gdk_threads_enter()/gdk_threads_leave(), но GTK-то ничего знать о них не будет...


volatile для переменной — это, грубо говоря, прибивание операций с переменной гвоздями. Будет имееть определенный эффект при синхронизации, но все же синхронизацию принято осуществлять другими методами.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[2]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 11.09.09 10:06
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

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


Y>>Если при доступе к переменной я окружаю код вызовами pthread_mutex_lock()/pthread_mutex_unlock(), то нужно ли при ее объявлении использовать квалификатор volatile?


ДД>Эти средства относятся к разным областям и никак не связаны.


Связаны. Volatile запрещает оптимизацию использования любой переменной в расчёте на участие в её судьбе постороннего агента. Кем этот агент является — сетевой картой, обработчиком прерывания или другой нитью — для компилятора уже неважно. Цитирую стандарт:

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have unknown side effects.


Там дальше ссылка на abstract machine ("в строгом соответствии с ней"), не хочу это приводить, но смысл такой — вне выражения с переменной компилятор обязан потерять всё знание про неё.

Y>>Где-то слышал, что компиляторы гарантируют, что после вызова функции в регистрах не окажется закэшированного значения переменной, но не уверен, так ли это.

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

Это верное утверждение, но для данного вопроса недостаточное.

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


А это не метод синхронизации, это обеспечение её корректности.
The God is real, unless declared integer.
Re[2]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: kvser  
Дата: 11.09.09 10:57
Оценка:
Здравствуйте, netch80, Вы писали:

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


Y>>Собственно вопрос.


Y>>Если при доступе к переменной я окружаю код вызовами pthread_mutex_lock()/pthread_mutex_unlock(), то нужно ли при ее объявлении использовать квалификатор volatile?


N>В общем таки желательно.


прочитайте ветку
Автор: remark
Дата: 27.08.08
Re[3]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 11.09.09 11:45
Оценка:
Здравствуйте, kvser, Вы писали:

Y>>>Собственно вопрос.


Y>>>Если при доступе к переменной я окружаю код вызовами pthread_mutex_lock()/pthread_mutex_unlock(), то нужно ли при ее объявлении использовать квалификатор volatile?


N>>В общем таки желательно.


K>прочитайте ветку
Автор: remark
Дата: 27.08.08


Прочитал. Не вижу ни одного противоречия моим словам. Или это был ответ автору треда?
The God is real, unless declared integer.
Re[4]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: kvser  
Дата: 11.09.09 12:19
Оценка:
Здравствуйте, netch80, Вы писали:

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


Y>>>>Если при доступе к переменной я окружаю код вызовами pthread_mutex_lock()/pthread_mutex_unlock(), то нужно ли при ее объявлении использовать квалификатор volatile?


N>>>В общем таки желательно.


K>>прочитайте ветку
Автор: remark
Дата: 27.08.08


N>Прочитал. Не вижу ни одного противоречия моим словам. Или это был ответ автору треда?


Это ответ и автору тоже.

Я не понял почему-таки желательно?
Re[2]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: riYu  
Дата: 11.09.09 12:24
Оценка:
Спасибо, кажется, до меня начало доходить...

N>А в чём специфика ситуации? Расскажите. С GTK не работал.

Специфика, на мой взгляд, в том, что в GTK всегда работает поток Main loop, обрабатывающий события от GUI, хотя в то же время я могу вмешиваться в его работу из другого потока, окружив свой код вызовами gdk_threads_enter()/gdk_threads_leave() так, что он об этом даже не узнает. Т. е. получается, что внутри GTK в коде никакие volatile не ставятся, и при оптимизации компилятор может поместить некоторые операции обращения к виджетам, которые я изменяю, перед кодом, который захватывает критическую секцию, которую я отпускаю после изменения данных виджетов функцией gdk_threads_leave().

Видимо, я не до конца понимаю, но, на мой взгляд, в итоге может получиться что-то вроде того, что случилось по вышеупомянутой ссылке http://alenacpp.blogspot.com/2006/04/volatile.html#comment-1976129473176086084
Re[3]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: riYu  
Дата: 11.09.09 12:28
Оценка:
Здравствуйте, kvser, Вы писали:
K>прочитайте ветку
Автор: remark
Дата: 27.08.08


Прочитал всю ветку — там чуть ли ни у каждого автора своя теория по поводу того, как в действительности надо поступать и почему. К единому мнению, вроде, так и не пришли.
Re[3]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: ДимДимыч Украина http://klug.org.ua
Дата: 11.09.09 12:42
Оценка:
Здравствуйте, netch80, Вы писали:

N>Связаны. Volatile запрещает оптимизацию использования любой переменной в расчёте на участие в её судьбе постороннего агента. Кем этот агент является — сетевой картой, обработчиком прерывания или другой нитью — для компилятора уже неважно.


Нам ведь нужно целостность переменной обеспечить, а не запретить оптимизацию. Volatile скажет о том, что при каждой записи в переменную произойдет физическая запись по адресу, где эта переменная находится, а при каждом чтении — физическое чтение по этому адресу. Для обеспечения целостности переменной это не является ни необходимым, ни достаточным условием.

N>Цитирую стандарт:


N>

N>An object that has volatile-qualified type may be modified in ways unknown to the implementation or have unknown side effects.


Да, изменение переменной другой нитью можно назвать частным случаем 'modification in ways unknown to the implementation'.

N>Там дальше ссылка на abstract machine ("в строгом соответствии с ней"), не хочу это приводить, но смысл такой — вне выражения с переменной компилятор обязан потерять всё знание про неё.


Это следствие вышеприведенной цитаты.

Y>>>Где-то слышал, что компиляторы гарантируют, что после вызова функции в регистрах не окажется закэшированного значения переменной, но не уверен, так ли это.

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

N>Это верное утверждение, но для данного вопроса недостаточное.


Почему? Можно пример, когда pthread_mutex_lock()/pthread_mutex_unlock() без volatile недостаточно для обеспечения атомарности?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[3]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: ДимДимыч Украина http://klug.org.ua
Дата: 11.09.09 12:49
Оценка:
Здравствуйте, riYu, Вы писали:

Y>Видимо, я не до конца понимаю, но, на мой взгляд, в итоге может получиться что-то вроде того, что случилось по вышеупомянутой ссылке http://alenacpp.blogspot.com/2006/04/volatile.html#comment-1976129473176086084


Автор комментария так и не сообщил, к чему приводило то, что "оптимизатор выносил присвоение за выход из мьютекса". Возможно, в его контексте это не имело никакого значения, и "необходимость volatile" существует только в его воображении. Я, например, какое-то время назад был очень удивлен, увидев в коде, сгенерированном gcc, помещение аргумента функции в регистр уже после вызова функции, а не до него. Оказалось, так и должно быть: особенность архитектуры
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[5]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 11.09.09 12:55
Оценка:
Здравствуйте, kvser, Вы писали:

K>Это ответ и автору тоже.


K>Я не понял почему-таки желательно?


Потому что в один сильно не прекрасный день компиляторы начнут оптимизировать доступ к переменным без volatile, и большому количеству кода настанет северный пушной песец.
The God is real, unless declared integer.
Re[4]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 11.09.09 12:59
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

N>>Связаны. Volatile запрещает оптимизацию использования любой переменной в расчёте на участие в её судьбе постороннего агента. Кем этот агент является — сетевой картой, обработчиком прерывания или другой нитью — для компилятора уже неважно.

ДД>Нам ведь нужно целостность переменной обеспечить, а не запретить оптимизацию. Volatile скажет о том, что при каждой записи в переменную произойдет физическая запись по адресу, где эта переменная находится, а при каждом чтении — физическое чтение по этому адресу. Для обеспечения целостности переменной это не является ни необходимым, ни достаточным условием.

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

ДД>Да, изменение переменной другой нитью можно назвать частным случаем 'modification in ways unknown to the implementation'.


Ну дык ёлы-палы.;)

Y>>>>Где-то слышал, что компиляторы гарантируют, что после вызова функции в регистрах не окажется закэшированного значения переменной, но не уверен, так ли это.

ДД>>>Компиляторы гарантируют, что последствия операций будут такими же, как если бы операции выполнились в том порядке, в каком они присутствуют в коде. Если это не так — значит, баг в компиляторе.
N>>Это верное утверждение, но для данного вопроса недостаточное.
ДД>Почему? Можно пример, когда pthread_mutex_lock()/pthread_mutex_unlock() без volatile недостаточно для обеспечения атомарности?

А при чём тут атомарность? Атомарность-то они обеспечат. А вот отсутствие кэширования — нет.
The God is real, unless declared integer.
Re[5]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: ДимДимыч Украина http://klug.org.ua
Дата: 11.09.09 13:36
Оценка:
Здравствуйте, netch80, Вы писали:

N>А при чём тут атомарность? Атомарность-то они обеспечат. А вот отсутствие кэширования — нет.


Разве lock()/unlock() функции не сбрасывают на SMP "личный" кэш процессора во избежание false sharing? Для запрета всего кэширования применяются другой метод — соответствующая настройка MMU, пользовательскому процессу в общем случае недоступный и ненужный.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[6]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 11.09.09 21:36
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

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


N>>А при чём тут атомарность? Атомарность-то они обеспечат. А вот отсутствие кэширования — нет.


ДД>Разве lock()/unlock() функции не сбрасывают на SMP "личный" кэш процессора во избежание false sharing?


1. Не видел ни одной системы, где бы эти функции сбрасывали кэш. Что за безумная идея? Откуда Вы вообще её взяли? Кэш памяти в процессоре — штука достаточно умная, чтобы не требовать общего сброса (безумно дорогого, кстати) на малейший чих.

2. А при чём тут вообще кэширование памяти в процессоре? Весь тред посвящён кэшированию значения переменной компилятором в другом месте (как правило, в регистре). Например, в коде вида

  int a, b, c;
  b = a;
  unlock(m);
  lock(m);
  c = a;


компилятор может закэшировать a в регистре между её чтениями, или заменить второе присвоение на c=b, или сделать любое другое действие подобного типа. И без volatile ему никто это не запретит.
The God is real, unless declared integer.
Re[7]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: ДимДимыч Украина http://klug.org.ua
Дата: 11.09.09 22:59
Оценка:
Здравствуйте, netch80, Вы писали:

N>1. Не видел ни одной системы, где бы эти функции сбрасывали кэш. Что за безумная идея? Откуда Вы вообще её взяли? Кэш памяти в процессоре — штука достаточно умная, чтобы не требовать общего сброса (безумно дорогого, кстати) на малейший чих.


Про общий сброс всех кэшей на малейший чих я не говорил. А проблема false sharing на SMP присутствует (если у каждого ядра есть как минимум один свой кэш), но к данной дискуссии, оказывается, отношения не имеет

N>2. А при чём тут вообще кэширование памяти в процессоре?


Вот и я думаю — при чем здесь кэширование в процессоре?

N>Весь тред посвящён кэшированию значения переменной компилятором в другом месте (как правило, в регистре). Например, в коде вида


N>
N>  int a, b, c;
N>  b = a;
N>  unlock(m);
N>  lock(m);
N>  c = a;
N>


N>компилятор может закэшировать a в регистре между её чтениями, или заменить второе присвоение на c=b, или сделать любое другое действие подобного типа. И без volatile ему никто это не запретит.


Для ядра пишут вот что: http://kernel.org/doc/Documentation/volatile-considered-harmful.txt. Уверен, что в userspace ситуация не сильно отличается. Если же все-таки существуют какие-нибудь более-менее официальные рекомендации по использованию volatile для защиты данных в мультинитевых приложениях, а не только домыслы анонимных комментаторов, буду благодарен за ссылки.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[8]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 12.09.09 09:11
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

N>>компилятор может закэшировать a в регистре между её чтениями, или заменить второе присвоение на c=b, или сделать любое другое действие подобного типа. И без volatile ему никто это не запретит.

ДД>Для ядра пишут вот что: http://kernel.org/doc/Documentation/volatile-considered-harmful.txt.

Спасибо, отличный пример бреда сивой кобылы в лунную ночь. "Volatile плохо, потому что не позволяет разумную оптимизацию". То, что если оно позволит разумную — позволит и неразумную, тут не вспоминается, и никакие down(), mutex_lock() и прочие этому не помешают — если компилятор туп, то он однородно и равномерно туп. Именно это и происходит с GCC.

И в этой статье "забыли" упомянуть то, как оно реально в Linux лечится. А лечится — разделением на функции, между которыми оптимизация доступа к переменной уже не производится.

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

ДД> Уверен, что в userspace ситуация не сильно отличается. Если же все-таки существуют какие-нибудь более-менее официальные рекомендации по использованию volatile для защиты данных в мультинитевых приложениях, а не только домыслы анонимных комментаторов, буду благодарен за ссылки.


Я такого не видел, но я работаю только с GCC, для которого достаточно (AFAIR) вызова функции.
The God is real, unless declared integer.
Re[9]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: ДимДимыч Украина http://klug.org.ua
Дата: 12.09.09 09:27
Оценка:
Здравствуйте, netch80, Вы писали:

N>Спасибо, отличный пример бреда сивой кобылы в лунную ночь. "Volatile плохо, потому что не позволяет разумную оптимизацию".


Короче, все понятно Вести дальнейшую дискуссию считаю нецелесообразным.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[10]: volatile - нужен ли при pthread_mutex_lock() и в GTK
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 12.09.09 09:35
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

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


N>>Спасибо, отличный пример бреда сивой кобылы в лунную ночь. "Volatile плохо, потому что не позволяет разумную оптимизацию".


ДД>Короче, все понятно :down: Вести дальнейшую дискуссию считаю нецелесообразным.


Up to you. Залагаться на линуксовую документацию при том, какой "дефолт" вызвала всего лишь попытка перейти на GCC 4.4 — действительно, тут дискутировать уже не о чем.
The God is real, unless declared integer.
Re[4]: volatile - нужен ли при pthread_mutex_lock() и в GTK?
От: Zhendos  
Дата: 12.09.09 12:23
Оценка: 4 (1)
Здравствуйте, ДимДимыч, Вы писали:

ДД>Почему? Можно пример, когда pthread_mutex_lock()/pthread_mutex_unlock() без volatile недостаточно для обеспечения атомарности?


например:

#include <pthread.h>

  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  static int acquires_count = 0;

  int
  trylock()
  {
    int res;

    res = pthread_mutex_trylock(&mutex);
    if (res == 0)
      ++acquires_count;

    return res;
  }


подробности можно найти здесь:
http://lkml.org/lkml/2007/10/24/673
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.