Na čem aktuálně pracují vývojáři GNOME a KDE Plasma? Pravidelný přehled novinek v Týden v GNOME a Týden v KDE Plasma.
Před 25 lety zaplavil celý svět virus ILOVEYOU. Virus se šířil e-mailem, jenž nesl přílohu s názvem I Love You. Příjemci, zvědavému, kdo se do něj zamiloval, pak program spuštěný otevřením přílohy načetl z adresáře e-mailové adresy a na ně pak „milostný vzkaz“ poslal dál. Škody vznikaly jak zahlcením e-mailových serverů, tak i druhou činností viru, kterou bylo přemazání souborů uložených v napadeném počítači.
Byla vydána nová major verze 5.0.0 svobodného multiplatformního nástroje BleachBit (GitHub, Wikipedie) určeného především k efektivnímu čištění disku od nepotřebných souborů.
Na čem pracují vývojáři webového prohlížeče Ladybird (GitHub)? Byl publikován přehled vývoje za duben (YouTube).
Provozovatel čínské sociální sítě TikTok dostal v Evropské unii pokutu 530 milionů eur (13,2 miliardy Kč) za nedostatky při ochraně osobních údajů. Ve svém oznámení to dnes uvedla irská Komise pro ochranu údajů (DPC), která jedná jménem EU. Zároveň TikToku nařídila, že pokud správu dat neuvede do šesti měsíců do souladu s požadavky, musí přestat posílat data o unijních uživatelích do Číny. TikTok uvedl, že se proti rozhodnutí odvolá.
Společnost JetBrains uvolnila Mellum, tj. svůj velký jazykový model (LLM) pro vývojáře, jako open source. Mellum podporuje programovací jazyky Java, Kotlin, Python, Go, PHP, C, C++, C#, JavaScript, TypeScript, CSS, HTML, Rust a Ruby.
Vývojáři Kali Linuxu upozorňují na nový klíč pro podepisování balíčků. K původnímu klíči ztratili přístup.
V březnu loňského roku přestal být Redis svobodný. Společnost Redis Labs jej přelicencovala z licence BSD na nesvobodné licence Redis Source Available License (RSALv2) a Server Side Public License (SSPLv1). Hned o pár dní později vznikly svobodné forky Redisu s názvy Valkey a Redict. Dnes bylo oznámeno, že Redis je opět svobodný. S nejnovější verzí 8 je k dispozici také pod licencí AGPLv3.
Oficiální ceny Raspberry Pi Compute Modulů 4 klesly o 5 dolarů (4 GB varianty), respektive o 10 dolarů (8 GB varianty).
Byla vydána beta verze openSUSE Leap 16. Ve výchozím nastavení s novým instalátorem Agama.
Současné vývojové jádro je stále 2.6.32-rc6; během minulého týdne nevyšly žádné nové předverze.
Současné stabilní jádro je 2.6.31.6 vydané (společně s 2.6.27.39) 9. listopadu. Obě jádra obsahují dlouhý seznam důležitých oprav včetně některých, které jsou spojeny s bezpečností.
-- Acked-by: ve stylu Paula McKenneyho (díky Amitu Shahovi)
-- Hugh Dickins
Alokace šířky I/O pásma a její řízení je záludný problém; jak zde bylo diskutováno dříve, o řešení se na různých úrovních pokusilo několik skupin. Na minisummitu v Tokiu se sešli vývojáři různých I/O řadičů a rozhodli se k víceúrovňovému přístupu k problému. Od té doby jeden z vývojářů, Vivek Goyal, poznamenal:
Tento první krok je série patchů o dvaceti částech, která implementuje I/O řadič proporcionální váhy v I/O plánovači CFQ. Je vytvořena nová třída kontrolních skupin (cgroup) nazvaná „blkio“, přičemž každé skupině je přidělena I/O váha mezi 100 a 1000. Dostupná I/O propustnost je skupinám přidělována podle nakonfigurované váhy.
Práce uvnitř CFQ dává I/O řadiči jemnozrnnou kontrolu nad tím, kolik propustnosti každá skupina dostane. Na druhou stranu je CFQ umístěno na špatném místě pro identifikaci blokového I/O provozu, který není generován přímo v uživatelském prostoru (například zpětný zápis), nebo k přiškrcení aktivity na úrovni virtuální paměti. Dosáhnout toho bude vyžadovat integraci řadiče, který se do systému připojí na mnohem vyšší úrovni. Plán je napsat takový řadič, který bude transparentně fungovat ve stejné kontrolní skupině. Bude ale pravděpodobně potřeba pár dalších malých krůčků, než bude připraven k začlenění.
Mechanismus „sysctl“ jádro používá k exportu široké škály ladících voleb do uživatelského prostoru. Ve skutečnosti se jedná o dvě rozhraní, která byla podivně spojena dohromady: systémové volání sysctl() a hierarchie adresářů v /proc/sys. Z těchto dvou se mnohem více používá /proc/sys, a to do té míry, že vývojáři na systémové volání pomyslí jenom málokdy. Implementace sysctl() ale představuje významný objem kódu, který trpí chronickým zanedbáváním. Již léta proto byla cílem pokusů o odstranění.
Problém v odstranění sysctl() je samozřejmě v tom, že je součástí jaderného ABI. Dokud existuje možnost rozbití nějakých aplikací, toto ABI nelze odstranit. Proto stále sedí v jádře i přes fakt, že by si jeho nepřítomnosti všimlo jenom pár lidí.
Eric Biederman přišel s novým přístupem k problému. Jeho sada patchů odstraňuje současnou implementaci sysctl() a zbavuje se tak několika tisíc řádků nemilovaného kódu. Poté přidává nový wrapper, který ABI sysctl() emuluje pomocí /proc/sys. Jakákoliv aplikace, která sysctl() používá, by tedy měla nadále fungovat, ale kód věnovaný tomu, aby fungovala, bude značně zredukován.
Sada patchů stále některé vývojáře znepokojuje. Wrapper má svou vlastní konfigurační volbu, takže se někteří bojí, že by ji distributoři mohli zakázat a způsobit tak podivné chyby. Přístup k těmto proměnným přes /proc/sys bude mnohem pomalejší než předtím; to by ale neměl být problém: Přístup k sysctl proměnným běžně není operace kritická pro výkonnost. Nezdá se tedy, že by začlenění těchto patchů stála v cestě nějaká skutečná překážka; jednoho dne možná binární sysctl() opravdu zmizí do zapomnění.
IBM developerWorks zveřejnilo úvod do souborových systémů NilFS2 a exofs. Zajímavým aspektem NiLFS(2) je technika nepřetržitého vytváření snímků. Protože je NILFS strukturovaný do záznamů [log structured], zapisují se nová data na začátek logu, zatímco stará data stále existují (dokud není zapotřebí uvolnit místo sesbíráním odpadu). Protože stará data na disku zůstávají, je možné vrátit se v čase a prozkoumat jednotlivé epochy souborového systému. Tyto epochy jsou v NiLFS(2) nazývány kontrolními body [checkpoint] a jsou součástí systému. NiLFS(2) tyto kontrolní body vytváří s tím, jak dochází ke změnám, ale také je možné vytvoření kontrolního bodu vynutit.
Mnoho povyku ohledně fsync() a robustnosti při pádu se během minulého roku ve skutečnosti týkalo toho, jak mohou aplikace od operací souborového systému získat transakční sémantiku. Vývojář aplikací často chce, aby sada operací buď uspěla, nebo selhala jako celek – bez možnosti částečného dokončení. Poskytnout aplikacím způsob, jak toto chování získat, však může být náročné.
Btrfs se pokusil uživatelskému prostoru tuto možnost nabídnout pomocí ioctl() volání BTRFS_IOC_TRANS_START a BTRFS_IOC_TRANS_END. Tento přístup má ale problémy, protože se tato ioctl chovají jako pár systémových volání, přičemž všechny operace mezi nimi jsou považovány za transakci v souborovém systému. Když ale něco selže nebo se aplikace nikdy nedostane k tomu, aby transakci ukončila, věci se nakonec zastaví. Proto kód btrfs obsahuje tento komentář:
Jinak řečeno je to nebezpečná schopnost, kterou nelze obecně zpřístupnit.
Sage Weil zaslal patch, který používá o něco jiný přístup k problému. Klíčovým nápadem je zde vyhnout se problému s nikdy nedokončenými transakcemi tak, že se celá věc zabalí do jediného systémového volání. Výsledkem je nový ioctl() příkaz BTRFS_IOC_USERTRANS; je pravděpodobné, že na tom bude potřeba ještě zapracovat, ale mohl by to být základ pro budoucí transakce pro uživatelský prostor.
Příkaz přebírá strukturu, která vypadá podobně jako tato:
struct btrfs_ioctl_usertrans { __u64 num_ops; struct btrfs_ioctl_usertrans_op *ops_ptr; __u64 num_fds; __u64 data_bytes, metadata_ops; __u64 flags; __u64 ops_completed; };
Argument ops_ptr ukazuje na pole num_ops jednotlivých operací:
struct btrfs_ioctl_usertrans_op { __u64 op; __s64 args[5]; __s64 rval; __u64 flags; };
op zde popisuje jednu operaci. Může to být:
Pro každou operaci args obsahuje argumenty podobné těm, které by bylo možné nalézt u odpovídajícího systémového volání. Jeden zajímavý rozdíl je v tom, že zde nejsou žádná napevno stanovená čísla popisovačů souborů; každá transakce místo toho dostane novou tabulku popisovačů a všechny operace pracují s indexy do této tabulky. Transakce v podstatě fungují v prostoru popisovačů souborů odděleného od toho, který používá volající proces.
Pole flags popisuje, jak má být interpretována návratová hodnota každé operace. Může obsahovat kteroukoliv hodnotu z:
V každém případě příznak způsobí, že bude návratová hodnota porovnána proti poli rval; jestliže je porovnání úspěšné, transakce selže.
Co se stane, když transakce selže? Částečně dokončená transakce není vrácena zpět [rollback]; btrfs není databáze, takže na něco takového není připraven. Místo toho se do uživatelského prostoru vrátí počet úspěšně dokončených operací. Aplikace může volitelně poskytnout příznak BTRFS_IOC_UT_FLAG_WEDGEONFAIL, který způsobí, že transakce zůstane v btrfs otevřená, což souborový systém uzamkne, dokud systém není rebootován. To se může zdát jako poměrně antisociální přístup k atomičnosti transakcí, ale pokud je selhání jak nepravděpodobné, tak vysoce problematické, může to být správný postup.
Takový patch přitahuje mnoho otázek. První překážkou může být fakt, že vyžaduje vyexportovat mnoho implementací systémových volání modulům, což je změna, která se v minulosti setkávala s odporem. Jaderný kód normálně nepotřebuje volat funkce jako sys_mkdir(), ale tento patch přesně to dělá. Volání implementací systémových volání přímo může být na některých architekturách záludné a obecně jsou dobré důvody pro to tyto funkce modulům nezpřístupňovat.
Další problém je, že souborový systém nemůže žádným způsobem zjistit, jestli transakce uspěje, předtím než do ní skočí; to nejlepší, co může udělat, je rezervovat si nějaký prostor pro metadata podle odhadu, který mu poskytne aplikace. Pokud se transakce může dokončit jenom částečně, není to transakce, ale alternativa v podobě uzamknutí systému může lidi nechávat na pochybách, jestli není lepší cesta.
Potom je zde otázka, která padla v konferenci: btrfs nabízí levné snímkování [snapshot], proč pro implementaci transakcí nepoužívat ty? Používání snímků by mělo výhodu využití existující funkcionality a mělo by umožnit vrácení do předchozího stavu. Problémem by zde byla výkonnost: Snímky nejsou zase tak levné, obzvláště když se uváží potřeba vynechat jakoukoliv další aktivitu souborového systému, když je transakce aktivní. Chris Mason proto naznačil, že stará náhrada – dopředné logování [write-ahead logging] – by byla lepší, protože by se chovala mnohem lépe. Myslí si ale, že ioctl() s více operacemi by se mohlo chovat ještě lépe.
A nakonec se zdá, že je tu skutečná podoba mezi tímto API a o něco obecnějším mechanismem sysletů. Syslety jsou již nějaký čas na vedlejší koleji, ale pokud by se zdálo, že by mohly být dobrým řešením problému, mohly by se vrátit do popředí.
Je zjevné, že jako velká část btrfs i toto nové ioctl() je rozdělaná práce. Pokud se dostane do hlavní řady, pravděpodobně se po cestě trochu změní. Problém, který se tento patch pokouší řešit, je ale reálný; je to rozhodně záležitost, o které má cenu přemýšlet.
„Fanotify“ je velmi revidovaný systém pro poskytování upozornění na události souborového systému do uživatelského prostoru s možností zablokovat uživatelským prostorem operace open() u specifických souborů. Zamýšleným použitím jsou nástroje pro vyhledávání malwaru, ale byly zmiňovány i další možnosti: Jako jedna z nich bylo citováno hierarchické úložiště. Tento kód má do jádra dlouhou a těžkou cestu z několika důvodů: Jaderní vývojáři nejsou velkými příznivci vyhledávání malwaru a definitivní stanovení ABI pro uživatelský prostor je náročné.
První překážka byla víceméně překonána. I vývojáři, kteří si myslí, že je vyhledávání malwaru nejhorší druh podfuku, se shodují na tom, že když tyto nástroje budou používat dobře definované jaderné rozhraní, bude to lepší, než když se uchýlí k ošklivým trikům, jako je zaháčkování v tabulce systémových volání. Potíže s ABI nicméně může být složitější překonat. V nejnovější verzí fanotify vývojář Eric Paris tuto záležitost alespoň pro část funkcionality možná vyřešil.
Nová verze odstraňuje novátorské rozhraní používající setsockopt() a nahrazuje ho párem nových systémových volání. První z nich je fanotify_init():
int fanotify_init(unsigned int flags, unsigned int event_f_flags, int priority);
Toto systémové volání inicializuje subsystém fanotify a vrátí popisovač souboru, který se bude používat pro další operace. Implementovány jsou dvě hodnoty flags: FAN_NONBLOCK vytvoří neblokující popisovač souboru a FAN_CLOEXEC nastaví příznak uzavření při exec. event_f_flags a priority se v současnosti nepoužívají; měly by být nastaveny na nulu.
Správa událostí se poté provádí pomocí fanotify_mark():
int fanotify_mark(int fanotify_fd, unsigned int flags, int dfd, const char *pathname, u64 mask, u64 ignored_mask);
Toto volání „označkuje“ specifické části hierarchie souborového systému a informuje o zájmu na tom získávat události týkající se daných souborů. fanotify_fd je popisovač souboru, který vrátilo fanotify_init(). Parametr flags musí být buď FAN_MARK_ADD nebo FAN_MARK_REMOVE. Určuje, jestli toto volání přidává nové značky, nebo odstraňuje existující; také je několik příznaků, které ovlivňují následování symbolických odkazů a značkování adresářů (bez jejich obsahu).
Soubor(y), které mají být označeny, jsou určeny pomocí dfd a pathname; tyto parametry fungují podobně jako ty v systémových voláních *at(). Jestliže je dfd rovno AT_FWCWD, pathname je vyhodnocováno podle současného adresáře. Pokud dfd ukazuje na adresář, vyhodnocování pathname začíná z tohoto adresáře. Jestliže je nicméně pathname null, pak je dfd interpretováno jako objekt k označení.
A nakonec mask a ignored_mask řídí, které události jsou hlášeny. Aby byla specifická událost vygenerována, soubor musí mít nastaven odpovídající příznak v mask a vynulován v ignored_mask. Příznaky jsou:
Také existuje událost FAN_Q_OVERFLOW pro přetečení fronty událostí, ale ta v současnosti není implementována.
Jakmile jsou soubory označkovány, aplikace může jednoduše číst události z popisovače souboru fanotify. Události vypadají takto:
struct fanotify_event_metadata { __u32 event_len; __u32 vers; __s32 fd; __u64 mask; };
Zde je event_len délka struktury, vers indikuje, která verze fanotify strukturu vygenerovala, fd je otevřený popisovač souboru pro objekt, ke kterému se přistupovalo, a mask popisuje, co se skutečně děje.
Mezi těmito komponentami chybí jedna kriticky důležitá: Neexistuje v ní způsob, jak by mohl uživatel fanotify na tyto události reagovat. Konkrétně možnost blokovat volání open(), hlavní součást procesu pro vyhledávání malwaru, chybí. Ta bude pravděpodobně přidána v budoucí verzi. Mezitím Eric požádal o možnost začlenit kód na upozorňování do linux-next, pravděpodobně s plánem na začlenění do 2.6.33. V době psaní tohoto článku se neobjevily námitky.
Originál tohoto článku pro LWN.net napsal Darren Hart.
Mechanismus futexů [PDF], který v 2.5.7 zavedli Rusty Russell, Hubertus Franke a Mathew Kirkwood, je rychlé, jádrem asistované zamykací primitivum pro aplikace v uživatelském prostoru. Poskytuje velmi rychlé získávání a uvolňování zámku, o který se nesoupeří. Stav futexu je uložen v proměnné v uživatelském prostoru (na všech platformách bezznaménkové 32bitové celé číslo). Pro změnu stavu futexu se v případě, kdy se nesoupeří, používají atomické operace bez režie způsobené systémovým voláním. Když se soupeří, zavolá se jádro, které úlohy uspává a probouzí.
Futexy jsou základem pro několik konstrukcí pro vzájemné vyloučení běžně používaných ve vícevláknovém programování. Mezi ty patří pthread mutexy, stavové proměnné [condvars], semafory, rwzámky [rwlocks] a bariéry. Během minulých let prošly mnoha plastickými i rekonstruktivními operacemi a nyní jsou efektivnější, funkčnější a lépe dokumentované než kdy dříve.
I když jenom pár vývojářů aplikací bude používat futexy přímo, letmé znalosti toho, jak to dělat, jsou nutné k tomu, aby člověk mohl ocenit vylepšení, která budou prezentována později. V jednoduchém příkladu lze futexy použít k uložení stavu zámku a poskytnout jadernou čekací frontu pro úlohy blokované zámkem. Aby se minimalizovala režie způsobená systémovými voláními, měl by tento stav umožňovat atomické získání zámku, když se o něj nesoupeří. Stav je možné definovat jako:
K získání zámku lze použít atomickou instrukci pro test a nastavení (jako je cmpxchg()), kde se testuje na nulovost a nastavuje 1. V tomto případě zamykající vlákno získá zámek bez účasti jádra (a jádro neví nic o tom, že futex existuje). Když se další vlákno pokusí zámek získat, test na nulovost selže a je potřeba jádro zapojit. Blokované vlákno poté může použít systémové volání futex() s operačním kódem FUTEX_WAIT a uspat se kvůli futexu, přičemž jako parametr předává adresu stavové proměnné futexu. Aby zámek uvolnil, změní jeho vlastník stav na nulu (odemčeno) a vyšle operační kód FUTEX_WAKE, který probudí blokované vlákno; to se následně vrátí do uživatelského prostoru a pokusí se zámek získat (jak bylo popsáno výše.) To je zjevně triviální příklad se spoustou prostoru pro optimalizace. Dokument Futexy jsou záludné [PDF] Ulricha Dreppera je stále uznávaná dokumentace pro používání futexů k vybudování zamykacích primitiv, jako jsou mutexy. Zkoumá mnoho souběhů spojených s používáním futexů a také optimalizace, které vylepšují příklad uvedený zde.
Když uživatelské vlákno volá jádro systémovým voláním futex, předá adresu stavu futexu (uaddr), operační kód, který má být proveden (op) a různé další argumenty. Uaddr jádro použije k vygenerování unikátního „futex_key“ (klíč futexu), kterým se na futex odkazuje. Pokud vlákno požaduje čekání na futex jako u FUTEX_WAIT, vytvoří se „futex_q“ a zařadí se do fronty v tabulce hashů „futex_queues“. Pro každou úlohu blokovanou futexem existuje jeden futex_q, což může znamenat mnoho futex_q na jeden futex. futex_queues samy o sobě (seznamy tabulek hashů, ne „futexy_q“) se sdílí mezi futexy, protože mnoho futex_key má hash pro stejnou frontu. Tyto vztahy jsou naznačeny níže:
Ve většině případů neexistuje politika, která by určovala, jak má být používána stavová proměnná v uživatelském prostoru (bez ohledu na to, co říkají nebo neříkají manuálové stránky futexů). Aplikace (nebo knihovna jako glibc) používá tuto hodnotu k definování stavu zamykající konstrukce, která je implementována. Může to být jednoduchá pravdivostní hodnota (jako v příkladu výše), ale optimalizované implementace a další zamykací mechanismy vyžadují komplexnější stavové hodnoty.
Kromě jednoduchých operací FUTEX_WAIT a FUTEX_WAKE jádro také zvládá speciální operace, které vyžadují větší znalosti o stavu zamykací konstrukce, než které lze mít v uživatelském prostoru; nejvýznamnější z nich jsou řetězce dědění priorit [priority inheritance, PI] a robustní seznamy. PI a robustní futexy jsou výjimkami z pravidla „politika je definována v uživatelském prostoru“ týkajícího se stavové proměnné. Jejich stav závisí nejenom na stavu zamknutí futexu, ale také identifikuje vlastníka a stanovuje, jestli existují čekatelé. Jako taková je hodnota futexu definována jako identifikátor vlákna (TID), které zámek vlastní, a bit, který indikuje čekající vlastníky. Tato politika stále umožňuje atomické operace v uživatelském prostoru tak, aby nebylo potřeba v případě, kdy se nesoupeří, volat jádro.
Od svého debutu v 2.5.7 byly futexy mnohokrát vylepšeny mnoha vývojáři. Mezi významnější zlepšení patří probouzení úloh v reálném čase založené na prioritách (Pierre Peiffer), robustní a PI futexy (Ingo Molnár a Thomas Gleixner.) Tato zlepšení byla adekvátně popsána na LWN.net stejně jako v excelentních diskuzích v jaderné e-mailové konferenci. Autor článku se futexům začal věnovat před dvěma a půl lety. Kromě několika oprav, které se zabývaly neobvyklými okrajovými případy a souběhy, se od těchto dřívějších příspěvků kód futexů dočkal i dalších vylepšení ohledně výkonnosti a funkcí.
Velká snaha byla zamířena na omezení režie spojené s futexy. Eric Dumazet zavedl privátní futexy jako optimalizaci pthread mutexů PTHREAD_PROCESS_PRIVATE. Privátní futexy mohou používat pouze vlákna stejného procesu. Odlišují se od sebe jednoduše svými virtuálními adresami, zatímco sdílené futexy mají různé virtuální adresy v každém procesu, takže jádro musí pro unikátní identifikaci vyhledat jejich fyzickou adresu. Tato optimalizace odstraňuje používání semaforu mmap_sem, což omezuje celosystémové soupeření. Také to odstraňuje atomické operace při čítání odkazů privátních futexů, což vede na omezení poskakování cachí na SMP strojích. Glibc ve výchozím nastavení nyní používá privátní futexy.
Peter Zijlstra dále omezil závislost futexů na mmap_sem použitím get_user_pages_fast() na rychlých cestách, přičemž využil get_user_pages() a zatlačil zámky mmap_sem do pomalých cest (září 2008). Tyto změny navíc měly výhodu v tom, že odstranily většinu logiky spojené s virtuální pamětí z kernel/futex.c, což kód významně zjednodušilo. Vzhledem ke své závislosti na adresách v uživatelském prostoru jsou futexy obtíženy několika možnými body výpadků. Držení mmap_sem komplikovalo logiku výpadů, protože ho bylo nutné uvolnit před voláním get_user(). S omezeným využíváním mmap_sem autor článku významně zjednodušil logiku výpadků (březen 2009), což vedlo na mnohem čitelnější kód.
Bitovou maskou podmíněné probouzení přidal Thomas Gleixner (únor 2008), aby umožnil optimalizovanou implementaci rwzámků v glibc. FUTEX_WAIT_BITSET a FUTEX_WAKE_BITSET umožňují uživateli specifikovat bitovou masku, která omezuje probouzené úlohy na ty, které specifikovaly stejnou masku (nebo nadřazenou jako FUTEX_BITSET_MATCH_ANY), když začaly čekat.
Od zavedení PI futexů byla implementace stavových proměnných pthread_cond_broadcast() (s PI mutexem) nucena probouzet všechny čekající, místo toho aby využila FUTEX_REQUEUE, protože v PI futexech chyběla podpora pro znovuzařazování do fronty. To vede k probouzecí bouři, protože všichni čekající závodí zpět do uživatelského prostoru, aby tam soupeřili o zámek. Také se jí nepodaří zajistit, že úloha o nejvyšší prioritě zámek získá první. Nejnovější jádra (2.6.31-r1* a 2.6.32-rc*) nyní obsahují patche autora článku FUTEX_CMP_REQUEUE_PI (duben 2009), které na straně jádra poskytují podporu pro opakované řazení čekajících z ne-PI futexů na PI futexy. S patchi glibc, na kterých pracuje Dinakar Guniguntala, budou aplikace běžící v reálném čase brzy schopné používat stavové proměnné pthread s garantovaným pořadím probouzení a menším počtem probuzení celkově.
I když je několik věcí, které by vývojáři futexů mohli zvažovat do budoucna, doufají, že kernel/futex.c a veškeré jeho příčetnost ničící a játra zabíjející šílenství lze nechat alespoň na chvíli v klidu. Žádný článek nicméně není kompletní bez seznamu dalších kroků, takže v budoucnu by se mohly nějaké pozornosti těšit následující záležitosti:
Manuálové stránky: Současné manuálové stránky neobsahují některé z nových operací futexů. Naznačují politiku pro hodnotu futexu, což s ohledem na používání futexů vedlo k nějakým zmatkům. Nejhorší je v tomto případě to, že definice futex() pro uživatelský prostor byla odstraněna z /usr/include/linux/futex.h takže manuálové stránky jsou nejenom nekompletní, ale také nepřesné. Uživatelé futexů musí použít rozhraní systémového volání přímo.
Adaptivní futexy: Je možné, že část režie plánování futexů by bylo možné omezit volitelnou dobou čekání v cyklu předtím, než se v jádře začne spát. Protože ale futexy odhalují svůj stav uživatelskému prostoru, čekat lze také v uživatelském prostoru, stejně jako se to nyní dělá u adaptivních mutexů v glibc; protože chybí informace o tom, jestli vlastník běží, je čekání v cyklu omezeno na smyčku s maximálním počtem pokusů.
Přerušitelné futexy: Je určitý zájem o přerušitelné operace blokování zámku ze strany velkých proprietárních softwarových projektů. Operace s futexy se v současnosti restartují v případě doručení signálu místo toho, aby do uživatelského prostoru vrátily -EINTR. Bylo by možné označit futexy FUTEX_INTERRUPTIBLE, tato značka by byla kontrolována při signálem vyvolaném probuzení, aby se zjistilo, jestli má být systémové volání restartováno nebo jestli má být do uživatelského prostoru vráceno ECANCELED. Vytvoření takové vlastnosti do zamykacího primitiva by znamenalo změny nesplňující specifikace POSIX v knihovně pthread, ale to není bezprecedentní.
Vylepšení škálovatelnosti: Na LKML probíhaly diskuze ohledně privátních a pro NUMA optimalizovaných tabulkách hashů. Tabulka hashů futexů je sdílena mezi všemi procesy a je chráněna spinlocky, což může vést ke značné režii obzvláště na rozsáhlých systémech. Tato režie není k ničemu dobrá, pokud jsou tyto systémy rozděleny mezi NUMA uzly, nebo dokonce ani pro procesy, které používají privátní futexy exkluzivně.
Sada testovacích nástrojů futexů: Autor článku sestavuje seznam požadavků pro vyčerpávající sadu testů, které ověří funkcionalitu futexů. Tato sada by při dalším vývoji sloužila k testování regresí. Velký počet okrajových případů a možností chybného využití futexů vytvoření takové sady komplikuje a způsobuje, že je tento úkol poměrně náročný.
Autor by rád poděkoval následujícím lidem: John Stultz, Will Schmidt, Paul McKenney, Nivedita Singhvi a samozřejmě Jon Corbet, díky jejichž revizím je tento článek čitelnější a kompletnější, než by jinak byl.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej: