пятница, 1 июля 2016 г.

RTOS: как сделать мир лучше

Слова бы правильные подобрать. Изучал код TNKernel, смотрел FreeRTOS, изучал код TNeo. И тут меня пробило - надо одному единственному человеку объяснить, может остальные повторять не будут. Час пытался сформулировать, что надо объяснить. Час пытался написать письмо, что указать человеку, как не надо писать программы.

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

Тезис 1) на операциях эксклюзивного доступа LDREX/STREX (ARM), LL/SC (MIPS), CAS, ... можно реализовать атомарные неблокирующие операции над словами. Вас не доучили программированию, если вы не знаете что это за операции или не можете реализовать операцию compare_and_exchange на операциях load-linked/store-conditional. Мир меняется с момента появления многопотоковых процессоров каждый программист должен знать что такое синхронизация процессов и на каких операциях это делается. Вы знаете что такое атомарность?
Тезис 2) На атомарных операциях типа load-linked/store-conditional можно сделать "семафор" неблокирующий, без запрещения прерываний, без вызова функций или системных прерываний.
Тезис 3) Мьютекс - это бинарный семафор.
Тезис 4) На атомарных операцих можно сделать очередь без блокирования доступа к очереди. Можно сделать односвязный список.
Тезис 5) Можно сделать неблокирующее выделение памяти. Распределение памяти можно сделать на операциях атомарных. Память - это либо список, либо массив. Выделение из массива делается на битовых атомарных операциях и на счетчиках типа семафор.
Тезис 6) Общение между процессорами в многопроцессорной многопотоковой системы можно сделать на очереди типа MessageQueue, а ее можно сделать на атомарных операциях.


Процессор - это такая скотина, которая обеспечивает атомарность операций на памяти, инвалидит кеш, если он есть. Со времен процессоров Alfa многоядерные процессоры умеют друг с другом обмениваться флагами инвалидности памяти, операция LL/SC действительно инвалидит кеш соседнего процессора для заданной ячейки памяти. Иногда нужны операции -- барьеры памяти, это нужно чтобы операции, которые могут выполняться  произвольном порядке были выполнены к заданном моменту. Например бывает важно сначала выполнить все операции, а потом помахать флагом соседнему процессу, сообщая о готовности, или выполнить все операции до вызова системного прерывания. Оптимизация компилятора может менять порядок выполнения операций. Чтобы этого не происходило, операции выставления флагов готовности надо оформлять барьерами для компилятора. Чтобы не писать, где попало в коде барьеры памяти, барьеры исполнения кода, надо это сделать в одном месте atomic_get, и сразу при выходе из цикла атомарной операции. В языке Си есть такое слово volatile. Кто знает зачем это слово? Кто нибудь знает зачем нужна операция CLREX для процессоров Cortex? Есть на свете хоть один программист, который ее использовал по назначению? Есть ситуация, когда операция strex может на конвейере процессора обогнать операцию ldrex? Зато есть публицисты, которые рекомендуют вставлять операцию clrex до выхода из прерывания и вставлять операцию барьера исполнения после выхода из атомарной операции. Что будет если две пары операций ldrex и strex из разных потоков пересекутся? Правда ли нужно при выходе из прерывания вставлять clrex?

Комментариев нет:

Отправить комментарий