Re[44]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 10:33
Оценка:
Здравствуйте, alex_public, Вы писали:

_>>>На том основание, что на всем железе инструкция записи регистра в память атомарна,

_>·>Это закон природы?
_>Скорее закон целесообразности. )
Стронгли белив, ок.

_>>>а присвоение переменной типа int скомпилируется именно в такую инструкцию.

_>·>А это на каком основании?
_>На том основание, что int умещается в один регистр. )
И? А ссылка на спеку где?

_>>>Там нет кода, который изменил бы своё поведение, в случае "кэширования" значения переменной в регистре.

_>·>Это по коду не видно. Там вызывается некий метод process который может тоже делать хз что, а компилятор может видеть и этот код и принимать свои решения.
_>Не, как раз всё видно. Вот если бы там было например по две операции чтения/записи нашей переменной в каждом потоке, то уже можно было начинать беспокоиться... )
А ты видишь какие есть операции в process() и какие там окажутся через год активной разработки?

_>>>Ты похоже как-то плохо умеешь читать текст на русском языке. Я же однозначно написал, что как раз в моём примере такого кода нет. А вот если бы был, то тогда и модификатор volatile появился бы.

_>·>Я не о конкретно данной ситуации. Меня повеселил факт, что оптимизации в принципе можно считать опасными.
_>Ну я вроде как рядом приводил вполне конкретные примеры, в которых это вполне актуально.
Актуально писать корректный код, а не бояться оптимизаций.

_>>>Перестановку обращений к одной области памяти тупо недопустит сам компилятор, т.к. это изменит поведение кода. )))

_>·>Компилятор, если ему не сказано явно, не учитывает поведение других потоков, поэтому он может допускать всё что угодно, что не противоречит наблюдаемым эффектам однопоточного исполнения данной части кода.
_>Правильно. И как ты видишь перестановку обращений к одной области памяти, которая не поменяет поведение однопоточного кода? ) Ну и которая не сводится к объединению двух одинаковых команд в одну (что отключается через volatile).
А, понял что ты имеешь в виду. Да, согласен. Другой вопрос, насколько это реально иметь не более одного обращения к памяти в сколько-нибудь нетривиальной программе.

_>·>Ох.. Повторяюсь. Записи оптимизировать может не только компилятор, но и процессор. А процессор про volatile ничего не знает.

_>Ты всё время путаешь два типа оптимизаций. В одной возможны перестановки команд, а в другой возможны слияния или даже опускания команд. Первый тип реализуется и компилятор и процессором. И отключается через соответствующие fence вызовы. А второй типа реализуется только компилятором и отключается для переменных с модификатором volatile.
Допустим мы заставили компилятор нагенерить:
mov [x], 1
// do stuff
mov [x], 2

Проц имеет право слить эти операции в mov [x], 2. Ну, понятное дело, если проц знает, что данный [x] это mm i/o, то он сливать не будет. Если же адрес в памяти и нет fence — можно же и заоптимизировать — всё в соответствии со спекой. Точно так же проц имеет право переупорядочивать или пропускать чтения и записи.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[42]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 10:48
Оценка:
Здравствуйте, alex_public, Вы писали:

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

_>·>Т.е. пользу языка ты оцениваешь по тому, что в ~двух конкретных параграфах документации не описано то что ты хочешь. УмнО!
_>Я этот язык внимательно рассматриваю с таких давних пор, в которые ты даже мельком не слышал это название. ))) Причём рассматриваю не просто из абстрактного интереса, а с точки зрения замены им моего основного инструмента! Так что пользу его я отлично знаю. Правда чем дальше идёт время от 2014-го года, тем меньше я вижу смысла в переходе (сравнивая направление и темпы развития Rust и C++), но это отдельный вопрос.
Так бы и сказал, что это твоё мнение, тебе язык не импонирует. И т.п. Зачем было перевирать факты — мне неясно.

_>>>·>На самом деле вообще-то мы о сабже. А следовательно рассуждаем о безопасности, корректности и т.п кода.

_>>>·>Мой тезис был в том, что "volatile sig_atomic_t" нельзя использовать из многопоточного кода, т.к. программа получится с undefined behaviour.
_>>>Использовать можно. Хотя по факту скорее всего никогда не нужно (не припомню платформ, на которых была бы доступна классическая многопоточность, но при этом не было бы atomic), но это не отменяет нормальности работы этого кода (никаких data race).
_>·>Я несколько раз уже цитировал, что это data race по стандарту. Так что подтверждай высказывание стандартом, либо признавайся, что не прав.
_>Да, и в твоей цитате было ясно написано, что для атомарных данных data race не будет. )
Верно. Там же явно указывалось, что считается атомарными данными в том месте — только std::atomic, а не "все типы у которых есть слово atomic в имени".

_>>>Ну вот найди мне определение атомарности в стандарте и будем говорить тогда о других определениях.

_>·>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.
_>Это их свойство, а не определение. )
Это определяющее свойство. Просто формулировка такая. Можно немного вывернуть, чтобы получилось по виду как определение:
Atomic type — is a type which objects are free from data races.
Притом такие типы там явно перечислены. И ключевое слово там "only". Т.е. все остальные типы — подвержены data race, а следовательно их надо защищать от конкурентных операций с помощью мьютексов и т.п.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[59]: Безопасность Rust
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.06.19 10:51
Оценка:
Здравствуйте, vdimas, Вы писали:

I>>Этот же vdimas утверждает, что многопоточность появилась в языке посредством внешних средств.


V>Так в языке или через внешние ср-ва? ))


Это у тебя надо спросить, это же ты пишешь "Согласно дизайну, многопоточность реализована в виде внешнего механизма"

Re[43]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 11:12
Оценка:
Здравствуйте, ·, Вы писали:

·>Притом volatile от этого не поможет, ибо он влияет только на компилятор, а железу пофиг.


volatile поможет донести до памяти значение операции.
Иногда этого достаточно, когда речь об одной переменной всего, при этом достоверно известно, что чтение и запись такой переменной атомарны.
(Собсно, в 100-й раз повторяюсь уже...)

Стоит добавить вторую переменную, и одного volatile мало, нужен явный fence.

Простой пример.
Есть некая "бесконечная" очередь, строго один поток-писатель и строго один поток-читатель.

int data[N];
volatile unsigned writeCursor = 0;
char padding[512];
unsigned readCursor = 0;

// вызывается потоком 1
void put(int value) {
    data[writeCursor] = value;
    fence();
    writeCursor++;
}

// вызывается потоком 2
template<typename Callback>
void process(Callback callback) {
    while(readCursor != writeCursor) {
        fence();
        callback(data[readCursor]);
        readCursor++;
    }
}


Тут важна очередность — переменная writeCursor изменяется последней при записи, но должна читаться первой при чтении.

Допустим, у нас есть железо, которое достоверно пишет в память в указанном порядке, тогда в потоке 1 требуется fence() только для компилятора, а не проца.
Или есть железо, которое не умеет делать предсказание ветвления и соотв. предварительную выборку, тогда fence() в потоке 2 избыточен.
Поэтому "ограды" и разложили на несколько вариантов, дабы описать более конкретно, что имелось ввиду, т.е. на конкретном железе некоторые варианты memory_order компиллируюся в обычные команды записи/чтения регистров.

Например, в архитектуре x86/x86_x64 кеш всегда строго когерентный, поэтому при записи с memory_order_relaxed и mevory_order_release используются обычные команды записи в память без дополнительных команд синхронизации.

А спорили мы о том, есть ли в природе такая архитектура, в которой в варианте memory_order_relaxed потребуется синхронизация для атомарных типов, т.е. где будет отличие от обычного volatile.
ИМХО, такой архитектуры не будет никогда, бо она будет заведомо невостребованной.
Т.е., с дуру придумать можно что угодно, ес-но, но программы под "это" писать не придётся. ))
Re[45]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 11:20
Оценка:
Здравствуйте, ·, Вы писали:

_>>На том основание, что int умещается в один регистр. )

·>И? А ссылка на спеку где?

В Си:
register a;

означает
int a;
Re[60]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 11:32
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>>>Этот же vdimas утверждает, что многопоточность появилась в языке посредством внешних средств.

V>>Так в языке или через внешние ср-ва? ))
I>Это у тебя надо спросить

Ты на вопрос ответь.
Re[61]: Безопасность Rust
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.06.19 11:44
Оценка:
Здравствуйте, vdimas, Вы писали:

I>>>>Этот же vdimas утверждает, что многопоточность появилась в языке посредством внешних средств.

V>>>Так в языке или через внешние ср-ва? ))
I>>Это у тебя надо спросить

V>Ты на вопрос ответь.


Я процитировал твоё собтсвенное противоречие. Это именно ты утверждаешь "многопоточность появилась в языке посредством внешних средств"
Потому и не ясно, в языке ли, или же внешними средствами.
Re[62]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 13:18
Оценка:
Здравствуйте, Ikemefula, Вы писали:

V>>>>Так в языке или через внешние ср-ва? ))

I>>>Это у тебя надо спросить
V>>Ты на вопрос ответь.
I>Я процитировал твоё собтсвенное противоречие.

Ты процитировал не меня.
Процитируй мои точные фразы.


I>Это именно ты утверждаешь "многопоточность появилась в языке посредством внешних средств"


Не утверждаю.


I>Потому и не ясно, в языке ли, или же внешними средствами.


Если возникли сомнения в тексте, стоило сначала уточнить сам текст, а не приставать к окружающим с глупыми вопросами. ))
Re[50]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 13:19
Оценка:
Здравствуйте, vdimas, Вы писали:

V>·>А вот race condition действительно относится к семантике и может быть "так и задумано".

V>Ты уже с терминологией решил начать спорить. ))
V>Race condition означает условное поведение всей программы в зависимости от как повезёт.
Да, т.е. недетерминизм.

V>Data race — означает одновременные попытки читать и писать некие данные, или одновременные попытки писать.

Да. И ведёт к undefined behaviour.

V>Соотносятся эти определения следующим образом: data race может быть причиной race condition.

Наоборот — race condition может быть причиной data race, если "мы не подумали, что тут лок может не захватиться".

V>Но может быть и частью алгоритма.

Data race не может быть частью корректного алгоритма, т.к. является undefined behaiour и никакие характеристики алгоритма обеспечить не может.

V>·>Нет. std::atomic гарантирует отсутсвие data race:

V>Только для тех типов, для которых он специализируется с мьютексом унутре.
Это твои фантазии.


V>·>"A program that has two conflicting evaluations has a data race unless ... both conflicting evaluations are atomic operations (see std::atomic) ..."

V>·>Без всяких оговорок о конкретном memory_order или о том, какими типами они специализированы.
V>На заборе тоже написано... , обычный data race.
Это твои фантазии.

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

V>·>Тот факт, что мы передали указатель на функцию куда-то, это ещё не означает, что эту функцию стало безопасно дёргать из многопоточки.
V>А что в теле этой ф-ии рекомендуется лишь установить значение единственной переменной static volatile sig_atomic_t и выйти, ты уже забыл?
Нет, не забыл. Ты хочешь сказать что такой код:
static volatile sig_atomic_t x;
void blah(int sig)
{
  x = sig;
}
callFromMultipleThreads(blah);

некорректный, А если добавить signal(SIG_NEVER_HAPPENS, blah) — то всё волшебным образом станет корректно?

V>>>·>Я ж отвечал уже — платформено-зависимыми функциями — ассемблерные вставки, сисколлы.

V>>>Для однопроцессорных мультизадачных операционок никаких дополнительных приседаний в виде ассемблерных вставок не требовалось.
V>·>В смысле "у меня всё работало"? Отличный аргумент.
V>У всех работало.
V>Исходники System V доступны, там для обсуждаемых вещей никаких ассемблерных вставок.
Не понял что ты имеешь в виду. Дай ссылку что-ли.

V>·>И что? Ничто из этого не означает, что обработчик сигнала можно вызывать из треда напрямую.

V>Это означает для начала, что твои частности не являлись аргументом.
V>А во вторых, разрешено всё, что не запрещено.
Использование типов кроме std::atomic конкурентно запрещено явно. Ну запрещено в том смысле, что объявлено как UB.

V>Вызывать собственный обработчик никем не запрещено.

Вызывать можно функцию, а не "обработчик". Функция начинает обрабатывать сигнал, когда ось дёргает её для обработки сигнала. А просто вызов функции работает как... ээ.. вызов функции — со всеми соответствующими гарантиями.

V>Т.е., возможны ситуации:

V>- два разных потока обрабатывают два разных сигнала одновременно;
V>- один и тот же поток обрабатывает оба сигнала, причём, второй сигнал залетел реентерабельно, не дожидаясь завершения работы первого обработчика.
Это не значит, что они могут шарить данные как хотят. Вообще это два разных механизма сигналы и треды — и требуется очень осторожный подход что можно делать, что нельзя.
https://stackoverflow.com/questions/6128547/is-execution-of-signal-handler-un-preemptible-in-linux
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[44]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 13:22
Оценка:
Здравствуйте, vdimas, Вы писали:

V>·>Притом volatile от этого не поможет, ибо он влияет только на компилятор, а железу пофиг.

V>volatile поможет донести до памяти значение операции.
Нет, оно только лишь отключает некоторые оптимизации компилятора. А у нас ещё есть процессор и всякие его кеши.

V>Иногда этого достаточно, когда речь об одной переменной всего, при этом достоверно известно, что чтение и запись такой переменной атомарны.

V>(Собсно, в 100-й раз повторяюсь уже...)
Атомарность не абсолютное понятие в данном случае. В общем случае — атомарная операция это такая операция, которая происходит мгновенно и не имеет никакой внутренней структуры с т.з. стороннего наблюдателя. А вот кто является этим сторонним наблюдателем — очень важно.
Так вот sig_atomic_t — это атомарность с т.з. асинхронного испонления сигналов, а std::atomic — с т.з. многопоточного исполнения. Притом очевидно, что второе включает в себя и первое.
Поэтому std:atomic можно юзать и в сигналах, но не наоборот.

V>Допустим, у нас есть железо, которое достоверно пишет в память в указанном порядке, тогда в потоке 1 требуется fence() только для компилятора, а не проца.

Это допущение некорректно с т.з. кода на языке, ибо оно не прописано в спеке и с т.з. языка является UB. Корректно писать как надо по спеке и это дело компилятора ставить барьеры нужного типа в нужное место.

V>А спорили мы о том, есть ли в природе такая архитектура, в которой в варианте memory_order_relaxed потребуется синхронизация для атомарных типов, т.е. где будет отличие от обычного volatile.

V>ИМХО, такой архитектуры не будет никогда, бо она будет заведомо невостребованной.
V>Т.е., с дуру придумать можно что угодно, ес-но, но программы под "это" писать не придётся. ))
Это не единственно возможное проявление UB, например, ты проигнорировал покоцанную тобой цитату тут.

They would be invalid for a hypothetical machine that is not tolerant of races or provides hardware race detection.

Архитектура, которая отслеживает и пришибает data race — будет востребованной уж точно. И твой говнокод там тупо разлетится на куски.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[51]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 13:34
Оценка:
Здравствуйте, ·, Вы писали:

V>>Data race — означает одновременные попытки читать и писать некие данные, или одновременные попытки писать.

·>Да. И ведёт к undefined behaviour.

Докажи.


V>>Соотносятся эти определения следующим образом: data race может быть причиной race condition.

·>Наоборот — race condition может быть причиной data race

Это уже ненормальность, однако. ))


·>если "мы не подумали, что тут лок может не захватиться".


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


V>>Но может быть и частью алгоритма.

·>Data race не может быть частью корректного алгоритма, т.к. является undefined behaiour и никакие характеристики алгоритма обеспечить не может.

Докажи.


V>>·>Нет. std::atomic гарантирует отсутсвие data race:

V>>Только для тех типов, для которых он специализируется с мьютексом унутре.
·>Это твои фантазии.

Докажи.


V>>·>"A program that has two conflicting evaluations has a data race unless ... both conflicting evaluations are atomic operations (see std::atomic) ..."

V>>·>Без всяких оговорок о конкретном memory_order или о том, какими типами они специализированы.
V>>На заборе тоже написано... , обычный data race.
·>Это твои фантазии.

Докажи.


·>Ты хочешь сказать что такой код:

·>некорректный, А если добавить signal(SIG_NEVER_HAPPENS, blah) — то всё волшебным образом станет корректно?

Да ты еще и русского языка не понимаешь. ))
Я хочу сказать, что такой код всегда корректный.
Обратное требуется доказать.


V>>Исходники System V доступны, там для обсуждаемых вещей никаких ассемблерных вставок.

·>Не понял что ты имеешь в виду. Дай ссылку что-ли.

Ссылку легко найдёшь сам.


V>>А во вторых, разрешено всё, что не запрещено.

·>Использование типов кроме std::atomic конкурентно запрещено явно.

Не запрещено.


·>Ну запрещено в том смысле, что объявлено как UB.


Объявлено как data race, а не UB.


V>>Вызывать собственный обработчик никем не запрещено.

·>Вызывать можно функцию, а не "обработчик". Функция начинает обрабатывать сигнал, когда ось дёргает её для обработки сигнала. А просто вызов функции работает как... ээ.. вызов функции — со всеми соответствующими гарантиями.

И что тебя смущает?


V>>Т.е., возможны ситуации:

V>>- два разных потока обрабатывают два разных сигнала одновременно;
V>>- один и тот же поток обрабатывает оба сигнала, причём, второй сигнал залетел реентерабельно, не дожидаясь завершения работы первого обработчика.
·>Это не значит, что они могут шарить данные как хотят.

Могут как хотят.


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


В стандарте явно говорится о обработчике сигнала, вызываемого из некоего треда процесса.
"Осторожный подход" тут требуется только если совсем не понимать, что такое прерывание.
Выросло, блин, поколение next...
Re[46]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 13:45
Оценка:
Здравствуйте, vdimas, Вы писали:

_>>>На том основание, что int умещается в один регистр. )

V>·>И? А ссылка на спеку где?

V>В Си:

V>
V>register a;
V>

V>означает
V>
V>int a;
V>

Мде...
Во-первых, "register a" означает сокращение "register int a" (та же шняга с unsigned).
Во-вторых, это всего лишь hint и может игнорироваться.
В-третьих, например, если ты напишешь "register long long a" — то волшебства не произойдёт и значение полезет в два регистра.
    //register long long a=111111111111L;
    mov     ebx, -558038585
    mov     esi, 25


Т.е. ключевое слово register лишь рекомендует комилятору размещать указанное значение в регистрах, а не в памяти, но ничего не говорит о том, что это должен быть один регистр.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[52]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 14:03
Оценка: +1 :)
Здравствуйте, vdimas, Вы писали:

Я тебе это уже доказал цитатами.

V>>>Data race — означает одновременные попытки читать и писать некие данные, или одновременные попытки писать.

V>·>Да. И ведёт к undefined behaviour.
V>Докажи.

If a data race occurs, the behavior of the program is undefined.

(с) https://en.cppreference.com/w/cpp/language/memory_model

V>>>Соотносятся эти определения следующим образом: data race может быть причиной race condition.

V>·>Наоборот — race condition может быть причиной data race
V>Это уже ненормальность, однако. ))

A race condition is per se not bad. A race condition can be the reason for a data race. In contrary, a data race is an undefined behaviour. Therefore, all reasoning about your program makes no sense anymore.

(с) https://www.modernescpp.com/index.php/race-condition-versus-data-race

V>·>если "мы не подумали, что тут лок может не захватиться".

V>Никаких если.
V>Ты споришь с базовой терминологией.
V>Впрочем, однажды я от тебя подобную жесть уже наблюдал.
Я спорю с твоими фантазиями.

V>>>Но может быть и частью алгоритма.

V>·>Data race не может быть частью корректного алгоритма, т.к. является undefined behaiour и никакие характеристики алгоритма обеспечить не может.
V>Докажи.

If a data race occurs, the behavior of the program is undefined.

(с) https://en.cppreference.com/w/cpp/language/memory_model

V>>>·>Нет. std::atomic гарантирует отсутсвие data race:

V>>>Только для тех типов, для которых он специализируется с мьютексом унутре.
V>·>Это твои фантазии.
V>Докажи.
Доказывать твои фантазии? Упаси боже. Ты глупость сказал, ты и доказывай.

V>>>·>"A program that has two conflicting evaluations has a data race unless ... both conflicting evaluations are atomic operations (see std::atomic) ..."

V>>>·>Без всяких оговорок о конкретном memory_order или о том, какими типами они специализированы.
V>>>На заборе тоже написано... , обычный data race.
V>·>Это твои фантазии.
V>Докажи.
Доказывать твои фантазии? Упаси боже. Ты глупость сказал, ты и доказывай.

V>Я хочу сказать, что такой код всегда корректный.

Это твои фантазии.

V>Обратное требуется доказать.

Корректность кода ты не доказал.

V>>>Исходники System V доступны, там для обсуждаемых вещей никаких ассемблерных вставок.

V>·>Не понял что ты имеешь в виду. Дай ссылку что-ли.
V>Ссылку легко найдёшь сам.
Это твои фантазии.

V>>>А во вторых, разрешено всё, что не запрещено.

V>·>Использование типов кроме std::atomic конкурентно запрещено явно.
V>Не запрещено.

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.

(с) https://en.cppreference.com/w/c/language/atomic

V>·>Ну запрещено в том смысле, что объявлено как UB.

V>Объявлено как data race, а не UB.
data race всегда UB.

V>>>Вызывать собственный обработчик никем не запрещено.

V>·>Вызывать можно функцию, а не "обработчик". Функция начинает обрабатывать сигнал, когда ось дёргает её для обработки сигнала. А просто вызов функции работает как... ээ.. вызов функции — со всеми соответствующими гарантиями.
V>И что тебя смущает?
Что вызывать код с data race не даёт никаких гарантий.

V>·>Это не значит, что они могут шарить данные как хотят.

V>Могут как хотят.
Это твои фантазии.

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

V>В стандарте явно говорится о обработчике сигнала, вызываемого из некоего треда процесса.
Тред процесса прерывает своё выполнение и обработчик вызывается ядром в контексте этого треда, притом сам тред на это время "не работает" по очевидным причинам. Это асинхронность, а не многопоточность. Примерно как async/await.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[45]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 14:08
Оценка:
Здравствуйте, ·, Вы писали:

V>>·>Притом volatile от этого не поможет, ибо он влияет только на компилятор, а железу пофиг.

V>>volatile поможет донести до памяти значение операции.
·>Нет

Докажи.


·>оно только лишь отключает некоторые оптимизации компилятора.


Какие именно? И с чего ты решил, что сей аргмент подтверждает твоё "нет", а не разбивает его в пух и прах?


·>А у нас ещё есть процессор и всякие его кеши.


Во-во.
Кеши ЧЕГО именно?


V>>Иногда этого достаточно, когда речь об одной переменной всего, при этом достоверно известно, что чтение и запись такой переменной атомарны.

V>>(Собсно, в 100-й раз повторяюсь уже...)
·>Атомарность не абсолютное понятие в данном случае.

Для тебя это не понятие, а набор звуков.
Де-факто, это абсолютнейшее понятие из всех возможных.


·>В общем случае — атомарная операция это такая операция, которая происходит мгновенно





·>и не имеет никакой внутренней структуры с т.з. стороннего наблюдателя. А вот кто является этим сторонним наблюдателем — очень важно.


Ты свои потёки сознания хоть чем-то подтверждать собираешься?


·>Так вот sig_atomic_t — это атомарность с т.з. асинхронного испонления сигналов


Это автоматически означает, что доступ к этому типу атомарен.
Бо пре-ры-ва-ни-я.

Включил бы хоть раз самый важный свой орган:
— компилятор, когда компилит обработчик сигнала, он понятия не имеет, что это именно обработчик сигнала, там такой же код компилится, как везде;
— обработчик сигнала вызывается из пользовательского потока, как и любой другой пользовательский код;

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


·>а std::atomic — с т.з. многопоточного исполнения.


Для атомарных типов выполняется лишь упорядочивание памяти, актуальное лишь когда в алгоритме более одной расшаренной м/у потоками переменной.


·>Притом очевидно, что второе включает в себя и первое.


Ну разумеется! Мн-во из 2-х переменных включает в себя множество из одной переменной!
А все такие дураки, спорят с тобой и возражают именно на этот важный аргумент!
(неужели тебе самому не весело себя читать)
(или специально троллишь)
(не похож ты на тролля, те тоньше и соображающие)


V>>Допустим, у нас есть железо, которое достоверно пишет в память в указанном порядке, тогда в потоке 1 требуется fence() только для компилятора, а не проца.

·>Это допущение некорректно с т.з. кода на языке

Вообще-то, приводится пример, ЗАЧЕМ нужны разные типы fence, т.е. почему плох одинаковый на все случаи жизни.
И это было сказано явно, но ты и этого не понял. ))


V>>А спорили мы о том, есть ли в природе такая архитектура, в которой в варианте memory_order_relaxed потребуется синхронизация для атомарных типов, т.е. где будет отличие от обычного volatile.

V>>ИМХО, такой архитектуры не будет никогда, бо она будет заведомо невостребованной.
V>>Т.е., с дуру придумать можно что угодно, ес-но, но программы под "это" писать не придётся. ))
·>Это не единственно возможное проявление UB, например, ты проигнорировал покоцанную тобой цитату тут.
·>

They would be invalid for a hypothetical machine that is not tolerant of races or provides hardware race detection.


would be — условное наклонение.
hypothetical — тем более.
Т.е. в стандарте явным образом говорится о том, чего не существует.
Де-факто таких архитектур нет и в ближайшие несколько десятилетий не предвидится.
Есть аппаратные помощники по детектированию data race, но они пока не умеют работать самостоятельно, только в связке с ПО.
Потому что не обладают инфой о типе.


·>Архитектура, которая отслеживает и пришибает data race — будет востребованной уж точно.


Для атомарных типов и единственной операции?
Не будет, бо это невозможно выразить схемотехнически.
Собсно, потому что нельзя выразить логически, поэтому нельзя схемотехнически.
И ты логически выразить тоже не сможешь.
Мог бы — уже давно бы членораздельно разложил всё по полочкам, что и где не так, вместо кивания на "авторитеты" в лице стандарта, который ты и не читал целиком, а где читал — толком не разобрался всё-равно.

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

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


·>И твой говнокод там тупо разлетится на куски.


Есть такой город — Нью-Васюки.
Вам туда. ))
Отредактировано 08.06.2019 6:04 vdimas . Предыдущая версия .
Re[47]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 14:38
Оценка:
Здравствуйте, ·, Вы писали:

·>Во-первых, "register a" означает сокращение "register int a" (та же шняга с unsigned).


Та же "шняга" не с unsigned:
f(a, b, c) { return a + b + c; }

main() { return f(1, 2, 3); }

Тип int можно не указывать.

Так почему именно так?
Re[46]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 14:38
Оценка:
Здравствуйте, vdimas, Вы писали:

V>·>А у нас ещё есть процессор и всякие его кеши.

V>Во-во.
V>Кеши ЧЕГО именно?
Кеши процессора. Запись в кеш != запись в память.

V>·>В общем случае — атомарная операция это такая операция, которая происходит мгновенно

V>
V>·>и не имеет никакой внутренней структуры с т.з. стороннего наблюдателя. А вот кто является этим сторонним наблюдателем — очень важно.
V>Ты свои потёки сознания хоть чем-то подтверждать собираешься?

This property of occurring instantaneously, or indivisibly, leads to the use of the term atomic as an alternative to the longer "linearizable"

(c) https://en.wikipedia.org/wiki/Linearizability

V>·>а std::atomic — с т.з. многопоточного исполнения.

V>Для атомарных типов выполняется лишь упорядочивание памяти, актуальное лишь когда в алгоритме более одной расшаренной м/у потоками переменной.
А так же когерентость кешей, например.

V>>>Допустим, у нас есть железо, которое достоверно пишет в память в указанном порядке, тогда в потоке 1 требуется fence() только для компилятора, а не проца.

V>·>Это допущение некорректно с т.з. кода на языке
V>Вообще-то, приводится пример, ЗАЧЕМ нужны разные типы fence, т.е. почему плох одинаковый на все случаи жизни.
V>И это было сказано явно, но ты и этого не понял. ))
Я знаю зачем.

V>·>Это не единственно возможное проявление UB, например, ты проигнорировал покоцанную тобой цитату тут.

V>·>

They would be invalid for a hypothetical machine that is not tolerant of races or provides hardware race detection.


V>would be — условное наклонение.

V>hypothetical — тем более.
V>Т.е. в стандарте явным образом говорится о том, чего не существует.
Это именно то о чём говорит undefined behaviour.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[48]: Безопасность Rust
От: · Великобритания  
Дата: 07.06.19 14:41
Оценка:
Здравствуйте, vdimas, Вы писали:

V>·>Во-первых, "register a" означает сокращение "register int a" (та же шняга с unsigned).

V>Тип int можно не указывать.
V>Так почему именно так?
Пофиг. Решил прикопаться к мелочам? Это не имеет никакого отношения к тезису "int умещается в один регистр".
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[53]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 15:02
Оценка:
Здравствуйте, ·, Вы писали:

·>Я тебе это уже доказал цитатами.


Ты терял признак атомарности, т.е. твои цитаты были нерелевантны обсуждаемому.


V>>>>Data race — означает одновременные попытки читать и писать некие данные, или одновременные попытки писать.

V>>·>Да. И ведёт к undefined behaviour.
V>>Докажи.
·>

If a data race occurs, the behavior of the program is undefined.


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


·>(с) https://www.modernescpp.com/index.php/race-condition-versus-data-race


Учу читать по твоей ссылке, дорого:

Race condition:
A race condition is a situation, in which the result of an operation depends on the interleaving of certain individual operations.

Data race:
A data race is a situation, in which at least two threads access a shared variable at the same time. At least on thread tries to modify the variable.


Вопросы?


V>>Ты споришь с базовой терминологией.

V>>Впрочем, однажды я от тебя подобную жесть уже наблюдал.
·>Я спорю с твоими фантазиями.

Или не понимаешь английского языка.


V>>>>Но может быть и частью алгоритма.

V>>·>Data race не может быть частью корректного алгоритма, т.к. является undefined behaiour и никакие характеристики алгоритма обеспечить не может.
V>>Докажи.
·>

If a data race occurs, the behavior of the program is undefined.

·>(с) https://en.cppreference.com/w/cpp/language/memory_model

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


V>>>>·>Нет. std::atomic гарантирует отсутсвие data race:

V>>>>Только для тех типов, для которых он специализируется с мьютексом унутре.
V>>·>Это твои фантазии.
V>>Докажи.
·>Доказывать твои фантазии? Упаси боже. Ты глупость сказал, ты и доказывай.

Глупости тут говоришь ты.
А моей целью было заставить тебя начать думать.
Начал бы ты думать и обнаружил бы, что для атомарных типов мьютекс в std::atomic не нужен не спроста.
И при этом гарантируется отсутствие гонок.
При том что достоверно известно, что одновременные чтения и запись в переменную идут.
Т.е. прямо согласно определению, это data race.
Или не совсем?


V>>Я хочу сказать, что такой код всегда корректный.

·>Это твои фантазии.

Доказать не в состоянии.
Слился.


V>>Обратное требуется доказать.

·>Корректность кода ты не доказал.

Какого именно?
Покажи строки, которые требуется доказывать?


·>(с) https://en.cppreference.com/w/c/language/atomic


Сравни:
they may be modified by two threads concurrently or modified by one and read by another.
...
A data race is a situation, in which at least two threads access a shared variable at the same time. At least on thread tries to modify the variable.

))


V>>·>Ну запрещено в том смысле, что объявлено как UB.

V>>Объявлено как data race, а не UB.
·>data race всегда UB.

Ты уже сравнил определения выше.
В чём отличия?


V>>>>Вызывать собственный обработчик никем не запрещено.

V>>·>Вызывать можно функцию, а не "обработчик".

Можно и обработчик.


·>Что вызывать код с data race не даёт никаких гарантий.


Не пиши на С/С++.
Ну так-то много где еще пишут даже не на С++11, как так?


V>>·>Это не значит, что они могут шарить данные как хотят.

V>>Могут как хотят.
·>Это твои фантазии.

Реальность.
Современные операционки не используют С++, не используют atomic, а операции навроде exchange, cas и fence используют ну очень редко — в основном для реализации примитивов синхронизации высокого уровня или захвата неатомарного ресурса. Еще для постановки в lock-free очередь.
В остальных случаях обходятся без всего этого прекрасно.
Иначе бы тормозили жутко и ты бы первый их поливал за тормознутость.


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

V>>В стандарте явно говорится о обработчике сигнала, вызываемого из некоего треда процесса.
·>Тред процесса прерывает своё выполнение и обработчик вызывается ядром в контексте этого треда,

Да, и этого достаточно.
Но тред не просто так прерывает своё исполнение, а в очень важный для абстрактной машины состояния процессора момент.
В какой именно момент, ы?


·>притом сам тред на это время "не работает" по очевидным причинам. Это асинхронность, а не многопоточность. Примерно как async/await.


Это примерно как если тупят не по детски.

Это прерывания.
Ты, походу, не понимаешь, что это.
Тут уже любой студент-первокурсник допёр бы, но ты все тупишь...
RTFM!
Re[49]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 15:03
Оценка:
Здравствуйте, ·, Вы писали:

V>>·>Во-первых, "register a" означает сокращение "register int a" (та же шняга с unsigned).

V>>Тип int можно не указывать.
V>>Так почему именно так?
·>Пофиг. Решил прикопаться к мелочам?

Я не прикапываюсь, я даю подсказки.


·>Это не имеет никакого отношения к тезису "int умещается в один регистр".


Имеет. ))
Попробуешь еще раз?
Re[47]: Безопасность Rust
От: vdimas Россия  
Дата: 07.06.19 15:23
Оценка:
Здравствуйте, ·, Вы писали:

V>>·>А у нас ещё есть процессор и всякие его кеши.

V>>Во-во.
V>>Кеши ЧЕГО именно?
·>Кеши процессора. Запись в кеш != запись в память.

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


V>>·>А вот кто является этим сторонним наблюдателем — очень важно.

V>>Ты свои потёки сознания хоть чем-то подтверждать собираешься?
·>

This property of occurring instantaneously, or indivisibly, leads to the use of the term atomic as an alternative to the longer "linearizable"


Выделенное обоснуй, плиз.
Вот есть железо.
Вот ты учился (я так думаю), на техническом ВУЗ-е, т.е. хотя бы начала электроники тебе давали.

Вот давай, распиши сценарий записи значения шириной в машинное слово из одного ядра и чтение этого же машинного слова из другого.
Покажи нам "одновременность" этих событий, плиз.
Как ты это себе представляешь?


V>>·>а std::atomic — с т.з. многопоточного исполнения.

V>>Для атомарных типов выполняется лишь упорядочивание памяти, актуальное лишь когда в алгоритме более одной расшаренной м/у потоками переменной.
·>А так же когерентость кешей, например.

Неужели ты хоть что-то решил прочесть? ))


V>>Т.е. в стандарте явным образом говорится о том, чего не существует.

·>Это именно то о чём говорит undefined behaviour.

Это показывает непонимание сути стандарта.
В том абзаце говорилось о том, что стандарт не может взять на себя кое-какие гарантии, в оправдание приводит пример гипотетической машины (пока не существующей), на которой эти гарантии были бы нарушены.
И там же, в той же главе, делается замечание об атомарных для конкретной платформы типах данных, для которых кое-какие гарантии, таки, соблюдаются.
Я приводил тебе ту цитату дважды, напоминал о ней раз 10.
Но я не должен был тебе ничего напоминать, если бы ты был честен в споре, не бегал бы, не юлил, не выхыватывал из стандарта только то, что тебе удобно, т.е. если бы не резал по цитатам.
Режешь по цитатам? — сливаешь.
Отредактировано 08.06.2019 5:56 vdimas . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.