-
31. Data: 2023-02-16 13:20:42
Temat: Re: C++ ośla łączka
Od: Piotr Gałka <p...@c...pl>
W dniu 2023-02-15 o 19:50, heby pisze:
> I nagle chcesz odczytywać wewnatrzny status CPU, co do którego nie ma
> nawet pewności, że istnieje na jakiejś architekturze sprzętowej, ani jak
> działa w konkretnym przypadku. To proszenie się o katastrofę. Od tej
> pory C musiał by być *tylko* na procesory z flagą C i to w dodatku
> działającą w jakiś specyficzny sposób. A jak jej nie ma wcale?
Akurat brat przyszedł do mnie z pytaniem, jak coś zrobić w C (o tym
dalej bo ja nie znam odpowiedzi ale powiedziałem mu, że zapytam
mądrzejszych ode mnie) więc wspomniałem mu o tym co tu napisałem o bicie
przeniesienia, czy parzystości.
On ma całkiem odmienne zdanie od Twojego.
Nie widzi żadnego problemu, aby w C dla zmiennych całkowitych było na
przykład pojęcie bitu parzystości. Jak procesor go ma to kompilator
korzysta bezpośrednio, a jak nie ma to wtedy wylicza tak jak ja w tej
crc16().
Gdzie tu proszenie się o katastrofę?
A....
Nie wspomniałem mu o różnych reprezentacjach zmiennych o których pisałeś
z czego on (tak jak i ja) całkowicie nie zdaje sobie sprawy. Ale
faktycznie są stosowane jakieś inne reprezentacje?
A teraz pytanie brata na które nie znamy odpowiedzi.
Ogólnie to jest pierwsze podejście do procesorów ARM (nie wiem z którym
w tej chwili walczy (Silabs EFM32PG22..., EFM32PG23..., a może EFM32TG11..).
Zanim użyje procesor po raz pierwszy musi opanować podstawowe działania
no i jest właśnie na tym etapie.
On by potrzebował sizeof(funkcja).
Ale jak próbuje to zrobić to dostaje 1.
Zasugerowałem, że może jak wstawi etykietę (przypomnieliśmy sobie, że
chyba w C coś takiego jest) na nawiasie zamykającym funkcję to uda się
policzyć różnicę między jej adresem a adresem początku funkcji.
Właśnie mi krzyknął (jego pokój jest piętro niżej), że z zewnątrz
funkcji nie ma dostępu do tej etykiety.
Napiszę do czego mu to potrzebne bo czasem może rozwiązanie głównego
problemu robi się inaczej niż on kombinuje.
Wczoraj wieczorem wspólnie tłumaczyliśmy dwa akapity datasheet, czy
manuala (nie wiem - on mi po prostu podświetlił akapit na ekranie i
chodziło o to jak to rozumiemy).
Tam było, że jak się coś robi z programowaniem flasha z wnętrza programu
to ogólnie nie ma gwarancji, że wszystko się uda. I to zdanie było
ogólne - czyli nawet jak ruszasz inną stronę niż jesteś to może coś nie
zadziałać. Nie napisali co dokładnie, ale skoro może coś się nie udać to
my tego nie chcemy. Napisali, żeby przekopiować odpowiednią funkcję do
RAMu, wywołać ją i z niej uruchomić proces kasowania, czy programowania
flasha.
Już opanował wywoływanie funkcji po jej skopiowaniu do RAMu.
Z adresem początku sobie radzi, choć mówi, że wskaźnik na funkcję jest
zawsze większy o 1 od prawdziwego adresu i ustalając fragment do
kopiowania on musi tę jedynkę odejmować.
Wszystko już działa, tylko, że na razie rozmiar funkcji bierze z sufitu
na zapas.
No i jedyne co brakuje do odhaczenia kolejnej funkcjonalności to
ustalenie w jednej funkcji jaki jest sizeof drugiej funkcji.
Może wiesz (lub ktoś inny) jak to się robi.
P.G.
-
32. Data: 2023-02-16 13:45:45
Temat: Re: C++ ośla łączka
Od: heby <h...@p...onet.pl>
On 16/02/2023 12:46, Grzegorz Niemirowski wrote:
>> Do tego, co piszesz, służa bariery/fence.
> Możesz podać przykład na ATmegę?
Nie. Bo mowa o C ogólnie. Szczególne dla AVR stosujemy sztuczki
asemblerowe, nielegalne w danej sytuacji słowa kluczowe itd itp. Sam
fakt użycia "przerwania" jest z definicji nieistniejącym bytem w C i
wymaga poza-językowych narzędzi, bo sam język nie dostarcza wsparcia dla
przerwań wiec trudno tez, aby dostarczał mechnizmy ich wspierania.
Uwaga o volatile dotyczy *języka* C a nie implementacji tego na AVR.
Jeśli pytałbyś o ogólny C++ to zasugeroeałbym okolice:
https://mariadb.org/wp-content/uploads/2017/11/2017-
11-Memory-barriers.pdf
Czy poprawna implementacja na AVR istnieje - nie wiem. Może kiedyś zerknę.
>> Jeśli potraktujesz przerwania jako wątki preemptive, to tak naprawdę
>> piszesz o zagadnieniu dostępu do zmiennych przez kilka watków. Tego
>> zagadnienia *NIE* należy rozwiązywać za pomocą volatile, ono nie
>> powstało do tego i sie do tego NIE nadaje.
> Wiem. Nic o wątkach nie pisałem.
Mimo to przerwanie jest czymś identycznym z wątkiem preemptive. Ma te
same konsekwencje i dla dużych procesorów, szczególnie wielordzeniowych,
niesie z sobą dokładnie te same zagrożenia, co wątki. I nie jest tak, że
świat kończy się na 8051. Wielordzeniowe procesory embedded to nic
specjalnie dziwnego.
Tam, wszyscy programiści od volatile, wybiją sobie zęby o protokoły
synchronizacji cache, out-of-order execution itd itp.
PS. Zaznaczam, że nic nie pisałeś o AVR w poprzednim poście, wiec w
ogólnym wypadku, volatile nie może i nie powinno być uzywane w celu
synchronizacji zmiannych w przerwaniach. W szczególnym, kiedy znasz
konkretną architekturę, być może.
-
33. Data: 2023-02-16 13:54:54
Temat: Re: C++ ośla łączka
Od: heby <h...@p...onet.pl>
On 16/02/2023 13:20, Piotr Gałka wrote:
> Nie widzi żadnego problemu, aby w C dla zmiennych całkowitych było na
> przykład pojęcie bitu parzystości. Jak procesor go ma to kompilator
> korzysta bezpośrednio, a jak nie ma to wtedy wylicza tak jak ja w tej
> crc16().
A do czego to potrzebne przeciętnemu suwerenowi? Z tej samej przyczyny w
C nie ma gotowej funkcji do wygrywania melodyjek na głośniczku podpiętym
pod PB.3. Jest dosłownie 3 osoby na świecie z tą potrzebą.
Dodakowo: jak liczysz parzystość?
Czy -0 i +0 są, czy nie, parzyste? Przypadkowo zakładajmy architekturę
wspierajacą signed-magnitude albo 1-complement. Oba dopuszczalne w C. W
obu występują dwa zera.
> Gdzie tu proszenie się o katastrofę?
W tym, że standard nie definiuje nawet reprezentacji bitowej liczb.
Skoro tak, to niby jak miałby określać znacznie głębsze detale jak
parzystość, przeniesienie czy cokolwiek detalicznego i związanego z
konkretną architekturą?
> A....
> Nie wspomniałem mu o różnych reprezentacjach zmiennych o których pisałeś
> z czego on (tak jak i ja) całkowicie nie zdaje sobie sprawy. Ale
> faktycznie są stosowane jakieś inne reprezentacje?
Nie są w praktyce, poza małymi wyjątkami.
Ale standard nie przejmuje się, czy są stosowane, czy nie. Są
dopuszczalne, wiec nie możesz zakładać, że nie mogą istnieć. Standard
nie może ich ignorować.
> On by potrzebował sizeof(funkcja).
[...]
> Już opanował wywoływanie funkcji po jej skopiowaniu do RAMu.
Czytaj wątek z przed paru dni:
"MCU - start programu z RAM"
> Z adresem początku sobie radzi, choć mówi, że wskaźnik na funkcję jest
> zawsze większy o 1 od prawdziwego adresu i ustalając fragment do
> kopiowania on musi tę jedynkę odejmować.
> Wszystko już działa, tylko, że na razie rozmiar funkcji bierze z sufitu
> na zapas.
> No i jedyne co brakuje do odhaczenia kolejnej funkcjonalności to
> ustalenie w jednej funkcji jaki jest sizeof drugiej funkcji.
> Może wiesz (lub ktoś inny) jak to się robi.
Było to omawiane w tym wątku. Ogólnie, jesli ma to związek z
programowaniem flasha, to boje się zapytać, czy jakoś się zabezpieczacie
prze utratą zasilania w trakcie.
-
34. Data: 2023-02-16 14:35:09
Temat: Re: C++ ośla łączka
Od: "J.F" <j...@p...onet.pl>
On Thu, 16 Feb 2023 13:45:45 +0100, heby wrote:
> On 16/02/2023 12:46, Grzegorz Niemirowski wrote:
>>> Do tego, co piszesz, służa bariery/fence.
>> Możesz podać przykład na ATmegę?
>
> Nie. Bo mowa o C ogólnie. Szczególne dla AVR stosujemy sztuczki
> asemblerowe, nielegalne w danej sytuacji słowa kluczowe itd itp. Sam
> fakt użycia "przerwania" jest z definicji nieistniejącym bytem w C i
> wymaga poza-językowych narzędzi, bo sam język nie dostarcza wsparcia dla
> przerwań wiec trudno tez, aby dostarczał mechnizmy ich wspierania.
W standardzie jezyka niby nie ma, ale w praktyce czesto jest.
Widac potrzebne, tylko ze realizacja rózna w róznych systemach,
to nie wsadzili do jezyka.
>>> Jeśli potraktujesz przerwania jako wątki preemptive, to tak naprawdę
>>> piszesz o zagadnieniu dostępu do zmiennych przez kilka watków. Tego
>>> zagadnienia *NIE* należy rozwiązywać za pomocą volatile, ono nie
>>> powstało do tego i sie do tego NIE nadaje.
>> Wiem. Nic o wątkach nie pisałem.
>
> Mimo to przerwanie jest czymś identycznym z wątkiem preemptive. Ma te
> same konsekwencje i dla dużych procesorów, szczególnie wielordzeniowych,
> niesie z sobą dokładnie te same zagrożenia, co wątki. I nie jest tak, że
> świat kończy się na 8051. Wielordzeniowe procesory embedded to nic
> specjalnie dziwnego.
Wielozadaniowosc tez była różna w wielu systemach.
Stad i "nakładki" na języki.
> Tam, wszyscy programiści od volatile, wybiją sobie zęby o protokoły
> synchronizacji cache, out-of-order execution itd itp.
>
> PS. Zaznaczam, że nic nie pisałeś o AVR w poprzednim poście, wiec w
> ogólnym wypadku, volatile nie może i nie powinno być uzywane w celu
> synchronizacji zmiannych w przerwaniach. W szczególnym, kiedy znasz
> konkretną architekturę, być może.
Przeciez to nie tylko C ma ten problem.
Wiec jesli są rozwiązania dobre, to mozna je w i C zaimplementowac.
Tylko ... schowac pod volatile, czy osobno.
Bo problemow w zaawansowanych systemach istotnie coraz wiecej.
J.
-
35. Data: 2023-02-16 15:23:50
Temat: Re: C++ ośla łączka
Od: "Grzegorz Niemirowski" <g...@g...net>
heby <h...@p...onet.pl> napisał(a):
> Tam, wszyscy programiści od volatile, wybiją sobie zęby o protokoły
> synchronizacji cache, out-of-order execution itd itp.
Ale ja nic nie mówiłem o cache procesora ani kolejności operacji. Chodzi o
problem jaki wprowadza kompilator optymalizując dostęp do zmiennej poprzez
przeniesienie jej z RAM-u do rejestru w jakimś fragmencie kodu. Żadne
bariery na to nie pomogą. Powszechnie problem ten rozwiązuje się stosując
volatile.
> Uwaga o volatile dotyczy *języka* C a nie implementacji tego na AVR.
To nie musi być AVR. Wspomniałem o nim, bo on nawet nie ma operacji do
barier jak np. ARM (DSB, DMB, ISB).
> Sam fakt użycia "przerwania" jest z definicji nieistniejącym bytem w C
Kogo to obchodzi? Jak na złość w prawie każdym procesorze są przerwania.
> PS. Zaznaczam, że nic nie pisałeś o AVR w poprzednim poście, wiec w
> ogólnym wypadku, volatile nie może i nie powinno być uzywane w celu
> synchronizacji zmiannych w przerwaniach. W szczególnym, kiedy znasz
> konkretną architekturę, być może.
A dlaczego nie powinno i co polecasz w zamian? Nie podałeś żadnego argumentu
przeciw volatile. Cały czas chodzi o programy bare metal, bez schedulera.
volatile jest powszechnie stosowanym oraz polecanym rozwiązaniem problemu
optymalizacji na MCU, o którym wspomniałem poprzednio, a doprecyzowałem na
początku tego posta, żeby było jasne o co chodzi. I jakoś w Internecie nie
widzę polemiki z tym polecaniem volatile, z wyjątkiem Twoim postów. Pomijam
oczywiście przypadki używania volatile do innych problemów, do których się
nie nadaje, jak atomowość.
Więc mamy kod:
int z = 0;
int main() {
while(!z);
return 0;
}
isr_handler() {
z = 1;
}
Przy kompilacji z -O0 nie ma problemu, przerwanie przerwie pętlę while. Przy
wyższej optymalizacji pętla może czytać kopię zmiennej i przez to nie
zauważyć jej modyfikacji. volatile łatwo i szybko usuwa ten problem. Mam
nadzieję, że teraz już jest wszystko jasne i w końcu dowiem się jakie
straszne efekty spowoduje tutaj wprowadzenie volatile oraz co jest lepszego.
--
Grzegorz Niemirowski
https://www.grzegorz.net/
-
36. Data: 2023-02-16 15:33:40
Temat: Re: C++ ośla łączka
Od: Piotr Gałka <p...@c...pl>
W dniu 2023-02-16 o 13:54, heby pisze:
>> Już opanował wywoływanie funkcji po jej skopiowaniu do RAMu.
>
> Czytaj wątek z przed paru dni:
>
> "MCU - start programu z RAM"
Przesłałem bratu (on nie czyta Usenetu) wszystkie wiadomości z tamtego
wątku.
W czasie jak pisałem dalszą część tej wiadomości wstępnie powiedział, że
według niego nie ma tam tego co on szuka. Ale rozmawialiśmy tylko
zgrubnie (ja siedzę w swoim pokoju a on piętro niżej). Coś mówił o
sekcjach, ale że to... coś tam (nie dosłyszałem).
Też rzucę okiem, tylko, że tak właściwie nie mam na to czasu.
> Było to omawiane w tym wątku. Ogólnie, jesli ma to związek z
> programowaniem flasha, to boje się zapytać, czy jakoś się zabezpieczacie
> prze utratą zasilania w trakcie.
Chyba powinien się obrazić :)
Napisałeś tak, jakby przeprogramowywanie flasha było jakąś nadzwyczajną
czynnością, a to przecież chyba wszyscy robią.
Są jeszcze jakieś urządzenia bez upgrade?
Do tej pory używaliśmy AtXmega z EEROMem na pokładzie. O ile się
zorientowaliśmy to w ARM (które chyba dużo ludzi używa) EEPROM to jakaś
egzotyka. Stosowana jest emulacja EEPROM we flashu więc wszyscy, którzy
chcą EEPROMu wewnątrz procka muszą programować Flasha.
Od czasu jak tylko przenieśliśmy się z procesorów OTP na flash (jak
pojawiły się pierwsze Atmele) jesteśmy moim zdaniem dobrze zabezpieczeni.
Pierwsza linia obrony:
Nasze urządzenia zasilane są z zasilaczy z podtrzymaniem bateryjnym
(starczającym na kilka godzin). Dopóki nie ma tak długich przerw w
zasilaniu to zanik napięcia zasilania urządzenia praktycznie nie zdarza
się przez lata.
Druga linia obrony:
Jest czujnik napięcia na elektrolicie przed stabilizatorem VCC.
Od przerwania z tego czujnika do choćby drgnięcia w dół napięcia VCC
mija więcej czasu niż flash potrzebuje na dokończenie rozpoczętego
procesu programowania, czy kasowania strony - czyli (pod warunkiem, że
procesor po tym przerwaniu wyłączy wszelkie zbędne obciążenia) każda
rozpoczęta operacja na flashu zostanie dokończona w komfortowych
warunkach. Oczywiście po tym NMI następna operacja nie zostanie rozpoczęta.
To zabezpieczenie występuje tylko w urządzeniach, które przechowują we
flashu jakieś dane. Na przykład nie ma go w czytnikach RFID. Tam
uważamy, że pozostałe zabezpieczenia wystarczą bo tam chodzi tylko o
upgrade, a on się skutecznie broni sam.
Trzecia linia obrony:
Brown-out, który zadziała po tym wszystkim zabezpiecza przed zgłupieniem
procesora, który mógłby wtedy coś nabruździć we flashu.
Różne inne zabezpieczenia, którym trudno nadać kolejne numery:
- ważne informacje we flashu mają sumy kontrolne. Po resecie procesor je
sprawdza. Jak się nie zgadza to przyjmuje bezpieczne wartości default.
- informacja o każdym resecie trafia do rejestracji i serwer może po
resecie skontrolować całą zawartość urządzenia.
- produkujemy urządzenia przez 'upgrade' z programu testowego to
oznacza, że w każdym urządzeniu są praktycznie dwie kopie programu.
- po resecie bootloader sprawdza crc32 programu i jak jest błędne to
sprawdza crc32 upgrade'u i ewentualnie wykonuje upgrade.
- przesyłanie upgrade'u nie niszczy programu (on nadal normalnie działa)
więc przerwanie przesyłania upgrade'u w dowolnym momencie nie jest
problemem,
- dopiero jak przyjdą wszystkie strony upgrade'u jest sprawdzany jego
podpis i upgrade jest wykonywany - zakładamy, że jakby upgrade został
przerwany w tym trakcie to po resecie crc32 to wykryje i upgrade
rozpocznie się od nowa (nie przesyłanie a wykonywanie).
Dotychczas nie zauważyliśmy problemu, którego źródłem byłoby
niedokończenie zapisu flasha.
P.G.
-
37. Data: 2023-02-16 15:37:23
Temat: Re: C++ ośla łączka
Od: "J.F" <j...@p...onet.pl>
On Thu, 16 Feb 2023 13:20:42 +0100, Piotr Gałka wrote:
> A teraz pytanie brata na które nie znamy odpowiedzi.
>
> Ogólnie to jest pierwsze podejście do procesorów ARM (nie wiem z którym
> w tej chwili walczy (Silabs EFM32PG22..., EFM32PG23..., a może EFM32TG11..).
> Zanim użyje procesor po raz pierwszy musi opanować podstawowe działania
> no i jest właśnie na tym etapie.
>
> On by potrzebował sizeof(funkcja).
I to ma zwrocic rozmiar kodu funkcji, czy rozmiar typu zwracanego
przez funkcję?
> Ale jak próbuje to zrobić to dostaje 1.
> Zasugerowałem, że może jak wstawi etykietę (przypomnieliśmy sobie, że
> chyba w C coś takiego jest) na nawiasie zamykającym funkcję to uda się
> policzyć różnicę między jej adresem a adresem początku funkcji.
> Właśnie mi krzyknął (jego pokój jest piętro niżej), że z zewnątrz
> funkcji nie ma dostępu do tej etykiety.
Nie liczylbym na to, ze to zadziała poprawnie.
Ale jak chcecie miec klopoty ... dodajcie do funkcji kolejny argument,
ktory przy wywolaniu zwroci róznice miedzy etykietami.
Albo gdzies zapamieta, bo przeciez typ funkcji moze byc inny.
> Napiszę do czego mu to potrzebne bo czasem może rozwiązanie głównego
> problemu robi się inaczej niż on kombinuje.
>
> Wczoraj wieczorem wspólnie tłumaczyliśmy dwa akapity datasheet, czy
> manuala (nie wiem - on mi po prostu podświetlił akapit na ekranie i
> chodziło o to jak to rozumiemy).
>
> Tam było, że jak się coś robi z programowaniem flasha z wnętrza programu
> to ogólnie nie ma gwarancji, że wszystko się uda. I to zdanie było
> ogólne - czyli nawet jak ruszasz inną stronę niż jesteś to może coś nie
> zadziałać. Nie napisali co dokładnie, ale skoro może coś się nie udać to
> my tego nie chcemy. Napisali, żeby przekopiować odpowiednią funkcję do
> RAMu, wywołać ją i z niej uruchomić proces kasowania, czy programowania
> flasha.
Kopiowanie pod inny adres wymaga relokowalnego kodu - czesto taki
jest, ale warto by sie upewnic.
> Już opanował wywoływanie funkcji po jej skopiowaniu do RAMu.
> Z adresem początku sobie radzi, choć mówi, że wskaźnik na funkcję jest
> zawsze większy o 1 od prawdziwego adresu i ustalając fragment do
> kopiowania on musi tę jedynkę odejmować.
Ciekawe, bardzo ciekawe.
A niech wywola gdzies funkcje ze wskaznika, i zobaczy jak to sie
skompiluje - tez bedzie cofnięcie o bajt?
Chyba, ze przed punktem startowym funkcji jest cos waznego zapisane.
> Wszystko już działa, tylko, że na razie rozmiar funkcji bierze z sufitu
> na zapas.
> No i jedyne co brakuje do odhaczenia kolejnej funkcjonalności to
> ustalenie w jednej funkcji jaki jest sizeof drugiej funkcji.
To chyba nie ma.
Napisalbym to w assemblerze, zeby wiadomo bylo, ze nic sie nie sp*,
lub postaral sie skorzystac z jakiejs dynamicznie ladowanej biblioteki
lub pozostal przy zapasie :-)
> Może wiesz (lub ktoś inny) jak to się robi.
https://developer.arm.com/documentation/ka003803/lat
est
cos takiego?
:-(
J.
-
38. Data: 2023-02-16 16:05:00
Temat: Re: C++ ośla łączka
Od: Piotr Gałka <p...@c...pl>
W dniu 2023-02-16 o 15:37, J.F pisze:
>> On by potrzebował sizeof(funkcja).
>
> I to ma zwrocic rozmiar kodu funkcji, czy rozmiar typu zwracanego
> przez funkcję?
Wiedziałem, że w tym miejscu jest niejasne i ze zaraz dalej się wyjaśni.
>> Już opanował wywoływanie funkcji po jej skopiowaniu do RAMu.
>> Z adresem początku sobie radzi, choć mówi, że wskaźnik na funkcję jest
>> zawsze większy o 1 od prawdziwego adresu i ustalając fragment do
>> kopiowania on musi tę jedynkę odejmować.
>
> Ciekawe, bardzo ciekawe.
On dokładnie wie o co chodzi i próbował mi wyjaśnić ale nie do końca
ogarnąłem. To nie jest kwestia błędu kompilatora tylko hardware'u i tak
ma być. Na tyle na ile zrozumiałem to przy operacji wywołania funkcji
(nie na poziomie C tylko na poziomie assemblera) wymagane jest
ustawienie najmłodszego bitu adresu na 1. A że wszystkie funkcje
umieszczane są pod adresami modulo (nie wiem, coś więcej niż 1) to
ustawienie tego bitu na 1 daje adres o 1 większy.
>> Może wiesz (lub ktoś inny) jak to się robi.
>
> https://developer.arm.com/documentation/ka003803/lat
est
>
Dzięki.
Wygląda na dokładnie jego pytanie.
Na razie nie próbowałem zrozumieć odpowiedzi.
Przesłałem mu. Zobaczymy. Na razie chwilowo go nie ma (chyba poszedł na
obiad, co i ja zaraz zrobię).
P.G.
-
39. Data: 2023-02-16 17:56:15
Temat: Re: C++ ośla łączka
Od: heby <h...@p...onet.pl>
On 16/02/2023 15:23, Grzegorz Niemirowski wrote:
> Ale ja nic nie mówiłem o cache procesora ani kolejności operacji. Chodzi
> o problem jaki wprowadza kompilator optymalizując dostęp do zmiennej
> poprzez przeniesienie jej z RAM-u do rejestru w jakimś fragmencie kodu.
> Żadne bariery na to nie pomogą.
Istnieje wiele metod, które pozwalają dostać co chcesz bez udziału volatile.
Mutexy, external function, sekcje krytyczne, atomiki, interlocked itd itp.
> Powszechnie problem ten rozwiązuje się
> stosując volatile.
Nie. Powszechnie rozwiązuje się ten problem używając poprawnych wzorców
projektowych dostępnych w języku i czasami na danej platformie
kompilatora bądź hardware.
Używanie volatile w tym celu pochodzi z czasów, kiedy nie było innych metod.
Volatile jest np. bezsensowne, bo uniemożliwia optymalizacje w
miejscach, gdzie jej nie chcesz i niestety również tam, gdzie chcesz.
Albo wszystko albo nic.
Na chwile obecną volatile uzyteczne jest tylko przy komunikacji z
hardware *oraz* na wyjątkowo zapuszczonych architekturach, gdzie
dokłądnie wiesz, co się stanie po jego użyciu.
Przykładowo, na 8051 przy jednoczesnym dostępie do RAMu bajtowo i
bitowo, biedy kompilator może źle wyoptymalizować kawałek kodu. Ale to
akuratnie taka popieprzona architektura, do której C pasuje w sposób
wymagający wbijania go młotkiem, trudo się więc dziwić, że wymaga
również przedziwacznych konstrukcji prostujących ten C do czegoś
użytecznego na guano 8051.
>> Uwaga o volatile dotyczy *języka* C a nie implementacji tego na AVR.
> To nie musi być AVR. Wspomniałem o nim, bo on nawet nie ma operacji do
> barier jak np. ARM (DSB, DMB, ISB).
Więc wyraźnie wyjaśniam, że jeśli chodzi o ogólne uzycie volatile, to
jest ono bezsensowne do rzeczy innych niż pamięć rejetrowa urządzeń. Ale
w szczególności, w programach do migania diodą na AVR, może być w jakimś
stopniu emulacją brakującej funkcjonalności i tam stosując je rozważnie
da się dostać namiastkę poprawnej synchronizacji.
>> Sam fakt użycia "przerwania" jest z definicji nieistniejącym bytem w C
> Kogo to obchodzi? Jak na złość w prawie każdym procesorze są przerwania.
Które obsługiwane są przez skrajnie specyficzny kod, zazwyczaj niezgodny
z ABI kompilatora, wymagajacy workaroudów typu pre/post i naked. To, że
procedure przerwania można napisać w C nie oznacza, że to "normalne" C.
To wyjątkowo wyjątkowe kodowanie, zazwyczaj na poziomie OSa, którego
zwykłego kodera C nie dotyczy.
User na górze, nawet jeśli wołany jest z wnętrza przerwania, nie widzi
róznicy między nim a wątkiem. Katastrofy z volatile i weak memory
ordering sa jak najbardziej możliwe, im wyżej w komplikacji procesora
wylądujesz ze swoim kodem.
>> PS. Zaznaczam, że nic nie pisałeś o AVR w poprzednim poście, wiec w
>> ogólnym wypadku, volatile nie może i nie powinno być uzywane w celu
>> synchronizacji zmiannych w przerwaniach. W szczególnym, kiedy znasz
>> konkretną architekturę, być może.
> A dlaczego nie powinno i co polecasz w zamian?
Atomik? Mutex? Sekcja krytyczna? IPC?
> Nie podałeś żadnego
> argumentu przeciw volatile.
Przecież zlinkowałem arykuł, w którym masz jasno wypisane powody i
ostrzeżenie.
Volatile działa inaczej, niż mysli 95% programistów C. I o ile w małych
systemach z AVRkiem to akurat nie problem, co najwyżej przyczyna
marudzenia "panie, jakie te kompialtory złe robio, nawet zopymalizować
nie potrafio", to w dużych systemach prowadzi prosto do wybicia sobie
zębów. A te "duże systemy" to obecnie coś, co dobija się z hukiem do
drzwi embedowców. Czasy 8051, po raz kolejny, jak co roku od 40 lat,
minęły. Za chwile powszechne będą RISC-V z kilkoma rdzeniami, w
zależnosci od wymogów mocowych, ze złożonymi superskalarnymi potokami i
pokręconym cache. Dalej będziesz w nich stosował volatile?
> Cały czas chodzi o programy bare metal, bez
> schedulera.
Przerwania to multitasking, taki sam jak w schedulerze preemptive.
> volatile jest powszechnie stosowanym oraz polecanym
> rozwiązaniem problemu optymalizacji na MCU
W pierdołowatych małych cpu zapewne tak. W dużych absolutnie nie. Pisząc
relatywnie duże programy, o dużej złożoności, z masą wątków i wymianą
danych między nimi, nie miałem okazji użyć volatile ani razu. Z
ciekawostek: w poważnych firmach słowo volatile jest wyłapywane przez
linter kodu i wymaga zgody komisji za zielonym suknem.
> I jakoś w Internecie nie widzę polemiki z tym polecaniem
> volatile
Bo jej nie szukasz. Google aż krzyczy "nie uzywaj volatile, to nie
działa jak myślisz".
Choćby wiki:
https://en.wikipedia.org/wiki/Volatile_(computer_pro
gramming)
[...]Furthermore, in C and C++ it does not work in most threading
scenarios, and that use is discouraged.[...]"
"[...]Operations on volatile variables are not atomic, nor do they
establish a proper happens-before relationship for threading. This is
specified in the relevant standards (C, C++, POSIX, WIN32),[1] and
volatile variables are not threadsafe in the vast majority of current
implementations. Thus, the usage of volatile keyword as a portable
synchronization mechanism is discouraged by many C/C++ groups[...]".
Niezliczona ilość postów/stron wyjasnia, dlaczego volatile nie jest tym,
o czym myślisz, że do czego jest.
Serio, nie zauważyłes?
> Więc mamy kod:
> int z = 0;
> int main() {
> while(!z);
> return 0;
> }
> isr_handler() {
> z = 1;
> }
> Przy kompilacji z -O0 nie ma problemu, przerwanie przerwie pętlę while.
> Przy wyższej optymalizacji pętla może czytać kopię zmiennej i przez to
> nie zauważyć jej modyfikacji. volatile łatwo i szybko usuwa ten problem.
W małym procesorze tak.
Teraz weź duży procesor. Być może Ci zaskoczy, że jeśli to przerwanie to
inny wątek na innym rdzeniu, to mimo, że rdzeń zapisze z = 1, to pętla
nigdy się nie zakończy. Bo możesz mieć system ze słabą koherencją cache
i bez bariery/fence informacja nigdy nie zostanie zsynchronizowana z
lokalnymi cache obu rdzeni. Albo ciekawoski z przestawianiem zapisów,
kiedy jeden rdzeń widzi zapis w innej kolejnosci niż wykonany w
sąsiednim rdzeniu.
Swoją drogą ten problem jest trudny do zauważenia przez przeciętnego
wciskacza klawiszy, bo x86 jest wyjątkowo tolerancyjny dla dziadowskiego
kodu. Tam to działa przypadkiem i wiele osób ma podejrzenie, że nie bez
powodu takie decyzje projektowe podjęto: łatwiej było zaprojektować
tolerancyjny procesor niż liczyć na poprawianie miliardów lini kodu po
kiepskich programistach.
> Mam nadzieję, że teraz już jest wszystko jasne i w końcu dowiem się
> jakie straszne efekty spowoduje tutaj wprowadzenie volatile oraz co jest
> lepszego.
Powoduje: zablokowanie optymalizacji *całej* zmiennej, wszędzie oraz nie
usuwa innych problemów z wątkowością, takich jak weak memory ordering
czy synchronizacja cache.
Ogólnie działa tylko na małych systemach, gdzie nie ma tego typu
zagrożeń, co powoduje że volatile jest narzędziem workaroudującym
prawidłowe metody, a nie metodą samą w sobie.
Na większych sens jest zerowy, poza dostępem do rejestrów.
Jak już musisz mieć niskopoziomowo to wyjasnione, to może zerknij tutaj:
https://www.kernel.org/doc/html/latest/process/volat
ile-considered-harmful.html
-
40. Data: 2023-02-16 18:01:23
Temat: Re: C++ ośla łączka
Od: heby <h...@p...onet.pl>
On 16/02/2023 15:33, Piotr Gałka wrote:
> Napisałeś tak, jakby przeprogramowywanie flasha było jakąś nadzwyczajną
> czynnością, a to przecież chyba wszyscy robią.
Niezliczona ilośc błędów popełnianych przez programistów w takim kodzie
każe mi dmuchać na zimne. Taki kod powinien podlegać weryfikacji
formalnej a z drugiej strony "zbrickowanie" urządzeń to rzecz tak
powszechna, że zastanawiam się kto w ogóle pisze te bootloadery,
flashery itd itp. bo wyglądają jak prace zaliczeniowe kiepskich studentów.
> Dotychczas nie zauważyliśmy problemu, którego źródłem byłoby
> niedokończenie zapisu flasha.
Zastanawia mnie wobec tego ta kombinacja z flashowaniem z RAM.
Musicie skasować cały flash (wątpię)? Ma byćszybciej? Coś innego nie działa?