Rst7 5 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 4 minutes ago, esaulenka said: Объясните, пожалуйста. Например непонимание работы exclusive monitor'а ядра тут: Quote Если между LDREX и STREX произошло прерывание и оно что-то записало в память (а оно обязательно хоть регистры, да сохранит в стек), то STREX ничего не запишет в память и в выходной регистре будет записана 1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 4 minutes ago, Rst7 said: Например непонимание работы exclusive monitor'а ядра тут: Это прямая цитата из статьи изиэлектроникса, которую написал @neiver. Вполне грамотный дядька, я б ему тоже поверил. Зря... Его там ниже поправили, но в самой статье ничего не поменялось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба Когда мы в прошлый раз проверяли всё это дело практически, то выяснили, что прерывания таки сбрасывают флаг экслюзивного доступа, даже если в обработчике ничего не делается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 17 minutes ago, AHTOXA said: что прерывания таки сбрасывают флаг экслюзивного доступа, даже если в обработчике ничего не делается. Я не об этом. Обычная запись в память (или чтение) между LDREX/STREX не сбрасывает флаг. volatile unsigned int testvar; volatile unsigned int testvar2; void TestEX(void) { unsigned int tv; tv=__LDREX(&testvar); __no_operation(); __no_operation(); __no_operation(); testvar2=1; testvar2; __no_operation(); __no_operation(); __no_operation(); tv=__STREX(tv,&testvar); DEBUG_PRINTF("__STREX result %d\r\n",tv); } Такой код печатает "__STREX result 0", несмотря на наличие LDR/STR между LDREX/STREX. То, что заход в прерывания сбрасывают флаг- это какой-то отдельный тонкий момент, с ним надо разбираться, потому что в теории так быть не должно. Ага, вот в чем дело (из мануала на CM4) Quote The processor removes its exclusive access tag if: • It executes a CLREX instruction. • It executes a Store-Exclusive instruction, regardless of whether the write succeeds. • An exception occurs. This means the processor can resolve semaphore conflicts between different threads. Т.к. прерывания - это тоже эксепшн, то вот и ответ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба Кстати, это только к Cortex-M относится, всякие -А вроде не сбрасывают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 1 час назад, haker_fox сказал: Как я понимаю, зависит от little или big-endian. Во всяком случае заголовчники для микроконтроллеров строятся на этом принципе и работают. Более того, обмениваемся битовыми полями, изготовленными двумя разными компиляторами: IAR и GCC. Но за документ спасибо! Но, на удивление, работает. А что вы используете вместо полей? Кстати я использую поля активно не только для доступа к регистрам. Очень удобная штука. Пока не подводила. Не совсем, компилятор может выбрать какой-то способ, по своей логике. В этом огромная разница между стандартом и практикой. На практике много чего работатет из того что не обязано работать. Проблема в том что оно работает здесь и сейчас, но может перестать работать потом, при изменении версии компилятора, портировании куда-то, просто потому что оптимизатору что-то показалось. И любой такой случай приводит к затратам времени на поиск проблемы. Постепенно убираю их из своих исходников в пользу дедовских сдвигов и битовых операций. Естетсвенно стараюсь обернуть это в разумные сервисные функции с логическим смыслом, без портянок в более высокоуровневом коде. Думал над темплейт-класс магией, но морально пока не созрел. 38 минут назад, Rst7 сказал: Я не об этом. Обычная запись в память (или чтение) между LDREX/STREX не сбрасывает флаг. Ага, вот в чем дело (из мануала на CM4) Эээ т.е. если просто записать в тот же адрес STR'ом вся схема сломается? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 1 час назад, Rst7 сказал: Я не об этом. Обычная запись в память (или чтение) между LDREX/STREX не сбрасывает флаг. Да, обычная запись не сбрасывает. Но всё же объяснение Цитата Если между LDREX и STREX произошло прерывание и оно что-то записало в память... - верно описывает результат. Хотя причины объясняет неверно :-) 40 минут назад, Kabdim сказал: Эээ т.е. если просто записать в тот же адрес STR'ом вся схема сломается? Естественно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба Жесть, насколько же x86 в этом аспекте прямолинейно правильней. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба Дык, RISC vs CISC. Не удивлюсь, если в x86 где-то на уровне микрокода всё делается примерно так же, через какие-то свои LDREX/STREX :-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба Нет, там физически нельзя всунуть в середине обработки обращение к тем данным к которым происходит атомарный доступ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 2 часа назад, Kabdim сказал: Жесть, насколько же x86 в этом аспекте прямолинейно правильней. В чём правильней? И что неправильного в механизме LDREX/STREX? Вроде там всё предельно ясно и логично. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 2 hours ago, AHTOXA said: - верно описывает результат. Хотя причины объясняет неверно :-) Верно описывает результат только для Cortex-M. Потому что объяснение неверное. 3 hours ago, Kabdim said: Эээ т.е. если просто записать в тот же адрес STR'ом вся схема сломается? А зачем писать в переменную, к которой Вы организуете эксклюзивный доступ, обычным способом? 2 hours ago, Kabdim said: Жесть, насколько же x86 в этом аспекте прямолинейно правильней. Только менее универсальный. Например, взять элемент из списка на ARM выглядит так: #define ExAddr(VAL) ((volatile unsigned int *)(&(VAL))) typedef struct LLITEM { struct LLITEM *next; unsigned char data[100]; }LLITEM; volatile LLITEM *FreeBlocks; LLITEM *AllocBlock(void) { LLITEM *p; LLITEM *next; do { p=(LLITEM*)__LDREX(ExAddr(FreeBlocks)); if (!p) {__CLREX(); return p;} next=p->next; }while(__STREX((unsigned long)next,ExAddr(FreeBlocks))); return p; } Spoiler 163 LLITEM *AllocBlock(void) 164 { \ AllocBlock: (+1) \ 0x0 0x.... 0x.... LDR.W R2,??DataTable6_1 165 LLITEM *p; 166 LLITEM *next; 167 do 168 { 169 p=(LLITEM*)__LDREX(ExAddr(FreeBlocks)); \ ??AllocBlock_0: (+1) \ 0x4 0xE852 0x0F00 LDREX R0,[R2] 170 if (!p) {__CLREX(); return p;} \ 0x8 0xB128 CBZ.N R0,??AllocBlock_1 171 next=p->next; 172 }while(__STREX((unsigned long)next,ExAddr(FreeBlocks))); \ 0xA 0x6803 LDR R3,[R0, #+0] \ 0xC 0xE842 0x3100 STREX R1,R3,[R2] \ 0x10 0x2900 CMP R1,#+0 \ 0x12 0xD1F7 BNE.N ??AllocBlock_0 173 return p; \ 0x14 0x4770 BX LR ;; return \ ??AllocBlock_1: (+1) \ 0x16 0xF3BF 0x8F2F CLREX \ 0x1A 0x4770 BX LR 174 } А на x86 с его единственным lock'ом надо извращаться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 52 минуты назад, jcxz сказал: В чём правильней? И что неправильного в механизме LDREX/STREX? Вроде там всё предельно ясно и логично. Тем что его нельзя сломать, даже если захочется. 46 минут назад, Rst7 сказал: на x86 с его единственным lock'ом надо извращаться. Есть такое. Если бы load/store гарантировали что их нельзя сломать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 21 февраля, 2020 Опубликовано 21 февраля, 2020 · Жалоба 5 minutes ago, Kabdim said: Если бы load/store гарантировали что их нельзя сломать... В смысле? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamer0k 0 21 февраля, 2020 Опубликовано 21 февраля, 2020 (изменено) · Жалоба Мое понимание такое, что если между LDREX и STREX было прерывание, то STREX не сработает, потому что при каждом входе и выходе из прерывания выполняется CLREX. Изменено 21 февраля, 2020 пользователем lamer0k Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться