2011-06-29 9 views
5

Hi guys, Robiąc SMP przenoszenie niektórych z naszych kierowców (na cel powerpc) zaobserwowaliśmy pewne zachowania, na których muszę wam do rzucić trochę światła:disable_local_irq i jądra czasomierze

  1. On robienie local_irq_disable() na systemie UP jiffies ma tendencję do zamrożenia, tzn. licznik przestaje się zwiększać. Czy to jest oczekiwane? Pomyślałem, że przerwanie dekrementacji jest "wewnętrzne" i nie powinno zostać zmienione przez wywołanie typu local_irq_disable, ponieważ oczekiwałem, że do wyłączono przetwarzanie przerwań lokalnych przerwań IRQ (przerwanie zewnętrzne). System oczywiście zamarza również podczas wykonywania skoku jiffies local_irq_enable() i wydaje się rekompensować "upływ czasu" pomiędzy wywołaniem local_irq_disable() i enable().

  2. Robiąc to samo w systemie SMP (P2020 z 2 e500 rdzeniami), wyniki są zaskakujące. Najpierw moduł, który jest wstawiany do , robi to testowanie zawsze na rdzeniu 1. Dalej czasami nie widać zamrożenia licznika "jiffies", a czasami widzimy, że to rzeczywiście zamarza. Ponownie w przypadku zatrzymania liczby ma tendencję do skakania po wykonaniu funkcji local_irq_enable(). Nie mam pojęcia, dlaczego to może być dzieje się. Czy wiemy, że w przypadku SMP oba rdzenie uruchamiają programator czasowy, więc , że w niektórych przypadkach nie widzimy zamrożenia liczby jiffie lub jest to tylko na rdzeniu 0?

Ponadto, ponieważ liczniki jądra polegać na „jiffies” - oznaczałoby to, że żaden z naszych timerów jądra zadziała jeśli local_irq_disable() została zrobić? Co się dzieje w przypadku jednego z rdzeni w systemie SMP ?

Istnieje wiele innych pytań, ale myślę, że to wystarczy, aby rozpocząć na ogólną dyskusję o tym samym :)

TIA

NS

Niektóre więcej komentarzy z eksperymentów wykonanych .

Moje zrozumienie w tym momencie jest takie, że ponieważ czasomierze jądra zależą od "jiffies" do ognia, to w rzeczywistości nie uruchomią systemu UP podczas wydawania local_irq_save(). W rzeczywistości część naszego kodu opiera się na założeniu, że kiedy wystawię plik local_irq_save(), gwarantuje to również ochronę przed przerwaniami na lokalnym procesorze i licznikach czasu jądra.

Jednak przeprowadzając to samo doświadczenie w systemie SMP, nawet z obydwoma rdzeniami wykonującymi funkcję local_irq_save(), jiffie NIE zatrzymują inkrementacji, a system nie zawiesza się. Jak to jest możliwe ? Czy LINUX korzysta z jakiegoś innego mechanizmu do wyzwalania przerwań czasowych w systemie SMP lub ewentualnie z IPI? To również łamie nasze założenie, że local_irq_disable będzie chronić system przed licznikami czasu jądra działającymi w tym samym rdzeniu co najmniej.

W jaki sposób mamy zamiar napisać kod, który jest bezpieczny przed zdarzeniami asynchronicznymi, tj. Przerwaniami i zegarami jądra i jest ważny zarówno dla UP jak i SMP.

Odpowiedz

4

local_irq_disable tylko wyłącza przerwania na bieżącym rdzeniu, więc gdy jesteś jednym rdzeniem, wszystko jest wyłączone (włączając przerywanie czasu) i dlatego jiffie nie są aktualizowane. Podczas uruchamiania w SMP, czasami zdarza się, że wyłączasz przerwania na rdzeniu, które aktualizuje jiffies, czasami nie. Zazwyczaj nie stanowi to problemu, ponieważ przerywniki powinny być wyłączane tylko przez bardzo krótkie okresy, a wszystkie zaplanowane zegary będą uruchamiane po ponownym włączeniu przerwań.

Skąd wiesz, że twój moduł zawsze działa na rdzeniu 1? W obecnych wersjach jądra może nawet działać na więcej niż jednym rdzeniu w tym samym czasie (to znaczy, jeśli nie zmusiłeś go, aby tego nie robił).

+0

Od kiedy robiłem to wszystko w module_init, również drukowałem procesor, na którym byłem (get_cpu()). Teraz smutną częścią jest to, że w przypadkach, w których widziałem zablokowane "jiffies", byłem na 1 poziomie iw przypadkach, gdy "jiffies" nie utknęły, wciąż byłem na rdzeniu 1 !!! –

+0

Co dziwne, kiedy używam local_irq_save()/restore() zamiast local_irq_enable()/disable() problem z jiffies utknięcie nigdy nie dzieje się niezależnie od rdzenia, że ​​jestem na. Dokładnie zdezorientowany !! :( –

+0

Victor, co masz na myśli mówiąc, że działasz na więcej niż jednym rdzeniu w tym samym czasie? Czy to jest pewna rzecz? Czy możesz wskazać mi jakąś literaturę na ten temat? –

4

Istnieje kilka aspektów tego problemu. Weźmy im 1 o 1.

1.

a)

local_irq_save() po prostu czyści flagę IF z EFLAGS zarejestrować. Programy obsługi przerwań IRQ mogą działać współbieżnie z innymi rdzeniami.

Funkcja global_irq_save() jest niedostępna, ponieważ wymagałoby to komunikacji między procesami interpretera i nie jest tak naprawdę potrzebna, ponieważ lokalne wyłączanie irq jest przeznaczone tylko na bardzo krótki czas.

b)

nowoczesny APICS pozwala IRQ dynamiczną dystrybucję wśród obecnych rdzeni a poza rzadkimi wyjątkami, jądro zasadniczo programów niezbędnych rejestrów w celu uzyskania rozkładu round-robin z przerwań.

Konsekwencją tego jest to, że jeśli IRQ są wyłączone wystarczająco długo lokalnie, gdy APIC dostarcza przerwanie do rdzenia, który je wyłącza, wynikiem końcowym będzie to, że system przestanie otrzymywać to konkretne IRQ do punkt, w którym irqs są ostatecznie ponownie lokowane lokalnie na rdzeniu, które otrzymało ostatnie IRQ tego typu.

2.

chodzi o różne wyniki dotyczące jiffies aktualizacje oraz IRQ wyłączenie, to zależy od wybranego clocksource.

można dowiedzieć się, który z nich zostanie wybrane przez Consulting:

$ cat/sys/devices/system/clocksource/clocksource0/current_clocksource

jeśli masz TSC jako clocksource wtedy wszystkie rdzenie mają go lokalnie. Jednak jeśli twoje źródło zegara jest czymś innym, np .: HPET urządzenie zewnętrzne, to jiffie zostaną zamrożone z powodów opisanych w punkcie # 1.