2013-03-19 10 views
17

Rozumiem, że DSB, DMB i ISB są barierami uniemożliwiającymi ponowne zamawianie instrukcji. Mogę również znaleźć wiele bardzo dobrych wyjaśnień dla każdego z nich, ale trudno jest sobie wyobrazić przypadek, że muszę z nich korzystać.Rzeczywiste przypadki użycia barier (DSB, DMB, ISB) w ARM

Również z kodów open source widzę te bariery od czasu do czasu, ale dość trudno jest zrozumieć, dlaczego są one używane. Wystarczy na przykład w funkcji jądra Linux 3.7 tcp_rcv_synsent_state_process, istnieje linia następująco:

if (unlikely(po->origdev)) 
      sll->sll_ifindex = orig_dev->ifindex; 
    else 
      sll->sll_ifindex = dev->ifindex; 

    smp_mb(); 

    if (po->tp_version <= TPACKET_V2) 
      __packet_set_status(po, h.raw, status); 

gdzie smp_mb() jest w zasadzie DMB. Czy możesz podać mi kilka przykładów z życia? Pomoże to lepiej zrozumieć bariery.

+0

To pytanie było ostatnim przykładem: http://stackoverflow.com/q/15003405/1163019 – auselen

+0

Przewodnik programisty Cortex zawiera także sekcję dla barier (11.2). http://infocenter.arm.com/help/topic/com.arm.doc.den0013c/index.html – auselen

+1

Nadal głosuję, aby zamknąć, ponieważ jest to bardzo szerokie pytanie. – auselen

Odpowiedz

26

Przykro mi, nie zamierzam dawać ci prostego przykładu, o który pytasz, ponieważ ponieważ przeglądasz już kod źródłowy Linuksa, masz mnóstwo osób, które mogą się obejść i nie wydają się Wsparcie. Nie ma w tym wstydu - każdy rozsądny człowiek jest początkowo zdezorientowany przez problemy z zamawianiem dostępu do pamięci :)

Jeśli jesteś głównie programistą aplikacji, to jest szansa, że ​​nie będziesz się musiał o to martwić - cokolwiek używane struktury współbieżności rozwiążą to za Ciebie.

Jeśli jesteś głównie programistą sterowników urządzeń, to przykłady są dość proste do znalezienia - zawsze, gdy istnieje zależność w twoim kodzie od wcześniejszego dostępu, który wywarł jakiś skutek (usunął źródło przerwania, napisał deskryptor DMA) zanim wykonywany jest inny dostęp (ponowne włączanie przerwań, inicjowanie transakcji DMA).

Jeśli jesteś w trakcie tworzenia struktury współbieżności (lub debugowania jednej), prawdopodobnie będziesz musiał przeczytać nieco więcej na ten temat - ale twoje pytanie sugeruje powierzchowną ciekawość, a nie natychmiastową potrzebę? Jeśli opracowuje się własną metodę przekazywania danych między wątkami, a nie w oparciu o prymitywy udostępniane przez strukturę współbieżności, to dla wszystkich celów i celów istnieje platforma współbieżności.

Paul McKenney napisał doskonały papier na potrzeby bariera pamięci i jakie efekty rzeczywiście mają w procesorze: Memory Barriers: a Hardware View for Software Hackers

Jeśli to nieco zbyt hardcore, napisałem 3-częściowy blogu serię, która jest nieco bardziej lekki i kończy się widokiem specyficznym dla ARM. Pierwsza część to Memory access ordering - an introduction.

Ale jeśli jest to konkretna lista przykładów, których szukasz, szczególnie w architekturze ARM, możesz zrobić znacznie gorzej niż Barrier Litmus Tests and Cookbook.

Wyjątkowo lekki dodatkowy widok programisty i nie do końca poprawny architektonicznie wersja:

  • DMB - ilekroć wymaga zamawiania dostępu do pamięci w odniesieniu do innego dostępu do pamięci.
  • DSB - zawsze, gdy dostęp do pamięci musi zostać zakończony przed rozpoczęciem wykonywania programu.
  • ISB - za każdym razem, gdy pobranie instrukcji musi nastąpić bezpośrednio po określonym punkcie programu, na przykład po aktualizacji map pamięci lub po zapisaniu kodu do wykonania. (W praktyce oznacza to "wyrzucenie wszelkich wcześniej przygotowanych instrukcji w tym miejscu".)
4

Zwykle należy stosować barierę pamięci w przypadkach, gdy konieczne jest upewnienie się, że dostęp do pamięci następuje w określonej kolejności. Może to być wymagane z wielu powodów, zwykle jest to wymagane, gdy dwa lub więcej procesów/wątków lub element sprzętowy uzyskuje dostęp do tej samej struktury pamięci, która musi być spójna.

Jest używany bardzo często w transferach DMA. A proste konstrukcje sterujące DMA może wyglądać następująco:

struct dma_control { 
    u32 owner; 
    void * data; 
    u32 len; 
}; 

Właściciel zazwyczaj są ustawione na coś podobnego OWNER_CPU lub OWNER_HARDWARE, aby wskazać, który z dwóch uczestników może pracować ze strukturą.

kod, który zmienia to zazwyczaj podoba się ten

dma->data = data; 
dma->len = length; 
smp_mb(); 
dma->owner = OWNER_HARDWARE; 

So dane len są zawsze ustawione przed własności zostaje przeniesione do sprzętu DMA. W przeciwnym razie silnik może uzyskać nieaktualne dane, takie jak wskaźnik lub długość, która nie została zaktualizowana, ponieważ procesor zmienił kolejność dostępu do pamięci.

To samo dotyczy procesów lub wątków działających na różnych rdzeniach. Mogą komunikować się w podobny sposób.

2

Jednym prostym przykładem wymogu dotyczącego barier jest spinlock. Jeśli zaimplementujesz blokadę spinów przy użyciu porównania-i-zamiany (lub LDREX/STREX na ARM) i bez bariery, procesor może spekulatywnie ładować wartości z pamięci i leniwie przechowywać obliczone wartości do pamięci, a żadne z nich nie jest wymagane w kolejności obciążeń/zapisów w strumieniu instrukcji.

Usługa DMB w szczególności zapobiega porządkowaniu dostępu do pamięci wokół DMB. Bez DMB, procesor może zmienić kolejność pamięci w pamięci chronionej przez spinlock po zwolnieniu spinlock. Albo procesor może odczytać pamięć chronioną przez spinlock przed zablokowaniem spinlock lub gdy został zablokowany przez inny kontekst.

Unixsmurf już to wskazał, ale wskażę też w kierunku Barrier Litmus Tests and Cookbook. Ma całkiem niezłe przykłady tego, gdzie i dlaczego należy stosować bariery.

Powiązane problemy