+3
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
// https://deadlockempire.github.io/
// Игра, где надо играть за планировщик чтоб вызвать дедлок
// https://deadlockempire.github.io/#2-flags
// First Army
while (true) {
while (flag != false) {
;
}
flag = true;
critical_section();
flag = false;
}
// Second Army
while (true) {
while (flag != false) {
;
}
flag = true;
critical_section();
flag = false;
}
The day finally came. The Deadlock Empire opened its gates and from them surged massive amounts of soldiers, loyal servants of the evil Parallel Wizard. The Wizard has many strengths - his armies are fast, and he can do a lot of stuff that we can't. But now he set out to conquer the world, and we cannot have that.
You are our best Scheduler, commander! We have fewer troops and simpler ones, so we will need your help. Already two armies of the Deadlock Empire are approaching our border keeps. They are poorly equipped and poorly trained, however. You might be able to desync them and break their morale.
Запостил: j123123,
20 Февраля 2021
guest6 20.02.2021 03:20 # 0
армия:строка
1:9
2:20
1:12
2:23
1:13
2:24
еблысь
guest6 20.02.2021 13:48 # 0
если во круг флага нет заборов, то он по идее может остаться в буфере ЦПУ, и в теории армия1 вообще никогда не узнает, что его изменила армия2.
bormand 20.02.2021 14:03 # 0
Да и flag = true с flag = false может слипнуться ещё во время конпеляции.
З.Ы. Угу, gcc от всей этой хуйни только внешний while (1) оставил.
MAPTbIwKA 20.02.2021 15:36 # 0
volatile нужно пхать, да?
bormand 20.02.2021 15:39 # +1
guest6 20.02.2021 15:40 # 0
я думал, что это volatile.
Срать может как и другое ядро, так и железо. просто в случае с другим ядром этого НЕДОСТАТОЧНО, потому что код-то он не выкинет, но гонка останется
или нет?
bormand 20.02.2021 15:50 # +1
Атомик втыкает барьеры, но не запрещает оптимизировать обращения. Они могут слипнуться если это никому не ломает happens before.
MAPTbIwKA 20.02.2021 15:54 # 0
Я имел ввиду, что volatile хоть и не сделает код корректным, но гарантирует, что его хотя-бы не выкинут.
Потому что без волатайла тут написано ``while(true){}``
Разумеется, обращение к переменной из двух потоков нужно синхронизировать барьером.
CEHT9I6PbCKuu_nemyx 10.09.2021 03:53 # 0
j123123 20.02.2021 15:49 # 0
Допустим есть микроконтроллер с одним ядром, есть некая глобальная volatile переменная, которая может читаться/писаться в обработчике прерывания и в обычном коде. Допустим, переменная там 64-битная, а инструкции записи байтиков в память есть максимум на 32 бит, и вот в коде мы наполовину перезаписали volatile переменную новым значением, и тут хуяк - обработчик прерывания. А в переменной вообще хуйня какая-то непредусмотренная
MAPTbIwKA 20.02.2021 15:50 # 0
Выходит, что запись в такую переменную это критическая секция, и нужно маскировать прерыввания на время записи, не?
bormand 20.02.2021 15:52 # 0
MAPTbIwKA 20.02.2021 15:55 # +1
У нас в жабке эти две концепции слиты воедино, нам проще
bormand 20.02.2021 17:16 # 0
Но, насколько я помню, для x.store(42); x.store(100500) конпелятор и проц имеют право выкинуть первую инструкцию. Порядок это не ломает, сторонний наблюдатель просто подумает, что он пиздец невезучий, раз никогда не видит там 42.
j123123 20.02.2021 16:12 # +2
> ... That is all we need for what volatile is intended for: manipulating I/O registers or memory-mapped hardware, but it doesn't help us in multithreaded code where the volatile object is often only used to synchronize access to non-volatile data. Those accesses can still be reordered relative to the volatile ones.
volatile вообще нехуй так использовать, компилятор имеет право всякое говно между этими volatile переставлять
https://godbolt.org/z/Pad3n5
- вот например оно два инкремента не-volatile глобальной переменной спихнуло в одну инструкцию после всей волатильной питушни
bormand 20.02.2021 16:16 # +1
MAPTbIwKA 20.02.2021 16:22 # 0
например
volatile_crap++
нельзя свернуть в volatile_crap += 2
а регулярный можно.
j123123 24.02.2021 09:19 # +2
И потом дальше делать как обычно.
guest6 24.02.2021 10:11 # +1
bormand 24.02.2021 15:58 # 0
guest6 24.02.2021 16:11 # +1
bormand 24.02.2021 16:25 # +2
interrupt_safe_atomic<uint64_t> x;
x = 42;
bormand 20.02.2021 16:31 # +1
MAPTbIwKA 20.02.2021 16:33 # 0
А если у CPU есть атомарная инструкция для этого?
bormand 20.02.2021 16:34 # +1
MAPTbIwKA 20.02.2021 16:35 # 0
В жабке есть AtomicInteger например
bormand 20.02.2021 16:44 # 0
MAPTbIwKA 20.02.2021 16:51 # 0
это std::atomic дает такую гарантию?
Потому что если я просто использую атомарную иструацию цепеу, то мне это не поможет.
PetuhCountAtomicIncrement()
SendDataToIoPort()
PetuhCountAtomicIncrement()
если питух не волатилен, то что мешает компилятору сделать
PetuhCountAtomicIncrement()
PetuhCountAtomicIncrement()
SendDataToIoPort()
?
bormand 20.02.2021 16:57 # 0
j123123 20.02.2021 16:54 # +1
> 8.1.1 Guaranteed Atomic Operations
>
> The Intel486 processor (and newer processors since) guarantees that the following basic memory operations will always be carried out atomically:
>
> •Reading or writing a byte
> •Reading or writing a word aligned on a 16-bit boundary
> •Reading or writing a doubleword aligned on a 32-bit boundary
>
> The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
>
> •Reading or writing a quadword aligned on a 64-bit boundary
> •16-bit accesses to uncached memory locations that fit within a 32-bit data bus
>
> The P6 family processors (and newer processors since) guarantee that the following additional memory operation will always be carried out atomically:
>
> •Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line
т.е. никакого xadd не надо для атомарности инкремента, если адрес записи выровнен по нужной границе
j123123 20.02.2021 16:58 # 0
bormand 20.02.2021 17:01 # 0
Емнип, на практике не атомарный add ещё как плющит из нескольких потоков.
j123123 21.02.2021 05:01 # +1
MAKAKA 21.02.2021 05:41 # +1
Понятное дело, что обычный поток кода не может выполняться, пока выполняется прерывание в одноядерной системе) Это я еще со времен доса помню.
А как именно код и обработчик прерывания достукиваются до этой глобалки?
Если это просто какое-то место в памяти, то разве не нужно его поменчать как volatile? компилятор же выкинет иначе нафиг всё, нет?
j123123 21.02.2021 06:07 # 0
По адресу памяти, очевидно.
> Если это просто какое-то место в памяти, то разве не нужно его поменчать как volatile?
Нет, зачем?
> компилятор же выкинет иначе нафиг всё, нет?
С чего б ему выкидывать что-то?
guest6 21.02.2021 06:11 # 0
*p = 1;
он видит, что автматическая переменная p нигде не испльзуется, и выкидывает ее
или нет?
j123123 21.02.2021 06:29 # 0
j123123 21.02.2021 06:35 # 0
то запись байтика по адресу 0xAABBCCDD у тебя нихуя выкидываться не будет
j123123 21.02.2021 06:48 # 0
то если в вызов shit3 заинлайнивается вся хуйня и компилятор это заоптимизирует, то запись в glob_var там будет только одна, ибо нехуй лишний раз ворошить память. И если shit3() это какой-то обработчик прерываний, то "применить" изменения глобалок надо тогда, когда весь этот обработчик завершится, так что по итогу там будет 1337 и никакие предыдущие записи в глобалку нахуй не нужны, раз обработчик никто на полпути не прервет. Но если glob_var это какая-то хуйня типа MMIO и там особая хуйня должна происходить при записи говна по таким-то адресам, то тогда вот можно volatile юзать
3_dar 21.02.2021 13:06 # 0
MAKAKA 21.02.2021 14:37 # 0
автоматические переменные никто не видит, но так как память-то у нас не в стеке, то запись в нее нельзя выкидывать
выкинуть
*a = 51;
он может только если потом идет
*a = 52
и тут нужен волатил
bormand 21.02.2021 06:44 # 0
Если насрать в глобалку и выйти -- конпелятор обязан сохранить такой эффект. Он даже отложить его на попозже его не может т.к. ISR никуда не инлайнится.
MAKAKA 21.02.2021 15:16 # 0
запись в глобалку нельзя отменить, можно только схлопнуть две записи
j123123 21.02.2021 06:59 # 0
Оно вполне может вытеснять, важно чтоб оно не конфликтовало, т.е. не ворошило те же самые глобалки, с которыми то прерывание имеет дело.
Desktop 21.02.2021 12:57 # 0
bormand 21.02.2021 13:01 # 0
Desktop 21.02.2021 13:14 # 0
bormand 21.02.2021 13:18 # 0
Desktop 21.02.2021 13:20 # 0
guest6 21.02.2021 13:20 # +1
Desktop 21.02.2021 13:23 # 0
bormand 21.02.2021 06:54 # +1
В том же "uefi" таймерное прерывание может само себя прервать 4-5 раз. Такие вот дела.
MAKAKA 21.02.2021 15:15 # 0
bormand 20.02.2021 15:27 # 0
MAPTbIwKA 20.02.2021 15:37 # 0
понятно
bormand 20.02.2021 08:14 # 0
Congratulations, you have triggered deadlocks in same way normal CPUs do!
hormand 20.02.2021 21:58 # 0
hormand 21.02.2021 13:23 # 0
hormand 21.02.2021 21:16 # 0
3.14159265 10.09.2021 02:41 # 0