Jump to content

    
Sign in to follow this  
esaulenka

OS::get_tick_count()

Recommended Posts

Господа, а скажите мне, насколько необходима критическая секция

    INLINE tick_count_t get_tick_count() { TCritSect cs; return Kernel.SysTickCount; }

Я помню о существовании порта на AVR (кто-нибудь пользуется, интересно?..), но для широко распространённых 32-битников можно съэкономить кучку тактов, добавив дефайн наподобие scmRTOS_SYSTEM_TICKS_ATOMIC.

Share this post


Link to post
Share on other sites

А тики могут быть 64-разрядными. А сколько тактов тратится?.. :) Ну, а если серьёзно, надо написать issue, чтобы не забыть. А ещё лучше pull request.

Share this post


Link to post
Share on other sites

Видел правку в репозитории. Вот не согласен я с ней. Дело в том, что анлогично можно не обкладывать критической секцией еще кучу мест, например TEventFlag::clear(); TEventFlag::is_signaled(). Я думаю, что нужно делать какой-то #define или constexpr размера атомарного доступа и обернуть критическую секцию в шаблон с обрабатываемой перемененой в качестве параметра (я пока не знаю, как это сделать). И чтобы если размер переменной в параметре шаблона меньше либо равен размеру атомарного доступа - то шаблон бы разворачивался в ничто, а если больше - в критическую секцию. 

Share this post


Link to post
Share on other sites
6 minutes ago, Сергей Борщ said:

Видел правку в репозитории. Вот не согласен я с ней.

Значит, не зря я начал это обсуждение :-)

 

7 minutes ago, Сергей Борщ said:

Дело в том, что анлогично можно не обкладывать критической секцией еще кучу мест

Угу. Мысль хорошая.

TEventFlag, на мой взгляд, будет работать без критической секции вообще. Булевый флажок влезает в атомарные чтение/запись в любом случае.

А вот для mutex'а, например, стоит придумать что-нибудь. Я не плюсплюс-гуру, но попробую...

Share this post


Link to post
Share on other sites
31 минуту назад, Сергей Борщ сказал:

 И чтобы если размер переменной в параметре шаблока меньше либо равен размеру атомарного доступа - то шаблон бы разворачивался в ничто, а если больше - в критическую секцию. 

Да, вот тоже думал о чём-то вроде этого (просто макрос в лоб - грубо и громоздко), наподобие как в шаблонах traits. Но образования в этой теме не хватает, давно уже плюсизмом не занимаюсь.

Share this post


Link to post
Share on other sites
2 часа назад, Сергей Борщ сказал:

Видел правку в репозитории. Вот не согласен я с ней.

Эх. А я уже тогось, принял эту правку. Не подумал сюда заглянуть сначала. Ладно, пусть пока так будет, а если (когда) появится более универсальное решение, то заменим.

 

2 часа назад, Сергей Борщ сказал:

Я думаю, что нужно делать какой-то #define или constexpr размера атомарного доступа и обернуть критическую секцию в шаблон с обрабатываемой перемененой в качестве параметра (я пока не знаю, как это сделать). И чтобы если размер переменной в параметре шаблона меньше либо равен размеру атомарного доступа - то шаблон бы разворачивался в ничто, а если больше - в критическую секцию. 

Есть же для этого стандартное решение в плюсах -- std::atomic. Но можно и что-то своё наколбасить подобное, если не все компиляторы могут c++11.

 

Share this post


Link to post
Share on other sites

Треды - они и в Африке треды. Конкурентные потоки исполнения. Атомики как раз для этого придуманы. Но надо смотреть, как они конкретно реализованы.

Посмотрел сейчас, во что выливается работа с std::atomic<uint32_t> на кортексах.

Чтение: барьер, чтение, барьер.

Запись: барьер, запись, барьер.

А вот с инкрементом уже посложнее:

80029c6:   f3bf 8f5b   dmb ish
80029ca:   e853 2f00   ldrex   r2, [r3]
80029ce:   3201        adds    r2, #1
80029d0:   e843 2100   strex   r1, r2, [r3]
80029d4:   2900        cmp r1, #0
80029d6:   d1f8        bne.n   80029ca <test1()+0x26>
80029d8:   f3bf 8f5b   dmb ish

Да, думаю, что для тиков это будет перебор.

Share this post


Link to post
Share on other sites

Что-то это какой-то другой тип атомарности. Барьеры - это борьба с проблемами, возникающими из-за конвейеров, а у нас-то критическая секция - это предотвращение ошибок из-за того, что объект сам по себе требует нескольких операций обращения со стороны аппаратуры. Представь, что у тебя объект на кортексе твоём имеет размер больше 32 бит, это потребует как минимум два обращения, и если между ними произойдёт прерывание и переключение в другой процесс, где опять доступ к этому же объекту, то как тут помогут барьеры?

Share this post


Link to post
Share on other sites

Мне было интересно, какие накладные добавятся для типа, который по идее атомарен. Вижу - барьеры (может, у нас они и не нужны, но в компиляторе так заложено, для чипов с кешами и несколькими ядрами). Вижу - аккуратный инкремент с использованием функций исключительного доступа (нам тоже не всегда нужен, например, для tick_count - не нужен). Получается, что именно в плане оптимизации (начальный посыл этой темы) - std::atomic не очень подходит.

Попробовал atomic<uint64_t> - не скомпилировалось (undefined reference to `__atomic_load_8'). Наверное у меня компилятор старый. Так что я не смог увидеть, во что выливается atomic  в случае, когда для доступа к переменной нужно несколько операций.

Share this post


Link to post
Share on other sites
44 минуты назад, AHTOXA сказал:

Попробовал atomic<uint64_t> - не скомпилировалось (undefined reference to `__atomic_load_8'). Наверное у меня компилятор старый. Так что я не смог увидеть, во что выливается atomic  в случае, когда для доступа к переменной нужно несколько операций.

А куда делись инструкции LDRD/STRD/LDM/STM из кортексов?

Share this post


Link to post
Share on other sites

Попробовал. Своих умений не хватило, к сожалению. Спасибо добрым людям из телеграмма pro.cxx

Получилось некоторое нагромождение шаблонов: https://godbolt.org/z/yJiCQS

Слушаю предложения и замечания (а заодно и тесты на не-gcc. У меня под рукой только древний кейл).

Share this post


Link to post
Share on other sites

Если используется #include <type_traits> и auto, то это уже c++11. А если можно c++11, то незачем городить эти шаблоны вручную, там есть std::conditional.

Но вообще, лучше бы, наверное, наоборот, вычистить c++11. Потому что, например, AVR-GCC на godbolt не понимает "-std=c++11". Что там сейчас используется от с++11? std::is_arithmetic и  std::is_enum. Думаю, можно обойтись без.

Ещё такой момент.  max_atomic_size = 4 - это же для ARM-ов. Для AVR-ок будет иначе. Надо как-то унифицировать. Или наоборот, вынести новый класс критической секции в порты, чтобы под каждую архитектуру был свой.

 

ЗЫ. Я, если честно, не представляю, как сейчас всё это тестировать. С IAR-ом большой напряг, AVR-овец и STM8-овец уже давным-давно не появлялся...  MSP-GCC у меня вроде есть, не знаю, насколько актуальный.

Share this post


Link to post
Share on other sites

И ещё не очень понятно, как это по месту использовать, чтобы автоматом оно понимало что с чем сравнивать. Ведь не догадается же компилятор о том, обращения к каким по размеру объектам производится. Это надо будет, получается, как-то указывать руками в каждом случае, что ли. А это уже громоздко и чревато ошибками, имхо.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this