Zakres rywalizacji o proces
Process Contention Scope to jeden z dwóch podstawowych sposobów planowania wątków. Obydwa to: lokalne planowanie procesów (znane jako Process Contention Scope lub Unbound Threads — model Many-to-Many) i systemowe planowanie globalne (znane jako System Contention Scope lub Bound Threads — model One-to-One) . Te klasy planowania są znane jako zakres rywalizacji o planowanie i są zdefiniowane tylko w POSIX . Planowanie zakresu rywalizacji o proces oznacza, że cały mechanizm planowania dla wątku jest lokalny dla procesu — biblioteka wątku ma pełną kontrolę nad tym, który wątek zostanie zaplanowany w LWP . Oznacza to również użycie modelu wiele-do-jednego lub wiele-do-wielu.
Rodzaje planowania PCS
Planowanie PCS jest wykonywane przez bibliotekę wątków. Biblioteka wybiera, który niezwiązany wątek zostanie umieszczony na którym LWP. Planowanie LWP jest (oczywiście) nadal globalne i niezależne od lokalnego planowania. Chociaż oznacza to, że niezwiązane wątki podlegają pewnego rodzaju zabawnej, dwupoziomowej architekturze planowania, w praktyce można zignorować planowanie LWP i zajmować się wyłącznie lokalnym algorytmem planowania. Istnieją cztery sposoby spowodowania przełączenia kontekstu aktywnego wątku (powiedzmy T1). Trzy z nich wymagają od programisty napisania kodu. Metody te są w dużej mierze identyczne we wszystkich bibliotekach.
- Synchronizacja . Zdecydowanie najczęstszym sposobem przełączania kontekstu (dzikie uogólnienie) jest żądanie przez T1 blokady mutex i jej nie uzyskanie. Jeśli blokada jest już utrzymywana przez T2, wówczas T1 zostanie umieszczony w kolejce uśpienia, oczekując na blokadę, umożliwiając w ten sposób uruchomienie innego wątku.
- pierwokup . Działający wątek (T6) robi coś, co powoduje, że wątek o wyższym priorytecie (T2) staje się uruchamialny. W takim przypadku aktywny wątek o najniższym priorytecie (T1) zostanie wywłaszczony, a wątek T2 zajmie jego miejsce w LWP. Sposoby na spowodowanie tego obejmują zwolnienie blokady, zmianę poziomu priorytetu T2 w górę lub T1 w dół.
- plonowanie . Jeśli programista umieści jawne wywołanie sched_yield() w kodzie, który jest uruchomiony T1, wówczas program planujący sprawdzi, czy istnieje inny uruchamialny wątek (T2) o tym samym priorytecie (nie może istnieć uruchamialny wątek o wyższym priorytecie ). Jeśli taki istnieje, zostanie on zaplanowany. Jeśli go nie ma, T1 będzie nadal działać.
- Dzielenie czasu . Jeśli PCS dostawcy pozwala na dzielenie czasu (jak Digital UNIX, w przeciwieństwie do Solaris), to T1 może po prostu skończyć swój wycinek czasu, a T2 (na tym samym poziomie priorytetu) otrzyma wtedy wycinek czasu.
Realizacja
Harmonogram wątków PCS ma bardzo prosty algorytm do decydowania, który wątek ma zostać uruchomiony. Każdy wątek ma przypisany numer priorytetu. Uruchamiane są wątki o najwyższych priorytetach. Te priorytety nie są dostosowywane przez bibliotekę wątków. Jedynym sposobem ich zmiany jest wyraźne wywołanie przez programistę thread_setschedparam(). Ten priorytet jest liczbą całkowitą w C. Nie udzielamy żadnych porad, jak wybrać wartość, ponieważ stwierdziliśmy, że sami nie używamy go zbyt często. Ty pewnie też nie.
Naturalną konsekwencją powyższego omówienia szeregowania jest istnienie czterech stanów szeregowania wątków. Wątek może znajdować się w jednym z następujących stanów:
- Aktywny : oznacza, że jest na LWP 5.
- Runnable : Oznacza to, że jest gotowy do uruchomienia, ale po prostu nie ma wystarczającej liczby LWP, aby go uzyskać. Pozostanie tutaj, dopóki aktywny wątek nie utraci swojego LWP lub dopóki nie zostanie utworzony nowy LWP.
- Sleeping : oznacza, że czeka na zmienną synchronizacji.
- Zatrzymany (nie w POSIX) : Oznacza, że wykonano wywołanie funkcji zawieszenia. Pozostanie w tym stanie, dopóki inny wątek nie wywoła na nim funkcji Kontynuuj.
- Zombie : oznacza, że wątek jest martwy i czeka na zebranie zasobów. (To nie jest rozpoznawalny stan dla użytkownika, chociaż może pojawić się w debugerze).