Здравствуйте, alex_public, Вы писали:
_>>>Да, всё верно. И я по прежнему утверждаю, что ты тогда сказал чушь, и значение global_var в том коде будет вполне определённым (одним из двух) даже в случае многопоточности. _>·>И на каком основании ты так считаешь? _>На том основание, что на всем железе инструкция записи регистра в память атомарна,
Это закон природы?
_>а присвоение переменной типа int скомпилируется именно в такую инструкцию.
А это на каком основании?
_>>>- volatile в том примере кода был не нужен, т.к. не было мест, где компилятор мог бы применить _>·>Подкрепи свои слова стандартом. _>Там нет кода, который изменил бы своё поведение, в случае "кэширования" значения переменной в регистре.
Это по коду не видно. Там вызывается некий метод process который может тоже делать хз что, а компилятор может видеть и этот код и принимать свои решения.
_>>>опасную оптимизацию _>·>Вот какой у тебя клёвый надёжный код, что оптимизации компилятора считаешь опасными! _>Ты похоже как-то плохо умеешь читать текст на русском языке. Я же однозначно написал, что как раз в моём примере такого кода нет. А вот если бы был, то тогда и модификатор volatile появился бы.
Я не о конкретно данной ситуации. Меня повеселил факт, что оптимизации в принципе можно считать опасными.
_>>>- atomic_thread_fence в том примере кода не нужен, т.к. вообще нет обращения к другим областям памяти _>>>Ещё комментарии будут? ))) _>·>atomic_thread_fence упорядочивает не "другие области", а обращения к памяти. Если у тебя более одного обращения из разных тредов, пусть даже к одной области — то у тебя уже могут быть вариации. _>Перестановку обращений к одной области памяти тупо недопустит сам компилятор, т.к. это изменит поведение кода. )))
Компилятор, если ему не сказано явно, не учитывает поведение других потоков, поэтому он может допускать всё что угодно, что не противоречит наблюдаемым эффектам однопоточного исполнения данной части кода.
_> Если конечно речь не идёт об оптимизациях типа объединения двух последовательных записей — это возможная оптимизация и если она вдруг тебе мешает, то ты можешь отключить её с помощью volatile.
Ох.. Повторяюсь. Записи оптимизировать может не только компилятор, но и процессор. А процессор про volatile ничего не знает.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, alex_public, Вы писали:
_>А я нигде и не говорил о многозадачности/многопоточности. Я говорил о важности модификатора volatile для низкоуровневого программирования.
Ну вот это вот — типичная подмена понятий. Изначально делалось сильное утверждение про то, что volatile появился в C ради поддержки многозадачных ОС, которые и были его основным применением.
А теперь мы видим, что единственное приличное применение volatile — это memory-mapped HW, которое строго ортогонально многозадачности оси.
Даже во вполне однозадачной ОС уровня MS-DOS работа с регистрами оборудования, отображёнными в память, будет требовать volatile, и, если я правильно понимаю принцип барьеров, то они тут неприменимы.
S>>Про перебор i в цикле я примера увы, не понял. С учётом того, что i у нас никуда не отображена, мы крутим регистр процессора. S>>Скорее всего, речь идёт о трудноуловимой баге — программист пытается выполнить задержку ненадёжным способом. _>Да, это именно задержка. И вполне себе надёжная. Т.е. понятно что аппаратный таймер лучше, но не во всех случаях его можно применить.
Нет, это ненадёжная задержка. Впендюрив сюда volatile, программист запрещает "устраняющие" оптимизации компилятору.
Но, во-первых, это никак не влияет на выбор размещения переменной, поэтому величина задержки получается произвольной даже в пределах одной аппаратуры — то ли будет выполнен сброс в память, то ли обойдёмся регистром. Какова будет разница в величине задержки?
Во-вторых, даже в пределах одной аппаратуры у нас может плавать тактовая частота, и скорость исполнения этого цикла будет меняться в разы.
Во-третьих, нет никакой гарантии, что во время цикла не будет выполнено вытеснение. Тогда можно запросто получить задержку на порядки больше, чем ожидалось.
Даже если бы у меня были выполнены необходимые предусловия, типа "это platform-specific code, и я знаю величину тактовой частоты", я бы не рискнул писать этот код в таком виде — он же выглядит как переносимый!
Там должно быть volatile asm(""), и дальше фигачим ровно те инструкции, тайминг которых я проверял в лаборатории.
_>Для полноценного спинлока тебе не хватит ни volatile, ни fences. Для него необходимы уже атомарные операции типа CAS или аналоги, поддерживаемые процессором.
Ну, тут мне не хватает квалификации для полноценного разговора. В рамках нашей дискуссии достаточно сказать, что volatile для спинлока бесполезен.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vdimas, Вы писали: V>Было бы хоть у кого-то, спор давно был бы исчерпан.
Статья Джонсона 1981 года достаточно подробно описывает state of the art на тот момент. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.3512
Там никакого volatile нет, да и оптимизации на тот момент были рудиментарными.
Всё интересное случилось между 1982 и 1985 — как раз комитет начал стандартизацию.
Авторы спецификации специально отмечали, что некоторые вещи, типа enum и void, были придуманы до начала стандартизации, а вот volatile и const были предложены в рамках процесса.
Понятное дело, что авторы поддерживали общение с комьюнити. Разработка компиляторов тогда была, похоже, более-менее прибыльным занятием — в середине восьмидесятых лицензия на компилятор C стоила 500-600 долларов, что овердофига.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vdimas, Вы писали:
V>>>А как быть с контролем выравнивания? _>>Эм, а что там с выравниваем? Я подробно с RISC-V не разбирался, так что не в курсе про какие-то особенности. V>АМО-операции генерят исключение, если адрес не выровнен. V>ИМХО, важная особенность.
А обычные операции не умеют?
_>>Нуу в потенциале RISC-V может стать очень интересной и популярной вещью. Приблизительно тем же самым, чем сейчас является ядро Линуха в ПО, только в мире железа. V>ХЗ, операционка — это, всё-таки, более объемлющее понятие, а RISC — малость узкое.
Да не важно RISC это или что-то другое. Главное что это куча халявных (причём под реально открытой лицензией, а не всякими убогими GPL) IP-ядер и даже готовых SoC'ов https://github.com/riscv/riscv-cores-list. Причём вполне современной архитектуры. И под них есть (благодаря унифицированной архитектуре) работающие из коробки gcc, Линух и т.п.
_>>Однако сейчас это всё ещё по сути игрушка энтузиастов или стартапов V>Я тоже в первый раз в этом обсуждении обратил на эту разработку внимание (хоть какая-то польза, ы-ы-ы), и мне она тоже понравилась тем, что систему команд разрабатывают раньше конкретного чипа (или его описания в терминах вентилей).
Не, я слышал раньше, из мира fpga. ) Но при этом так ни разу и не лазил во внутренности. И собственно и сейчас ещё пока не планирую — подожду, пока она реально станет чем-то серьёзным. А то если всё интересное изучать подробно, то никакого времени не хватит. )))
V>Обычно, эти вещи шли одновременно, т.е. порадовало отделение мух от котлет. V>Не помешал бы аналогичный проект для VLIW.
А ещё лучше открытое ядро современного GPU. Но тут что-то совсем тухло всё.
Здравствуйте, Ikemefula, Вы писали:
I>Для таких вещей всегда имелись библиотеки. А ну как придется портировать такой код на какую другую платформу, что ты будешь делать с этими mapped_xxx ?
Обычно все эти константы определяются в соответствующих *.h файлах, предоставляемых производителем чипов. Универсальных библиотек "на все платформы" естественно не существует. А вот под какое-то большое семейство чипов конечно бывают, и настраиваются под конкретный чип как раз с помощью подключения правильного *.h файла.
И да, я так не понял к чему ты это вообще написал. )))
Здравствуйте, alex_public, Вы писали:
S>>Скажем, если бы речь шла о спинлоке, то там внутри цикла должны были бы стоять не volatile, а fences — чтобы упорядочить чтения с записями из других потоков/ядер.
_>Для полноценного спинлока
Прям классика! Настоящий шотландец.
_> тебе не хватит ни volatile, ни fences. Для него необходимы уже атомарные операции типа CAS или аналоги, поддерживаемые процессором.
вот такой себе самый обычный код:
volatile sig_atomic x = 0;//или даже boolean
...
//thread1:
x = 1;
//thread2:
while(!x) {}
никаких CAS не надо, а вот fence нужен и volatile не поможет.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Sinclair, Вы писали:
_>>А я нигде и не говорил о многозадачности/многопоточности. Я говорил о важности модификатора volatile для низкоуровневого программирования. S>Ну вот это вот — типичная подмена понятий. Изначально делалось сильное утверждение про то, что volatile появился в C ради поддержки многозадачных ОС, которые и были его основным применением.
Кем и где делалось такое дикое утверждение? ) Я в любом случае подобного никогда не утверждал. И что-то сомневаюсь, что бы vdimas такое говорил, потому что, как это модно теперь здесь говорить, это был бы слишком большой залёт. )))
S>А теперь мы видим, что единственное приличное применение volatile — это memory-mapped HW, которое строго ортогонально многозадачности оси.
Ты не совсем правильно понимаешь. Применение volatile ортогонально и многозадачности и memory-mapped и вообще чему-либо "реальному". Это исключительно внутреннее дело компилятора C/C++, которому разрешают или не разрешают определённые вольности при генерации кода. Применяться это может в очень разных местах. И при работе с периферией процессора и при организации оптимизированных спинлоков (см. конец сообщения) в многопоточности и ещё много где.
S>Даже во вполне однозадачной ОС уровня MS-DOS работа с регистрами оборудования, отображёнными в память, будет требовать volatile, и, если я правильно понимаю принцип барьеров, то они тут неприменимы.
Да, всё правильно.
_>>Да, это именно задержка. И вполне себе надёжная. Т.е. понятно что аппаратный таймер лучше, но не во всех случаях его можно применить. S>Нет, это ненадёжная задержка. Впендюрив сюда volatile, программист запрещает "устраняющие" оптимизации компилятору. S>Но, во-первых, это никак не влияет на выбор размещения переменной, поэтому величина задержки получается произвольной даже в пределах одной аппаратуры — то ли будет выполнен сброс в память, то ли обойдёмся регистром. Какова будет разница в величине задержки? S>Во-вторых, даже в пределах одной аппаратуры у нас может плавать тактовая частота, и скорость исполнения этого цикла будет меняться в разы. S>Во-третьих, нет никакой гарантии, что во время цикла не будет выполнено вытеснение. Тогда можно запросто получить задержку на порядки больше, чем ожидалось.
Всё, что ты тут написал может быть справедливо например для написания ОС, но скажем для написания драйвера мотора на конкретном МК, это уже не актуально. )))
_>>Для полноценного спинлока тебе не хватит ни volatile, ни fences. Для него необходимы уже атомарные операции типа CAS или аналоги, поддерживаемые процессором. S>Ну, тут мне не хватает квалификации для полноценного разговора. В рамках нашей дискуссии достаточно сказать, что volatile для спинлока бесполезен.
Нуу всё относительно.
Смотри, спинлок — это по сути почти такой же код, как в моём первом примере на тему volatile, только он после изменения ячейки памяти (и окончания блокировки) должен мгновенно вернуть старое значение в ячейку — осуществить захват ресурса. Точнее слово "мгновенно" тут даже не верно: проверка флага и его установка (в случае нулевого значения) должна происходить атомарно! И соответственно для возможности реализации такого кода, нужна соответствующая поддержка от процессора. Обычно это реализуется через атомарную инструкцию CAS (CMPXCHG для х86, доступна в C++ через эту https://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange функцию класса atomic), которая как раз создана для таких целей и является базовым кирпичиком практически всех lock-free алгоритмов.
Казалось бы при применение CAS никакие volatile не нужны, достаточно только наличие у железа подобной инструкции. Но есть нюансы! ))) Инструкция CAS, как и все атомарные инструкции типа "прочитать-изменить-записать", весьма медленная. Поэтому частенько делают более интеллектуальную схему реализации спинлока: вставляют дополнительный блокирующий цикл ожидания, на обычном быстром чтение памяти (в точности как мой первый пример), а уже после его "прохода" реализуют захват на медленной атомарной функции. Ну и соответственно для возможности написания такой оптимизации, тебе очевидно потребуется volatile.
Вообще довольно иронично тут получается — для возможности оптимизации, тебе необходима возможность отмены другой оптимизации. )))
Здравствуйте, vdimas, Вы писали:
I>>Ты ведь на это намекаешь, что де задолго до стандарта всё уже было, правильно ?
V>Я не намекаю, я прямо говорю, что пользовался компилятором, в котором volatile достоверно появился до выхода стандарта ANSI C. V>Первую программу на Си я написал в 90-м году на Turbo C 2.0 (релиз 1988г), который вышел раньше стандарта на год (1989г).
V>Turbo C 1.0 я уже не застал (релиз 1987), но по нему легко ищется дока, там есть volatile.
Ядро Unix было портировано на С ажно 1973м году. Ты утверждаешь, что volatile появилось ради многопоточности в ядре Unix. И аргументируешь тем, что спустя 1988-1973 = 15 в комиляторе было volatile.
Между тем, для твого аргумента требуется доказать что volatile уже было в 1972году, то есть, с самого начала, т.к. в 1973 был релиз.
Ты такое доказательство привести не можешь, что видно по твоим сообщениям. Вместо такого доказательства ты надуваешь щеки, выпучиваешь глаза и пытаешься пускать пыль в глаза намекаешь на некоего предшественника Turbo C.
То есть, твоя версия несостоятельна, необоснована, отдаёт слишком тонкой и хрупкой эмоциональной архитектурой.
Здравствуйте, alex_public, Вы писали:
_>Обычно все эти константы определяются в соответствующих *.h файлах, предоставляемых производителем чипов. Универсальных библиотек "на все платформы" естественно не существует. А вот под какое-то большое семейство чипов конечно бывают, и настраиваются под конкретный чип как раз с помощью подключения правильного *.h файла.
Настраивается, но из этого не следует, что весь ввод вывод всегда отображается на память. То есть, все равно придется подключать более военные вещи.
_>И да, я так не понял к чему ты это вообще написал. )))
Здравствуйте, Ikemefula, Вы писали:
_>>Обычно все эти константы определяются в соответствующих *.h файлах, предоставляемых производителем чипов. Универсальных библиотек "на все платформы" естественно не существует. А вот под какое-то большое семейство чипов конечно бывают, и настраиваются под конкретный чип как раз с помощью подключения правильного *.h файла. I>Настраивается, но из этого не следует, что весь ввод вывод всегда отображается на память. То есть, все равно придется подключать более военные вещи.
Хы, ты похоже вообще не понял о чём была речь тут. ))) Видимо представил себе что-то типа DMA от устройств в реальную оперативку, да? ))) Не, здесь речь была о совсем другом: в современных МК все нужные регистры всей периферии отображаются в адресное пространство процессора! Причём в совсем другую его область, чем отображена оперативная память. Так что когда процессор видит инструкцию типа записи из регистра в ячейку памяти с подобным адресом, он на самом деле осуществляет запись в соответствующий регистр периферийного устройства. И это и есть собственно штатный способ взаимодействия с периферией процессора.
Здравствуйте, alex_public, Вы писали:
_>>>А я нигде и не говорил о многозадачности/многопоточности. Я говорил о важности модификатора volatile для низкоуровневого программирования. S>>Ну вот это вот — типичная подмена понятий. Изначально делалось сильное утверждение про то, что volatile появился в C ради поддержки многозадачных ОС, которые и были его основным применением.
_>Кем и где делалось такое дикое утверждение? ) Я в любом случае подобного никогда не утверждал. И что-то сомневаюсь, что бы vdimas такое говорил, потому что, как это модно теперь здесь говорить, это был бы слишком большой залёт. )))
"Понятие многопоточности в языке появилось давно, одновременно с ключевым словом volatile." @vdimas
Этот же vdimas утверждает, что многопоточность появилась в языке посредством внешних средств. Ага, внутри дома, методом наружного присутствия, объявился некто.
Здравствуйте, alex_public, Вы писали:
S>>Нет, это ненадёжная задержка. Впендюрив сюда volatile, программист запрещает "устраняющие" оптимизации компилятору. S>>Но, во-первых, это никак не влияет на выбор размещения переменной, поэтому величина задержки получается произвольной даже в пределах одной аппаратуры — то ли будет выполнен сброс в память, то ли обойдёмся регистром. Какова будет разница в величине задержки? S>>Во-вторых, даже в пределах одной аппаратуры у нас может плавать тактовая частота, и скорость исполнения этого цикла будет меняться в разы. S>>Во-третьих, нет никакой гарантии, что во время цикла не будет выполнено вытеснение. Тогда можно запросто получить задержку на порядки больше, чем ожидалось. _>Всё, что ты тут написал может быть справедливо например для написания ОС, но скажем для написания драйвера мотора на конкретном МК, это уже не актуально. )))
Для конкретного исходного кода и всех его зависимостей, конкретной версии компилятора, для конкретных флагов компилятора — да, не актуально. Т.е. процесс разработки будет выглядеть как: написали/изменили код, скомпилировали, дизассемблировали, посмотрели, что сгенерировались нужные инструкции в каждом таком месте и только после этого можно отдавать в прод.
Правда смысл этого мероприятия от меня ускользает. Не проще ли тогда тупо вставить asm?
_>Казалось бы при применение CAS никакие volatile не нужны, достаточно только наличие у железа подобной инструкции. Но есть нюансы! ))) Инструкция CAS, как и все атомарные инструкции типа "прочитать-изменить-записать", весьма медленная. Поэтому частенько делают более интеллектуальную схему реализации спинлока: вставляют дополнительный блокирующий цикл ожидания, на обычном быстром чтение памяти (в точности как мой первый пример), а уже после его "прохода" реализуют захват на медленной атомарной функции. Ну и соответственно для возможности написания такой оптимизации, тебе очевидно потребуется volatile.
Можно увидеть пример где так сделано?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
_>>·>Ох... Что непонятного-то? Да, рекурсивное определение. Как прям в BNF: <safe> ::= <proven_safe> | <safe>+<proven_safe>, где <proven_safe> код написанный в unsafe rust или ffi, но доказан другими средствами, что заявляемые в спеке языка гарантии удовлетворяются. _>>Только это работает исключительно в том случае, если предварительно было точно задано определение proven_safe. ·>Это задано в спеках на соответствующие конструкции языка.
Так у тебя proven_safe то что значит, "код без unsafe" или же "код с unsafe, но доказанный иными методами"? Если первое, то тогда определение выше просто не сработает. )))
·>
_>·>Safe Rust is the true Rust programming language. If all you do is write Safe Rust, you will never have to worry about type-safety or memory-safety. You will never endure a dangling pointer, a use-after-free, or any other kind of Undefined Behavior.
_>>·>The standard library also gives you enough utilities out of the box that you'll be able to write high-performance applications and libraries in pure idiomatic Safe Rust.
_>>И что характерно, даже в этой цитате речь идёт о разных вариациях безопасности по памяти, но нет ни слова про многопоточность... ) ·>"or any other kind of Undefined Behavior", Data Race это Undefined Behaviour, а Data Race это как раз про многопоточность.
Это конечно верно, однако все остальные известные проблемы там хорошо развёрнуты, а вот про многопоточность даже упоминания нет... ))) Очень характерно для чего в реальности польза этого языка.
_>>Давай разберёмся. Ты задал вопрос, является ли доступ к "volatile sig_atomic_t" из многопоточного кода атомарным или нет. Не определяя при этом, что ты подразумеваешь под атомарностью. Я думал, что ты подразумевал своё же старое определение этого термина — в этом случае атомарность будет. ·>Почему ты решил, что она будет?
В соседнем сообщение же прямой ответ был. )
_>>Если же ты подразумевал не то определение, а что-то другое, то тоже не проблема — сформулируй его и я тебе скажу будет ли оно соблюдаться для volatile sig_atomic_t или нет. ·>На самом деле вообще-то мы о сабже. А следовательно рассуждаем о безопасности, корректности и т.п кода. ·>Мой тезис был в том, что "volatile sig_atomic_t" нельзя использовать из многопоточного кода, т.к. программа получится с undefined behaviour.
Использовать можно. Хотя по факту скорее всего никогда не нужно (не припомню платформ, на которых была бы доступна классическая многопоточность, но при этом не было бы atomic), но это не отменяет нормальности работы этого кода (никаких data race).
·>Атомарность это детали обсуждения. Как бы мы ни определили понятие атомарости в нашей беседе, корректность кода не изменится, т.к. Стандарт явно называет это undefined behaviour, а следовательно все наложенные другими пунктами стандарта понятия типа атомарности идут лесом. ·>Согласен?
Эти детали как раз важны для того, чтобы понять происходит ли там на самом деле неопределённое поведение или речь всего лишь о зависимости от платформы.
_>>Если мы не опираемся на определения, данные в начале нашей дискуссии, то тогда приводи новые и будем говорить в их терминах. ·>Смотри соответствующие определения в стандарте и опирайся на них. Если я сказал что-то не то, поправляй меня цитатами стандарта.
Ну вот найди мне определение атомарности в стандарте и будем говорить тогда о других определениях.
Здравствуйте, alex_public, Вы писали:
V>>АМО-операции генерят исключение, если адрес не выровнен. _>А обычные операции не умеют?
Оно ж там как — не попало кривое выравнивание на границу линейки кеша — исключения от обычной операции не будет.
Если вообще нет кеша, вообще исключений не будет.
А на другом железе с некоей другой длиной линейшки кеша — прощай атомарность.
_>Да не важно RISC это или что-то другое. Главное что это куча халявных (причём под реально открытой лицензией, а не всякими убогими GPL) IP-ядер и даже готовых SoC'ов https://github.com/riscv/riscv-cores-list. Причём вполне современной архитектуры. И под них есть (благодаря унифицированной архитектуре) работающие из коробки gcc, Линух и т.п.
Я ж не спорю, что это клёво.
Просто вижу, что одним классом процов всего не покрыть, а одной операционкой можно покрыть почти всё. ))
V>>Не помешал бы аналогичный проект для VLIW. _>А ещё лучше открытое ядро современного GPU. Но тут что-то совсем тухло всё.
Здравствуйте, alex_public, Вы писали:
_>>>·>Ох... Что непонятного-то? Да, рекурсивное определение. Как прям в BNF: <safe> ::= <proven_safe> | <safe>+<proven_safe>, где <proven_safe> код написанный в unsafe rust или ffi, но доказан другими средствами, что заявляемые в спеке языка гарантии удовлетворяются. _>>>Только это работает исключительно в том случае, если предварительно было точно задано определение proven_safe. _>·>Это задано в спеках на соответствующие конструкции языка. _>Так у тебя proven_safe то что значит, "код без unsafe" или же "код с unsafe, но доказанный иными методами"? Если первое, то тогда определение выше просто не сработает. )))
Выделил. Очевидно же, что второе.
_>>>И что характерно, даже в этой цитате речь идёт о разных вариациях безопасности по памяти, но нет ни слова про многопоточность... ) _>·>"or any other kind of Undefined Behavior", Data Race это Undefined Behaviour, а Data Race это как раз про многопоточность. _>Это конечно верно, однако все остальные известные проблемы там хорошо развёрнуты, а вот про многопоточность даже упоминания нет... ))) Очень характерно для чего в реальности польза этого языка.
Т.е. пользу языка ты оцениваешь по тому, что в ~двух конкретных параграфах документации не описано то что ты хочешь. УмнО!
_>>>Давай разберёмся. Ты задал вопрос, является ли доступ к "volatile sig_atomic_t" из многопоточного кода атомарным или нет. Не определяя при этом, что ты подразумеваешь под атомарностью. Я думал, что ты подразумевал своё же старое определение этого термина — в этом случае атомарность будет. _>·>Почему ты решил, что она будет? _>В соседнем сообщение же прямой ответ был. )
Ты ссылку давай. Тут столько соседних сообщений, что я не знаю куда смотреть.
_>·>На самом деле вообще-то мы о сабже. А следовательно рассуждаем о безопасности, корректности и т.п кода. _>·>Мой тезис был в том, что "volatile sig_atomic_t" нельзя использовать из многопоточного кода, т.к. программа получится с undefined behaviour. _>Использовать можно. Хотя по факту скорее всего никогда не нужно (не припомню платформ, на которых была бы доступна классическая многопоточность, но при этом не было бы atomic), но это не отменяет нормальности работы этого кода (никаких data race).
Я несколько раз уже цитировал, что это data race по стандарту. Так что подтверждай высказывание стандартом, либо признавайся, что не прав.
_>·>Атомарность это детали обсуждения. Как бы мы ни определили понятие атомарости в нашей беседе, корректность кода не изменится, т.к. Стандарт явно называет это undefined behaviour, а следовательно все наложенные другими пунктами стандарта понятия типа атомарности идут лесом. _>·>Согласен? _>Эти детали как раз важны для того, чтобы понять происходит ли там на самом деле неопределённое поведение или речь всего лишь о зависимости от платформы.
Вне зависимости от деталей там неопределённое поведение.
_>>>Если мы не опираемся на определения, данные в начале нашей дискуссии, то тогда приводи новые и будем говорить в их терминах. _>·>Смотри соответствующие определения в стандарте и опирайся на них. Если я сказал что-то не то, поправляй меня цитатами стандарта. _>Ну вот найди мне определение атомарности в стандарте и будем говорить тогда о других определениях.
Objects of atomic types are the only objects that are free from data races, that is, they may be modified by two threads concurrently or modified by one and read by another.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Sinclair, Вы писали:
V>>Было бы хоть у кого-то, спор давно был бы исчерпан. S>Статья Джонсона 1981 года достаточно подробно описывает state of the art на тот момент. S>http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.3512 S>Там никакого volatile нет, да и оптимизации на тот момент были рудиментарными.
В статье многих конструкция языка нет, и?
Статья в основном о лейауте данных и переносимости как таковой.
Это ты, действительно, по этой статье выводы делал? ))
S>Всё интересное случилось между 1982 и 1985 — как раз комитет начал стандартизацию.
Когда комитет начал работы по стандартизации, в наличии уже были реализации, развивающиеся независимо.
Собсно, из-за этого комитет и собрали.
У нас были лабы на EC 1033 и EC 1020, там был заметно другой Си, чем на персоналках.
S>Авторы спецификации специально отмечали, что некоторые вещи, типа enum и void, были придуманы до начала стандартизации, а вот volatile и const были предложены в рамках процесса.
ОМГ
В комитет входили основные разработчики компилятора или представители от них, и создали комитет по их же инициативе аккурат для "сверки часов".
S>Понятное дело, что авторы поддерживали общение с комьюнити.
В голос уже ))
"Поддерживали"...
Да это и было само коммьюнити.
На тот момент даже еще не было понятно, в рамках какого стандарта будет происходить стандартизация, комитет был просто независимой группкой по интересам от коммерческих контор.
И так оно и вышло — сували стандарт для публикации сначала в одно бюро по стандартизации, потом в другое.
S>Разработка компиляторов тогда была, похоже, более-менее прибыльным занятием — в середине восьмидесятых лицензия на компилятор C стоила 500-600 долларов, что овердофига.
Опять в голос ))
Тогда в основном были мини-ЭВМ или мейнфреймы, эта лицензия, считай, на десятки-сотни человек.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Ikemefula, Вы писали:
_>>>Обычно все эти константы определяются в соответствующих *.h файлах, предоставляемых производителем чипов. Универсальных библиотек "на все платформы" естественно не существует. А вот под какое-то большое семейство чипов конечно бывают, и настраиваются под конкретный чип как раз с помощью подключения правильного *.h файла. I>>Настраивается, но из этого не следует, что весь ввод вывод всегда отображается на память. То есть, все равно придется подключать более военные вещи.
_>Хы, ты похоже вообще не понял о чём была речь тут. ))) Видимо представил себе что-то типа DMA от устройств в реальную оперативку, да? )))
Нет, не про это. Плохой из тебя телепат, да ?
>Не, здесь речь была о совсем другом: в современных МК все нужные регистры всей периферии отображаются в адресное пространство процессора! Причём в совсем другую его область, чем отображена оперативная память. Так что когда процессор видит инструкцию типа записи из регистра в ячейку памяти с подобным адресом, он на самом деле осуществляет
запись в соответствующий регистр периферийного устройства. И это и есть собственно штатный способ взаимодействия с периферией процессора.
Значит мне повезло — когда я писал на ассемблере, таких фокусов еще не было, и нужно было заниматься ручным программированием портов.
Здравствуйте, vdimas, Вы писали:
I>>Ядро Unix было портировано на С ажно 1973м году.
V>Не, первые работы начались в 67-м, но тогда и язык так не назывался, и UNIX был еще не UNIX. V>Первый более-менее релиз (если его так можно назвать) состоялся в 74-м.
Вот и интересно посмотреть, как использовали volatile в этот период.
Здравствуйте, vdimas, Вы писали:.
V>Здравствуйте, Sinclair, Вы писали: V>В статье многих конструкция языка нет, и? V>Статья в основном о лейауте данных и переносимости как таковой.
В том числе описано и то, какие оптимизаци выполняет компилятор.
V>Это ты, действительно, по этой статье выводы делал? ))
Да. У вас есть более хороший источник?
S>>Всё интересное случилось между 1982 и 1985 — как раз комитет начал стандартизацию.
V>Когда комитет начал работы по стандартизации, в наличии уже были реализации, развивающиеся независимо. V>Собсно, из-за этого комитет и собрали. V>У нас были лабы на EC 1033 и EC 1020, там был заметно другой Си, чем на персоналках.
Ну естественно, это ж было 8 лет спустя. Для того времени — целая эпоха. V>В комитет входили основные разработчики компилятора или представители от них, и создали комитет по их же инициативе аккурат для "сверки часов". V>Да это и было само коммьюнити.
Ну, вы собственно подтверждаете мои слова.
V>И так оно и вышло — сували стандарт для публикации сначала в одно бюро по стандартизации, потом в другое.
Всё верно. Я ни разу и не утверждал, что volatile появился после принятия стандарта. Но вам стоило бы задуматься о том, что первое издание K&R вышло в 1978, и достаточно полно отражало язык в тот момент.
Задача написания ядра Unix к тому моменту уже несколько лет как была завершена.
S>>Разработка компиляторов тогда была, похоже, более-менее прибыльным занятием — в середине восьмидесятых лицензия на компилятор C стоила 500-600 долларов, что овердофига.
V>Опять в голос ))
Смех без причины V>Тогда в основном были мини-ЭВМ или мейнфреймы, эта лицензия, считай, на десятки-сотни человек.
Ну да. Поэтому большинство людей знакомились с С в университетах. Только отдельные смельчаки покупали его для домашнего использования.
Вместо того, чтобы ржать в голос, почитайте воспоминания дедушек: https://www.quora.com/What-was-the-first-C-compiler-you-used-and-on-what-computer