-
71. Data: 2019-02-14 23:02:16
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: Janusz <j...@o...pl>
W dniu 2019-02-14 o 13:59, Queequeg pisze:
> J.F. <j...@p...onet.pl> wrote:
>
>>> Ale co kompilator może zrobić, jak sam procesor nie obsługuje
>>> atomicznego dostępu do tej zmiennej (bo np. jest 8-bitowy, a zmienna
>>> 16-bitowa)?
>>
>> To samo, co programista ma zrobic :-)
>
> Programista ma kontekst, którego nie ma kompilator. Programista wie, kiedy
> chce mieć sekcję krytyczną (która nie musi obejmować wyłącznie atomicznego
> dostępu do zmiennej szerszej niż magistrala adresowa).
>
>>> Zmienna może się zmienić między każdą z tych instrukcji.
>>
>> Cos w tym jest.
>
> Jest jest... po to są sekcje krytyczne.
>
>>> Czemu? Co ma do tego ARM? Chodzi o szerokość magistrali danych? To
>>> rozwiązuje tylko jeden problem,
>>
>> Tak, problemu z int nie bedzie :-)
>
> Z odczytem int nie, ale np. z read-modify-write już tak.
>
>>> ale inne (chociażby ten pierwszy przykład wyżej) pozostają.
>>
>> Ciezkie jest zycie programisty.
>
> A to swoją drogą... ale raczej przez ludzi a nie przez komputery :)
>
> Trzeba po prostu pamiętać, że (przynajmniej w przypadku C i C++)
> kompilator nie tłumaczy kodu na język maszynowy jeden do jednego. Kod to
> tylko pewien abstrakcyjny opis, który kompilator może traktować z dosyć
> dużą dowolnością. Dochodzą do tego chociażby zagadnienia związane z
> reorderingiem.
>
> Przykładowo:
>
> https://www.nongnu.org/avr-libc/user-manual/optimiza
tion.html
>
> 1. Dzielimy (powolna operacja)
> 2. Wyłączamy przerwania cli
> 3. Zapisujemy wynik dzielenia do zmiennej (szybka operacja)
> 4. Włączamy przerwania
>
> A optymalizator twierdzi, że wyłączy sobie przerwania przed dzieleniem, bo
> tak mu mnieszy kod wychodzi :)
Faktycznie tak robi, na całe dzielenie wył przerwania ale można ten
problem obejść :)
void test2( unsigned int val )
{div_t wynik;
wynik=div(65535U,val);
e10: bc 01 movw r22, r24
e12: 8f ef ldi r24, 0xFF ; 255
e14: 9f ef ldi r25, 0xFF ; 255
e16: 0e 94 f7 08 call 0x11ee ; 0x11ee <__divmodhi4>
return 1;
}
static __inline__ uint8_t __iCliRetVal(void)
{
cli();
e1a: f8 94 cli
//val = / val;
ATOMIC_BLOCK(ATOMIC_FORCEON) {
ivar = wynik.quot;
e1c: 70 93 14 02 sts 0x0214, r23 ; 0x800214 <ivar+0x1>
e20: 60 93 13 02 sts 0x0213, r22 ; 0x800213 <ivar>
return 1;
}
static __inline__ void __iSeiParam(const uint8_t *__s)
{
sei();
e24: 78 94 sei
Da się? da sie :) ale prawda jest taka że trzeba mu cały czas patrzyć na
ręce
czy nam czegoś nadmiernie nie zoptymalizował.
--
Pozdr
Janusz
-
72. Data: 2019-02-14 23:03:48
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: "Grzegorz Niemirowski" <g...@p...onet.pl>
Irek.N. <t...@j...taki.jest.pl> napisał(a):
> Dlaczego miał by tak zrobić? Ponieważ volatile (w moim przekonaniu) mówi
> kompilatorowi, że może się spodziewać problemów z tą zmienną i nie może
> zakładać, że uda się ją odczytać etapowo (tak samo jak np. nie ma sensu ją
> buforować, tylko za każdym razem trzeba czytać).
Na szczęście co mówi volatile to jest zdefiniowane w standardzie a nie w
czyichś przekonaniach :)
volatile dotyczy wyłącznie optymalizacji. "Problemy" ze zmienną mogą brać
się z wielu różnych przyczyn, nie tylko z przerwań. Jest też np. DMA. Nie ma
sensu rozważać volatile w kontekstach, do których nie zostało stworzone lub
też oczekiwać, że kompilator przejmie rolę menedżera pamięci lub inną,
należącą do systemu operacyjnego lub programisty.
--
Grzegorz Niemirowski
https://www.grzegorz.net/
-
73. Data: 2019-02-15 08:57:26
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: Mateusz Viste <m...@n...pamietam>
On Thu, 14 Feb 2019 22:46:09 +0100, Irek.N. wrote:
> Zastanawiam się, czy gdyby kompilator zrobił odczyt wielokrotny, czy
> było by to "moralnie" poprawne, czy nadal miało by znamiona łaty?
Ale co miałoby to rozwiązać? Wartość może zmieniać się za każdym
odczytem, i co wtedy? Ma się zapętlać ad vitam aeternam?
> Dlaczego miał by tak zrobić? Ponieważ volatile (w moim przekonaniu) mówi
> kompilatorowi, że może się spodziewać problemów z tą zmienną i nie może
> zakładać, że uda się ją odczytać etapowo (tak samo jak np. nie ma sensu
> ją buforować, tylko za każdym razem trzeba czytać).
Ty natomiast zakładasz z góry, że wartość tej zmiennej zmienia się
wolniej niż pętla jest w stanie ją sprawdzić. Nadgorliwość gorsza od... :)
Mateusz
-
74. Data: 2019-02-15 11:07:11
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: "J.F." <j...@p...onet.pl>
Użytkownik "Queequeg" napisał w wiadomości grup
dyskusyjnych:67cc78db-da90-4e43-be55-e269940aa85e@tr
ust.no1...
Janusz <j...@o...pl> wrote:
>>> AVR ma to rozwiązane w ten sposób:
>>> https://www.nongnu.org/avr-libc/user-manual/group__u
til__atomic.html
>> Mylisz pojęcia, atomic blok i voltaile to są zupełnie dwie różne
>> sprawy.
>Nie mylę, może nieprecyzyjnie się wyraziłem. AVR ma wspomniane
>mechanizmy,
>których programista może użyć, jeśli interesuje go atomiczny dostęp
>lub
>tak naprawdę jakakolwiek inna sekcja krytyczna.
Taka typowa sekcja krytyczna to jeszcze wymaga systemu operacyjnego, a
przynajmniej czegos na ksztalt, z przelaczaniem procesow ..
Ha, moze i faktycznie C++ trzeba uzyc nawet na 8051 - dostep do
zmiennych obiektu da sie przez wydzielone funkcje, ktore zadbaja o
potrzebne rzeczy :-)
J.
-
75. Data: 2019-02-15 20:57:41
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: "Irek.N." <t...@j...taki.jest.pl>
> Ale co miałoby to rozwiązać? Wartość może zmieniać się za każdym
> odczytem, i co wtedy? Ma się zapętlać ad vitam aeternam?
>
> Ty natomiast zakładasz z góry, że wartość tej zmiennej zmienia się
> wolniej niż pętla jest w stanie ją sprawdzić. Nadgorliwość gorsza od... :)
Wiem że masz rację, wiesz, myślenie życzeniowe :)
Miłego.
Irek.N.
-
76. Data: 2019-02-15 20:59:49
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: "Irek.N." <t...@j...taki.jest.pl>
> Na szczęście co mówi volatile to jest zdefiniowane w standardzie a nie w
> czyichś przekonaniach :)
I całe szczęście Panie, i całe szczęście.
Czy w C ktoś pisze sterowanie do silników samolotów? ;)
Miłego.
Irek.N.
-
77. Data: 2019-02-16 22:53:59
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: q...@t...no1 (Queequeg)
Irek.N. <t...@j...taki.jest.pl> wrote:
>> Na szczęście co mówi volatile to jest zdefiniowane w standardzie a nie w
>> czyichś przekonaniach :)
>
> I całe szczęście Panie, i całe szczęście.
> Czy w C ktoś pisze sterowanie do silników samolotów? ;)
Pisze :)
https://pl.wikipedia.org/wiki/MISRA_C
https://www.aerodefensetech.com/component/content/ar
ticle/adt/features/articles/17022
--
Eksperymentalnie: http://facebook.com/groups/pl.misc.elektronika
-
78. Data: 2019-02-16 23:03:44
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: q...@t...no1 (Queequeg)
Irek.N. <t...@j...taki.jest.pl> wrote:
>> Skąd wiesz?
>
> Chociaż by z powodu występowania możliwości błędnego odczytu wartości 0
> dla tej zmiennej gdy jest czytana połówkami. Mój przypadek.
No tak, ale volatile przed tym nie chroni.
> Dlaczego miał by tak zrobić? Ponieważ volatile (w moim przekonaniu) mówi
> kompilatorowi, że może się spodziewać problemów z tą zmienną i nie może
> zakładać, że uda się ją odczytać etapowo (tak samo jak np. nie ma sensu
> ją buforować, tylko za każdym razem trzeba czytać).
To przekonanie to to, co podpowiadałaby intuicja, ale z punktu widzenia
standardu jest błędne.
Zobacz chociażby tutaj:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n112
4.pdf
Strona 25, punkty 2 i 3, później też strona 121, punkt 6.
Tu nie ma mowy o atomicznym odczycie zmiennej tylko o nieoptymalizowaniu
dostępu do tej zmiennej.
Oczywiście na logikę chcielibyśmy, żeby zmienna nie zmieniła wartości w
trakcie jej odczytu, ale do tego po prostu służą inne mechanizmy niż
modyfikator volatile.
--
Eksperymentalnie: http://facebook.com/groups/pl.misc.elektronika
-
79. Data: 2019-02-16 23:11:47
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: q...@t...no1 (Queequeg)
J.F. <j...@p...onet.pl> wrote:
> Taka typowa sekcja krytyczna to jeszcze wymaga systemu operacyjnego, a
> przynajmniej czegos na ksztalt, z przelaczaniem procesow ..
Czemu? Na 8-bitowcach zwykle nie mamy OS ani wielu procesów, mamy jedynie
przerwania, więc w sekcji krytycznej chcemy po prostu, żeby funkcje
obsługi przerwań poczekały na koniec sekcji krytycznej. Czyli:
1. Wyłączamy przerwania
2. Odczytujemy jedną połówkę zmiennej
3. Timer zgłasza przerwanie (ustawia flagę)
4. Odczytujemy drugą połówkę zmiennej
5. Włączamy (przywracamy) przerwania
6. Przerwanie zgłoszone przez timer jest obsługiwane
> Ha, moze i faktycznie C++ trzeba uzyc nawet na 8051 - dostep do
> zmiennych obiektu da sie przez wydzielone funkcje, ktore zadbaja o
> potrzebne rzeczy :-)
To, czy programujemy obiektowo, czy nie, to zupełnie inny poziom
abstrakcji niż to, o czym tutaj mówimy :)
--
Eksperymentalnie: http://facebook.com/groups/pl.misc.elektronika
-
80. Data: 2019-02-16 23:26:28
Temat: Re: Zagwozdka w C Keil - wyjaśnienie.
Od: q...@t...no1 (Queequeg)
J.F. <j...@p...onet.pl> wrote:
> W sumie poprawnie - jeszcze nie wie ktore funkcje beda uzyte, to musi
> skompilowac poprawnie.
> Ale trzeba bylo sprawdzic ze static.
Sprawdziłem, nie ma różnicy w wygenerowanym kodzie.
Diff:
#v+
--- test-no-static.s 2019-02-16 23:19:27.993290080 +0100
+++ test-static.s 2019-02-16 23:19:20.653290321 +0100
@@ -29,7 +29,7 @@
.L6:
.align 2
.L5:
- .word i
+ .word .LANCHOR0
.size fn1, .-fn1
.align 2
.global fn2
@@ -45,8 +45,14 @@
.L9:
.align 2
.L8:
- .word i
+ .word .LANCHOR0
.size fn2, .-fn2
- .comm i,4,4
+ .bss
+ .align 2
+.LANCHOR0 = . + 0
+ .type i, %object
+ .size i, 4
+i:
+ .space 4
.ident "GCC: (Raspbian 4.9.2-10) 4.9.2"
.section .note.GNU-stack,"",%progbits
#v-
> A potem ...
>
> static void fn2(void) { i = 40; }
>
> i jej nie wywolywac.
Tak, to zmienia postać rzeczy.
Z samym `int i;` fn1 wygląda wtedy:
#v+
ldr r3, .L5
ldr r3, [r3]
.L2:
cmp r3, #42
bne .L2
#v-
A ze statycznym:
#v+
.L2:
b .L2
#v-
> static void fn2(void) { i = 40; }
>
> main()
> {
> fn() ;
> fn2();
> }
Tak... to zrobił ciekawie.
Jeśli main jest niestatyczne, to wygenerował ciało fn1() a jeśli jest
statyczne, to zamienił na nieskończoną pętlę.
> No i ciekawe, na ile dobrze zoptymalizuje :-)
Nie wiem czemu to:
#v+
static int i;
void fn1(void) { while (i != 42) ; }
static void fn2(void) { i = 40; }
void fn3(void) { fn1(); fn2(); }
#v-
spowodowało wygenerowanie ciała fn1:
#v+
ldr r3, .L5
ldr r3, [r3]
.L2:
cmp r3, #42
bne .L2
#v-
--
Eksperymentalnie: http://facebook.com/groups/pl.misc.elektronika