Szeregowanie w systemie Windows 2000/XP

Informacje wstępne


Ogólne podejście do szeregowania w Windows jest podobne do wcześniej przedstawionych. Wyróżniono dwa zakresu (pasma) priorytetów, z których wynika taż sposób zarządzania priorytetami wątków.

W paśmie zmiennych priorytetów stosowany jest algorytm rotacyjny oparty jest na priorytetach dynamicznych. Priorytet wątku w tym paśmie może ulec podwyższeniu po zakończeniu oczekiwania, a następnie jest stopniowo obniżany.

W paśmie priorytetów czasu rzeczywistego stosowany jest również algorytm rotacyjny, ale priorytety nie ulegają zmianie. Tak rozumiany czas rzeczywisty oznacza tylko bardziej przewidywalne zachowanie, nie gwarantuje natomiast utrzymania jakiegokolwiek reżimu czasowego.

W sumie wyróżniono 32 poziomy priorytetu, ale najniższy poziom zastrzeżony jest dla wątku bezczynności.

  • Szeregowaniu podlegają wątki, stanowiące obiekty w obrębie procesu.
  • Stosowany jest algorytm rotacyjny z wywłaszczaniem, oparty na priorytetach dynamicznych.
  • Wyróżnia się 32 poziomy priorytetu:
    • 0 — bezczynność (poziom systemowy, niedostępny),
    • 1 do 15 — priorytety dynamiczne (zmienne)
    • 16 do 31 — priorytety czasu rzeczywistego
  • Większa wartość (poziom) oznacza wyższy priorytet.

Definiowanie priorytetu


Wyróżniono kilka klas priorytetu, z których większość jest w paśmie priorytetów dynamicznych. Każda klasa reprezentowana jest przez pewną wartość priorytetu, która ustalana jest dla procesu. Wartość ta dziedziczona jest przez wątek procesu, ale jego priorytet bazowy może zostać w stosunku do klasy procesu skorygowany poprzez zastosowanie odpowiedniego modyfikatora. Oprócz podanych modyfikatorów w paśmie wątków czasu rzeczywistego możliwe są też wartości –7, -6, ..., -3, 3, 4, 5, 6. W wyniku zsumowania klasy priorytetu oraz modyfikatora nie można wyjść poza pasmo, czyli suma ta jest odpowiednio ograniczana.

  • Zdefiniowanie klasy priorytetu dla procesu: idle (4), below normal (6), normal (8), above normal (10), high (13), realtime (24).
  • Zmodyfikowanie priorytetu wątku w ramach klasy priorytetu: idle (-15), lowest (-2), below normal (-1), normal (0), above normal (+1), highest (+2), time critical (+15).
  • Priorytet bazowy wątku jest sumą wartości dla klasy oraz modyfikatora (priorytetu wątku).

Priorytet bazowy wątku


Dwa zasadnicze pasma priorytetu, decydujące o sposobie przeliczania wartości priorytetów wątków, to:

  • pasmo priorytetów dynamicznych z zakresu od 1 do 15,
  • pasmo priorytetów czasu rzeczywistego z zakresu od 16 do 31.

Warto zwrócić uwagę, że modyfikatory THREAD_PRIORITY_TIME_CRITICAL oraz THREAD_PRIORITY_IDLE reprezentują odpowiednio najwyższy i najniższy dostępny priorytet w danym paśmie . Modyfikatory takie oznaczają odpowiednio 31 i 16 w paśmie czasu rzeczywistego oraz wartości 15 i 1 w paśmie priorytetów dynamicznych, niezależnie od klasy priorytetu.

slajd 25

Struktury danych do zarządzania wątkami gotowymi


Podobnie jak w systemach UNIX i Linux podstawową strukturą danych, ułatwiającą pracę planisty — zwanego w polskich tłumaczeniach dyspozytorem (ang. dispatcher) — jest kolejka priorytetowa. W celu przyspieszenia wyszukiwania kolejki o najwyższym priorytecie stosowany jest wektor bitowy, wskazujący kolejki niepuste.

  • KiDispatcherReadyListHead — tablica kolejek wątków gotowych.
  • KiReadySummary — maska bitowa identyfikująca niepuste kolejki w tablicy KiDispatcherReadyListHead.

Tablica kolejek wątków gotowych


Przykład pokazuje stan kolejki priorytetowej, za pomocą której identyfikowanych jest pięć wątków gotowych, należących do dwóch procesów.

Dwa wątki procesu P1 (TA i TB) oraz jeden wątek procesu P2 (TC) mają priorytet na poziomie 3, a pozostałe 2 wątki procesu P2 (TC i TE) mają priorytet na poziomie 2.

slajd 27

Przełączanie kontekstu


Przypadki przełączania kontekstu są typowe dla planowania rotacyjnego z wywłaszczaniem na podstawie priorytetu.

Wywłaszczenie przez wątek o wyższym priorytecie może być konsekwencją:

  • wejścia wątku o wyższym priorytecie w stan gotowości,
  • podwyższenia priorytetu wątku gotowego.

Wywłaszczony wątek umieszczany jest na początku kolejki procesów gotowych.

Upłynięcie kwantu czasu nie musi oznaczać przełączenia kontekstu, gdyż może się okazać, że nie ma w systemie wątku gotowego o równym lub wyższym priorytecie.

  • Zakończenie działania wątku
  • Przejście w stan oczekiwania (samoistnie — w wyniku odwołania do systemu operacyjnego w programie np. wątku w związku z synchronizacją lub operacją wejścia-wyjścia)
  • Wywłaszczenie przez wątek o wyższym priorytecie
  • Upłynięcie kwantu czasu

Procedury zarządzania wątkami gotowymi


Realizacja szeregowania sprowadza się do wywołania jednej z dwóch procedur FindReadyThread lub ReadyThread.

Wywołanie FindReadyThread oznacza, że wątek wykonywany dobrowolnie zrzekł się procesora lub upłynął przydzielony mu kwant czasu. W związku z tym konieczne jest wybranie nowego wątku do wykonania.

Procedura ReadyThread uruchamiana jest dla konkretnego wątku, który wchodzi w stan gotowości lub któremu podwyższono priorytet, a jej celem jest zdecydować o dalszym losie tego wątku. Zależnie od wartości priorytetów, skutkiem wykonania procedury jest:

  • wywłaszczenie dotychczas wykonywanego wątku i wyekspediowanie na procesor wątku, dla którego uruchomiona została procedura, albo
  • umieszczenie wątku, dla którego została uruchomiona procedura, we właściwej dla jego priorytetu kolejce.
  • FindReadyThread

    • uruchamiana po zwolnieniu procesora przez wątek wykonywany,
    • szuka wątku gotowego o najwyższym priorytecie i ekspediuje go na procesor.
  • ReadyThread
    • uruchamiana dla wątku, który przechodzi w stan gotowości lub zwiększa priorytet,
    • porównuje priorytet gotowego wątku z priorytetem wątku wykonywanego i albo wywłaszcza wątek wykonywany albo kolejkuje wątek gotowy.

Przebieg wywłaszczenia przez ReadyThread


Algorytm pokazuje zasady wywłaszczania. Jeśli gotowy wątek Tg, dla którego uruchomiona została procedura, ma wyższy priorytet niż wątek wykonywany Tw , to następuje wywłaszczenie. W przeciwnym przypadku wątek Tg trafia na koniec właściwej dla jego priorytetu kolejki wątków gotowych. W przypadku wywłaszczenia wątek wywłaszczony trafia najczęściej na koniec kolejki wątków gotowych, właściwej dla swojego priorytetu. Wyjątkiem jest przypadek, gdy wątek wywłaszczony nie wykorzystał jeszcze pierwszego kwantu czasu, wówczas trafia na początek właściwej dla jego priorytetu kolejki.

Niech Tg oznacza wątek gotowy, Tw wątek wykonywany, a pri(T) priorytet wątku T.

  • if pri( Tg) > pri( Tw) then

    • if liczba wykorzystanych kwantów przez Tw ≥ 1 then umieść Tw na końcu KiDispatcherReadyListHead[pri(Tw)]
    • else umieść Tw na pocz. KiDispatcherReadyListHead[pri(Tw)]
  • else

    • umieść Tg na końcu KiDispatcherReadyListHead[pri(Tg)]

    Upłynięcie kwantu czasu


    Kwant czasu nie jest wyrażany w jednostka bezpośrednio związanych z czasem. Jednostka ma związek z taktem zegara, ale również nie jest to liczba taktów, gdyż każde przerwanie zegarowe zmniejsza liczbę jednostek o 3. Liczbę jednostek można zmieniać modyfikując w rejestrze Windows wartość HKLM\SYSTEM\CurrentControlSet\Control\PriorityControl\Win32PrioritySeparation.

    Wykorzystanie kwantu czasu skutkuje podobnymi działaniami, jak w innych podejściach z wywłaszczaniem, opartych na priorytecie, czyli rozpoczyna się poszukiwanie innego wątku do wykonania. Ponieważ jednak stosowane jest podejście priorytetowe, poszukiwany wątek nie może mieć priorytetu niższego niż wątek, który stracił kwant czasu. Jeśli takiego wątku nie ma, wątek dotychczas wykonywany otrzymuje kolejny kwant czasu.

    Jeśli następuje przełączenie kontekstu, ta prawdopodobnie znaleziony został wątek o takim samym priorytecie, jak dotychczas wykonywany. Gdyby w stanie gotowości był wątek o priorytecie wyższym, wcześniej nastąpiłoby wywłaszczenie i wątek wykonywany (o niższym priorytecie) nie doczekałby końca kwantu czasu.

    W pewnych warunkach priorytet wątku, który wykorzystał swój kwant czasu może zostać obniżony (patrz następne slajdy). W wyniku tego obniżenia może zaistnieć stan, w którym innych wątek gotowy ma priorytet wyższy, niż wątek dla którego kwant czasu właśnie upłynął.

    • Kwant wyrażanych jest jednostkach kwantu czasu.
      • Liczba jednostek do dyspozycji wątku wynosi:

        • 6 — w wersjach dla komputerów osobistych i stacji.
        • 36 — w wersjach dla serwerów.
      • Z każdym taktem zegara odejmowane są 3 jednostki.
      • Upłynięcie kwantu czasu (zredukowanie liczby jednostek do 0) powoduje wywłaszczenie z procesora pod warunkiem, że jest gotowy inny wątek o takim samym (lub wyższym) priorytecie.
      • Jeśli dotychczas działający wątek jest jedynym o tak wysokim priorytecie, przydzielony zostaje mu kolejny kwant.

      Regulacja kwantu czasu


      Wyrażenie kwantu w jednostkach nie związanych bezpośrednio z długością interwału zegara umożliwia zrealizowanie częściowego zanikania kwantu. Przykładem jest wejście w stan oczekiwania przed upłynięciem kwantu. Brak zanikania oznaczałby, że wątek nigdy nie utraci swojego kwantu, jeśli tylko będzie zgłaszał jakieś żądanie tuż przed jego upływem. Taki przywilej mają natomiast wątki w paśmie czasu rzeczywistego.

      • Wątkowi o priorytecie mniejszym niż 16 zabierana jest jedna jednostka kwantu, gdy wchodzi o w stan oczekiwania.
      • Jeśli jednak wątek działa na poziomie 14 lub wyższym, przed zredukowaniem jego kwant jest odnawiany.
      • Podobne postępowanie jest przeprowadzane w pewnych przypadku wątków pierwszoplanowych, nawet jeśli ich priorytet jest mniejszy niż 14.
      • W przypadku wątków o priorytetach powyżej 15 liczba jednostek kwantu jest odnawiana po wyjściu ze stanu oczekiwania.
        • Wydłużenie kwantu zamiast zwiększenie priorytetu nie powoduje głodzenie przetwarzania w tle (zakładając ten sam priorytet). Ogranicza jedynie czas procesora dla takiego przetwarzania. Wyższy priorytet wątków związanych z obsługą okna mógłby oznaczać, że wątki w tle nie otrzymywałyby w ogóle procesora.

          • Wątki procesu pierwszoplanowego mogą uzyskać 3-krotnie dłuższy kwant czasu, zależnie od ustawienia rejestru HKLM\ SYSTEM\ CurrentControlSet\Control\PriorityContr ol\Win32PrioritySeparation
          • Wydłużenie kwantu ma na celu zwiększenie preferencji dla wątków związanych z oknem pierwszoplanowym przy jednoczesnym uniknięciu zagłodzenia wątków drugoplanowych.
          • W ramach przeciwdziałania głodzeniu wydłużany jest również 2-krotnie czas dla wątków oczekujących długo (ponad 300 taktów) na procesor. Celem tego wydłużenia jest przeciwdziałanie inwersji priorytetów.

          Zmiana dynamicznych priorytetów wątków


          W zależności od zdarzenia, które spowodowało przejście wątku w stan oczekiwania, priorytet wątku, wchodzącego ponownie w stan gotowości, jest odpowiednio zwiększany. Zwiększenie priorytetu ma jednak charakter tymczasowy. Po upływie każdego kolejnego kwantu czasu jest on zmniejszany o 1, aż osiągnie poziom bazowy dla danego wątku.

          • Podwyższenie priorytetu wątku (maksymalnie do wartości 15) może nastąpić w następujących przypadkach:
            • po zakończeniu operacji wejścia-wyjścia,
            • po oczekiwaniu na zdarzenie lub semafor,
            • po zakończeniu oczekiwania przez wątek pierwszoplanowy,
            • po przebudzeniu wątku GUI,
            • po zbyt długim oczekiwaniu w stanie gotowości.
          • Podwyższony priorytet jest obniżany sukcesywnie o 1 po upływie kwantu czasu, aż wróci do wartości bazowej.

          Wzrost priorytetu po zakończeniu operacji wejścia-­wyjścia


          System Windows faworyzuje procesy interaktywne. Stąd wysoki wzrost priorytetu w przypadku zakończenie oczekiwania na dane z klawiatury lub reakcję myszy. Są to typowe urządzenia, którymi posługuje się użytkownik interaktywny. Również inne wątki, które zakończyły oczekiwanie na urządzenie zewnętrzne, otrzymują wyższy priorytet, gdyż mogą być ograniczone wejściem-wyjściem. Po uzyskaniu procesora nawet na krótki czas mogą ponownie zażądać operacji wejścia-wyjścia. W ten sposób równoważone jest obciążenie systemu.

          Wielkość podwyższenia jest definiowana przez moduł sterujący urządzenia wejścia-wyjścia.

          • Operacja związana z dyskiem, CD, portem równoległym lub kartą video — wzrost o 1
          • Operacja związana z siecią portem szeregowym, potokiem, skrytką pocztową—wzrost o 2
          • Operacja związana z klawiaturą lub myszą— wzrost o 6
          • Operacja związana z kartą dźwiękową— wzrost o 8
          • Wartość podwyższenia dodawana jest do bazowego priorytetu wątku.

          Wzrost priorytetu po oczekiwaniu na zdarzenie lub semafor


          Zdarzenia i semafory związane są z synchronizacją między procesami. Zwiększony o 1 priorytet będzie obowiązywał tylko przez 1 kwant czasu, gdyż zaraz po nim zostanie obniżony o 1, wracając tym samym do poziomu bazowego.

          • Wartość zwiększenia, 1, dodawana jest do bazowego priorytetu wątku.
          • Kwant czasu procesora zmniejszany jest o 1 jednostkę.

          Wzrost priorytetu po zakończeniu oczekiwania przez wątek pierwszoplanowy


          Zwiększenie kwantu czasu zostało już omówione. Warto zwrócić uwagę, że zwiększenie priorytetu jest tymczasowe, podczas gdy zwiększenie kwantu będzie obowiązywać tak długo, jak długo okno będzie na pierwszym planie.

          • Priorytet zwiększany jest o wartość zmiennej jądra PsPriority Separation, dostępnej też jako jedno z pól w rejestrze Windows pod nazwą HKLM\SYSTEM\ CurrentControlSet\Control\PriorityContr ol\Win32PrioritySeparation
          • Wartość zwiększenia dodawana jest do bieżącego priorytetu wątku.
          • Zależnie do wartości Win32PrioritySeparation może zostać zwiększony kwant czasu dla wszystkich wątków procesu pierwszoplanowego.

          Wzrost priorytetu po przebudzeniu wątku GUI


          Wątki, które obsługują okno (nie koniecznie pierwszoplanowe) mają zwiększany priorytet o 2, gdy pojawi się jakieś zdarzenie (jakiś komunikat) związane z tym oknem.

          • Wartość zwiększenia — 2 — dodawana jest do bieżącego priorytetu wątku.

          Przeciwdziałanie głodzeniu


          Skutkiem zbyt niskiego priorytetu wątku może być jego głodzenie w dostępie do procesora, jeśli zawsze będzie jakiś wątek gotowy o wyższym priorytecie. Zwiększenie jego priorytetu do największej możliwej wartości w paśmie zmiennych priorytetów daje mu możliwość „złapania” procesora chociaż na krótką chwilę. Jeśli upłynie przyznany czas, priorytet wraca do wartości bazowej, co może wymagać kolejnych kilku sekund oczekiwania, zanim wątek dostanie kolejną szansę na dostęp do procesora.

          Działanie takie ma między innymi na celu przeciwdziałanie inwersji priorytetów poprzez uruchamianie wątków, które być może przetrzymują jakieś zasoby potrzebne innym wątkom o wyższych priorytetach.

          • Co sekundę uruchamiany jest wątek balance set manager, którego jednym z zadań jest sprawdzanie czasu bieżącego oczekiwania wątków gotowych.
          • Jeśli wątek oczekuje dłużej niż 300 taktów zegara (około 3-4 sekundy), jego priorytet uzyskuje wartość 15, a kwant czasu zwiększa się dwukrotnie, a w wersjach „serwerowych" czterokrotnie.
          • Po upływie przyznanego kwantu, priorytet wątku wraca do poziomu bazowego.