programmatūra · 6 min · 12.09.2026

Četri ielāpi labo kešatmiņu apzinošo plānošanu: nepareizs skaitītājs izmeta uzdevumus no LLC

Kešatmiņu apzinošā plānošana Linux kodolā ieguva četrus labojumus. Intel inženieris Tims Čens (Tim Chen) 10. septembrī nosūtīja kodola adresātu sarakstam sēriju, kas maina 340 rindas deviņos failos un noņem 94. Divi ielāpi neļauj uzdevumam pazust no tam labvēlīgākās kešatmiņas, divi labo atmiņas lietošanu pēc atbrīvošanas.

Pati funkcija kodolā iekļuva versijā 7.2. Mēnesi pēc laidiena testētāji atrada, ka dažos gadījumos plānotājs dara tieši pretējo tam, kam tas domāts. Sērija uzliekas uz sched/urgent zara un adresēta Pīteram Zijlstram (Peter Zijlstra), kurš uztur kodola plānotāju.

Ko dara kešatmiņu apzinošā plānošana

Servera procesoros katram kodolu blokam ir sava pēdējā līmeņa kešatmiņa, saīsināti LLC. Ja divi viena procesa pavedieni strādā ar kopīgiem datiem, bet plānotājs tos izkaisa pa dažādiem blokiem, katra datu porcija jāved caur galveno atmiņu. Kešatmiņu apzinošā plānošana skaita, cik daudz laika uzdevums pavada katrā LLC, izvēlas tam vienu preferred_llc un turpmāk cenšas uzdevumu turēt tur.

Skaitīšanu veic account_mm_sched(), ko izsauc update_curr() ceļā. Statistiku līdz šim glabāja mm_struct laukā sc_stat, tātad tā piederēja adrešu telpai. Tieši šī izvēle radīja divas no četrām kļūdām.

Skaitītājs, kas skaita citu kopu

Xiaomi izstrādātājs Džans Sušens (Zhan Xusheng) 27. augustā ziņoja par vienu pārbaudi failā kernel/sched/fair.c. Funkcija alb_break_llc() salīdzina divus skaitītājus: nr_pref_llc_running pret cfs.h_nr_runnable. Tie seko dažādām uzdevumu kopām. Pirmais uztur rindā ieliktos uzdevumus, otrais izlaiž tos, kurus funkcija set_delayed() ir izņēmusi no skaita, kamēr uzdevums vēl paliek rindā.

Ar ieslēgtu DELAY_DEQUEUE tikko aizmidzis uzdevums tur pirmo skaitītāju augstāku par otro. Vienādība neizpildās, pārbaude atgriež nepatiesu vērtību un aktīvā slodzes balansēšana pārstāj ievērot LLC izvēli.

Džans problēmu atrada, lasot kodu. Divu ligzdu qemu viesī viņš to izprovocēt nevarēja: ar sešiem darbīgiem un desmit guļošiem pavedieniem p->preferred_llc netika piešķirts nevienam uzdevumam, kamēr pati alb_break_llc() nostrādāja 21 reizi.

Skaitītājs ir otra virskopa, tāpēc kļūda ir vienpusēja: pārbaude var neaizsargāt, bet nekad neaizsargā nepareizi.

Stopper pavediens pazaudē nodomu

Otrais ielāps nāk no Lu Vanga (Lu Wang) un ir jau ceturtajā redakcijā. Aktīvo slodzes balansēšanu izpilda atsevišķs stopper pavediens. Tas uzbūvē jaunu lb_env struktūru, kas nepārmanto lauku migration_type. Bez tā can_migrate_task() neredz migrācijas iemeslu un var aizvest uzdevumu prom no tā LLC.

Labojums pievieno karodziņu LBF_ACTIVE_LB_LLC un izvēlas stopper atsaukumu jau brīdī, kad balansēšana tiek pieprasīta. Čens pavadvēstulē skaidro, kāpēc migration_type netiek vienkārši padots caur stopper: tas sajauktu aizkavētās izņemšanas loģiku.

KASAN noķēra mm, kas pazūd execve laikā

Trešo problēmu ar KASAN atrada Hjonvu Kims (Hyunwoo Kim). Funkcija account_mm_sched() lasa statistiku caur p->mm->sc_stat. Neviena slēdzene šo mm struktūru dzīvu netur.

Kims aprakstīja precīzu sacensību. Uz viena CPU notiek rakstīšana konveijerā, try_to_wake_up() paņem otra CPU rindas slēdzeni un nonāk līdz account_mm_sched(), kas nolasa tur darbojošā uzdevuma mm. Tajā pašā brīdī otrs CPU izpilda execve(), exec_mmap() pārslēdz uzdevumu uz jaunu mm un ceļš no mmput() līdz __mmdrop() atbrīvo veco. KASAN žurnālā tas izskatās kā 8 baitu lasījums no atbrīvotas atmiņas funkcijā update_se().

Iepriekšējais labojums, commit 9f23469401b0, pieņēma, ka active_mm atsauce struktūru notur dzīvu. Izpildot execve, arī active_mm tiek pārlikts uz jauno mm, tāpēc tā atsauce pazūd. Paliek vienīgi bprm->old_mm atsauce, kuras atdošana ir tieši tā atbrīvošana, kas kļūdu rada.

Labojums sadalīts divos ielāpos. Pirmais izceļ sched_cache_stat no mm_struct atsevišķā struktūrā sched_cache_group ar atsauču skaitītāju un RCU atbrīvošanu. Otrais liek katram uzdevumam paņemt savu atsauci copy_mm() un exec_mmap() brīdī, atdodot to exit_mm(). Rindas slēdzenes ņemšanu mm atbrīvošanas ceļā Čens nosauc par sliktāku darījumu.

Blakusefekts ir tāds, ka statistikas grupa vairs nav piesaistīta adrešu telpai. Čens raksta, ka tās īpašnieks vēlāk varētu būt lietotāja definēta grupa, cgroup vai numa_group. Abi šie ielāpi ir arī pirmie divi no atsevišķa RFC par uzdevumu grupēšanu caur prctl.

Divas kļūdas paliek ārpus sērijas

Pavadvēstule uzskaita divas problēmas, kas vēl tiek apspriestas. Viena ir nepareizs donora konteksts, ko saņem task_tick_cache(). Otra ir konflikts ar Intel Turbo Boost Max tehnoloģiju jeb ITMT.

ITMT gadījumā Intel inženieris Čens Ju (Chen Yu) apraksta konkrētu situāciju. CPU 0 ar augstāko prioritāti izpilda uzdevumu, kas dod priekšroku LLC3, bet slodzes balansētājs uz CPU 120 to paņemt nevar. Pārbaude sched_asym() neļauj vilkt vienīgo uzdevumu no augstākas prioritātes kodola uz zemākas prioritātes kodolu. Uzdevums paliek nepareizajā kešatmiņā bez laika ierobežojuma.

Ielāps tam pievieno piecas rindas un dzēš vienu. Tipam migrate_llc_task šī pārbaude tiek izlaista. Hibrīdajiem procesoriem ar P un E kodoliem līdzīgu izņēmumu Čens Ju apzināti nepievienoja. Viņš skaidro, ka atšķirība kodolu veiktspējā ir pārāk liela, lai kešatmiņas tuvums to atsvērtu, tāpēc filtrs SD_ASYM_CPUCAPACITY paliek neskarts, kamēr kāds uzrāda pretēju mērījumu.

Četru ielāpu sērija mērķē Linux 7.3. Abiem atmiņas labojumiem Hjonvu Kims ir devis Tested-by atzīmi. Čens lūdz tos ņemt kodolā kopā, jo atsevišķi tie problēmu neatrisina.

Avoti

komentārisaruna

Komentāri

Šim rakstam vēl nav komentāru. Esi pirmais, kurš dalās ar savu viedokli.

Pievieno komentāru

Tavs e-pasts netiks publicēts. Obligātie lauki atzīmēti.

vēl no programmatūrasaistītie