Po patrząc na kiść z innymi pytaniami i ich odpowiedzi , mam wrażenie, że nie ma powszechnej zgody na to, co „lotny” słowo kluczowe w C oznacza dokładnie.
Nawet sam standard nie wydaje się wystarczająco jasny, aby wszyscy mogli się zgodzić co to znaczy .
Wśród innych problemów:
- Wydaje się, że zapewnia różne gwarancje w zależności od sprzętu i kompilatora.
- Wpływa to na optymalizacje kompilatora, ale nie na optymalizacje sprzętowe, więc na zaawansowanym procesorze, który wykonuje własne optymalizacje w czasie wykonywania, nie jest nawet jasne, czy kompilator może zapobiec jakiejkolwiek optymalizacji, której chcesz zapobiec. (Niektóre kompilatory generują instrukcje, aby zapobiec niektórym optymalizacjom sprzętowym w niektórych systemach, ale nie wydaje się to być w żaden sposób ustandaryzowane).
Podsumowując problem, wydaje się (po przeczytaniu dużo), że „niestabilność” gwarantuje coś w rodzaju: Wartość zostanie odczytana / zapisana nie tylko z / do rejestru, ale przynajmniej do pamięci podręcznej L1 rdzenia, w tej samej kolejności, w jakiej odczyty / zapisy pojawiają się w kodzie. Ale wydaje się to bezużyteczne, ponieważ odczyt / zapis z / do rejestru jest już wystarczający w tym samym wątku, podczas gdy koordynacja z pamięcią podręczną L1 nie gwarantuje nic więcej odnośnie koordynacji z innymi wątkami. Nie mogę sobie wyobrazić, kiedy synchronizacja może być ważna tylko z pamięcią podręczną L1.
WYKORZYSTANIE 1
Jedynym powszechnie uzgodnionym zastosowaniem lotnych wydaje się być w przypadku starych lub wbudowanych systemów, w których niektóre lokalizacje pamięci są mapowane sprzętowo na funkcje we / wy, np. W pamięci, która kontroluje (bezpośrednio, w sprzęcie) światło lub trochę pamięci, która informuje, czy klawisz klawiatury jest wciśnięty, czy nie (ponieważ jest podłączony bezpośrednio przez sprzęt do klawisza).
Wydaje się, że „use 1” nie występuje w przenośnym kodzie, którego celem są systemy wielordzeniowe.
USE 2
Nie różni się zbytnio od „use 1” to pamięć, która może być w dowolnym momencie odczytana lub zapisana przez program obsługi przerwań (który może kontrolować światło lub przechowywać informacje z klucza). Ale już w tym przypadku mamy problem polegający na tym, że w zależności od systemu moduł obsługi przerwań może działać na innym rdzeniu z własną pamięcią podręczną pamięci , a „niestabilność” nie gwarantuje spójności pamięci podręcznej we wszystkich systemach.
Więc „Zastosowanie 2” wydaje się być poza to, co „lotny” może dostarczyć.
WYKORZYSTANIE 3
Jedynym innym niekwestionowanym zastosowaniem, jakie widzę, jest zapobieganie błędnej optymalizacji dostępu poprzez różne zmienne wskazujące na tę samą pamięć, której kompilator nie zdaje sobie sprawy z tej samej pamięci. Ale jest to prawdopodobnie tylko niekwestionowane, ponieważ ludzie o tym nie mówią - widziałem tylko jedną wzmiankę o tym. Pomyślałem, że standard C już rozpoznał, że „różne” wskaźniki (jak różne argumenty funkcji) mogą wskazywać na ten sam element lub elementy w pobliżu, i już określiłem, że kompilator musi wygenerować kod, który działa nawet w takich przypadkach. Nie mogłem jednak szybko znaleźć tego tematu w najnowszym standardzie (500 stron!).
Więc „użyj 3” może w ogóle nie istnieje ?
Stąd moje pytanie:
Czy „niestabilność” w ogóle gwarantuje cokolwiek w przenośnym kodzie C dla systemów wielordzeniowych?
EDYCJA - aktualizacja
Po przejrzeniu najnowszego standardu wygląda na to, że odpowiedź jest co najmniej bardzo ograniczona tak:
1. Norma wielokrotnie określa specjalne traktowanie dla określonego typu „volatile sig_atomic_t”. Jednak standard mówi również, że użycie funkcji sygnału w programie wielowątkowym powoduje niezdefiniowane zachowanie. Zatem ten przypadek użycia wydaje się ograniczony do komunikacji między programem jednowątkowym i jego obsługą sygnału.
2. Norma określa również jasne znaczenie słowa „niestabilny” w stosunku do setjmp / longjmp. (Przykładowy kod, który ma znaczenie, podany jest w innych pytaniach i odpowiedziach ).
Tak więc bardziej precyzyjne pytanie brzmi:
czy „ulotność” w ogóle gwarantuje cokolwiek w przenośnym kodzie C dla systemów wielordzeniowych, oprócz (1) zezwalającego jednemu wątkowi programu na otrzymywanie informacji z jego procedury obsługi sygnału lub (2) zezwalającego na setjmp kod, aby zobaczyć zmienne zmienione między setjmp i longjmp?
To wciąż pytanie tak / nie.
Jeśli „tak”, byłoby świetnie, gdybyś mógł pokazać przykład bezbłędnego przenośnego kodu, który staje się błędny, jeśli pominięto „niestabilność”. Jeśli „nie”, to przypuszczam, że kompilator może zignorować „niestabilność” poza tymi dwoma bardzo szczególnymi przypadkami, dla celów wielordzeniowych.
volatile
konkretnie, które moim zdaniem jest konieczne.
volatile
informować program, że może on zmieniać się asynchronicznie.