Примитивы синхронизации

8-битные микроконтроллеры AVR (AT90, ATtiny, ATmega) от Atmel (в настоящий момент принадлежит Microchip)

Moderator: Shaos

User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Примитивы синхронизации

Post by masterspammer »

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

Задача - взаимодействия кода из прерываний и "основного цикла" через общую память (флаги, счётчики).
Хочется счётчик 16 бит, устанавливаемый флаг и возможно буфер.
Прерывания запрещать нельзя :-(
User avatar
Shaos
Admin
Posts: 24011
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Примитивы синхронизации

Post by Shaos »

А зачем мьютексы то? Мультитредности то нету :)
Есть обработчик прерывания и основная программа - они обе могут использовать одни и те же переменные
Всё просто :)
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

Нормальной может и нету, но параллельные "потоки" выполнения вполне есть.

Пример: основной цикл дрючит какой-то медленный процесс, например читает UART,
прерывания быстро выводят данные куда-то наружу, пусть на VGA :trollface:

Взаимодействие этих "потоков" на примере счётчика - пусть он увеличивается при чтении с UART и иногда уменьшается при выводе.

1. цикл - читает в регистр значения ячейки счётчика (дальше хочет сравнивать)
2. тут "врывается" прерывание, меняет значение счётчика, оканчивается
3. цикл продолжает работу с уже неверным значением.

Логично, что прерыванию хорошо бы "знать" что тут счётчик занят и не трогать его, нужен какой-то флаг, который атомарен и с ним самим не случиться той же неприятности, что случилась с ячейкой счётчика.
User avatar
Shaos
Admin
Posts: 24011
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Примитивы синхронизации

Post by Shaos »

Ну UART это не такая уж медленная штука, если нормальные скорости делать...
Есть же команды запрещения-разрешения прерываний - надо тебе из основной программки поюзать общий счётчик - запрещаешь прерывания и юзаешь
А обработчик прерывания может трогать счётчик когда захочет т.к. он сам отдаёт управление, когда всё сделал
И никаких мьютексов
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

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

Костыльно можно сделать так:

1. цикл устанавливает флажок (хоть в памяти, хоть в регистре)
2. цикл обрабатывает конфликтный ресурс
3. цикл сбрасывает флажок
4. цикл делает все остальные дела

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

---

Вопрос - можно ли как-то реализовать не так костыльно и более общим случаем?
Mixa64
Doomed
Posts: 480
Joined: 25 Aug 2009 07:02
Location: Москва

Re: Примитивы синхронизации

Post by Mixa64 »

"Костыль" ПМСМ начинается уже тут
masterspammer wrote:Прерывания запрещать нельзя
, а не тут :) :

Костыльно можно сделать так:

1. цикл устанавливает флажок (хоть в памяти, хоть в регистре)
2. цикл обрабатывает конфликтный ресурс
3. цикл сбрасывает флажок
4. цикл делает все остальные дела
, которое, вообще-то, уже не костыль сам по себе, а вполне разумный подход в сложившихся обстоятельствах.

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

---
Вопрос - можно ли как-то реализовать не так костыльно и более общим случаем?
Более общий случай - это как раз что-то типа enterCritical() и exitCritical() , внутри этих скобок обрамление из запрета и разрешения прерываний.

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

А так, DMA еще бывает, если что.
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

Mixa64 wrote:"Костыль" ПМСМ начинается уже тут
masterspammer wrote:Прерывания запрещать нельзя
, а не тут :)
...
Во многих архитектурах можно без прерывания, может и у AVR можно (но я не знаю как)?
Mixa64 wrote: Более общий случай - это как раз что-то типа enterCritical() и exitCritical() , внутри этих скобок обрамление из запрета и разрешения прерываний.
Скорее из сохранения состояния прерываний и восстановления - кто сказал, что они запрещены? Да, там кроме прерываний ещё и сам макрос быть должен какой-то.
Mixa64 wrote:То есть, вы, вероятно, считаете костылем то, что при таком вынужденном подходе прерывание будет иногда отрабатываться вхолостую, если случается, что ресурс трогать нельзя.
Не, тем, что этот подход только для данного примера пригоден. А вот если вообразить какой-нибудь "диспетчер", получающий управление по прерыванию от одного кода, а возвращающий в другой (примитивная такая многозадачность), то так уже не выйдет, там при попытке получить семафор управление должно передаваться другим "потокам" до освобождения.
Mixa64 wrote: А так, DMA еще бывает, если что.
Xmega?
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

Mixa64 wrote: Более общий случай - это как раз что-то типа enterCritical() и exitCritical() , внутри этих скобок обрамление из запрета и разрешения прерываний.
типа как тут?
https://github.com/chrismoos/avr-os/blo ... rm/arm11.c
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

Хотя по аналогии с реализацией spinlock на обмене регистра с памятью можно сделать на инкременте / декременте регистра (регистр будет занят всегда, увы):
(псевдокод для варианта - попытаться или обломаться без ожидания; в регистре единица)
if(! --reg){
do_crytical()
}
reg++

при попытке кучи "потоков" уменьшить регистр только один получит 0, а остальные - FF или чуть меньше, но быстро вернут назад.
Mixa64
Doomed
Posts: 480
Joined: 25 Aug 2009 07:02
Location: Москва

Re: Примитивы синхронизации

Post by Mixa64 »

Я всего лишь хотел сказать, что запреты и разрешения прерываний это обычная практика, а если запретить запреты прерываний, то тут уж хозяин барин.
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

Mixa64 wrote:Я всего лишь хотел сказать, что запреты и разрешения прерываний это обычная практика, а если запретить запреты прерываний, то тут уж хозяин барин.
Вопрос был и теоретический тоже - поинтересовавшись, как на разных платформах реализуют тот же spinlock (как правило без запрета прерываний), я не придумал, как сделать на AVR, потому и спросил.

P.S. В моём практическом примере классический (ожидающий) семафор приведёт как раз к зависанию :-)
User avatar
Shaos
Admin
Posts: 24011
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Примитивы синхронизации

Post by Shaos »

Если очень хочется "запретить запреты прерываний", то надо заводить атомарный флаг доступа (семафор?) где неделимы были бы инкремент/декремент и сравнение (иначе прерывание может между ними проскочить) - в авре вроде есть косвенный доступ к регистрам с постинкрементом (или предекрементом) индексного регистра одной инструкцией - возможно это как-то удастся задействовать?...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

Shaos wrote:...то надо заводить атомарный флаг доступа (семафор?) где неделимы были бы инкремент/декремент и сравнение...
Про то и речь и ничего кроме физического регистра (который на 100% занят этим и только этим) в голову не пришло.
Shaos wrote: ...в авре вроде есть косвенный доступ к регистрам с постинкрементом (или предекрементом) индексного регистра одной инструкцией - возможно это как-то удастся задействовать?...
Типа "LD rx, Z+"? Тут 100% не выйдет, значение памяти не меняется, если параллельно (в прерывании) другой код сделает тоже самое, друг на друга они не повлияют - ну только если не глобально запретить использовать Z для чего-то ещё другого и тогда получится ровно то же, что я писал про регистр, только чуть сложнее (потребуется кусок памяти с одной единичкой и каким-то списком нулей после).
User avatar
Shaos
Admin
Posts: 24011
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Примитивы синхронизации

Post by Shaos »

А вообще AVR это не та платформа, на которой следует экспериментировать с многозадачностью...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
masterspammer
Fanat
Posts: 95
Joined: 13 Dec 2020 21:11

Re: Примитивы синхронизации

Post by masterspammer »

Shaos wrote:А вообще AVR это не та платформа, на которой следует экспериментировать с многозадачностью...
А вы отдаёте себе отчёт, что на этом форуме такие слова звучат как вызов? :-)

С многозадачностью, правда, хочу поиграть на Z80 (который пошустрее из новых), но чем AVR не то?