Пока не вижу её будущего, но не могу записать это в ту, которую сейчас пишу. В общем, я сломался об исходный код, а оказалось, что всё макросами генерится.
Изучал я код __free_pages
из mm/page_alloc.c
. И в нём упоминается некий PageHead()
, который я не смог ни нагрепать, ни найти его в elixir. Даже поиск в гитхабе ничего путного не дал. Зато, нашёл эту функцию в ядрах v4.3
и младше. Даже нашёл коммит, который удаляет эту функцию. В нём же он добавляет её использование. Я долго недоумевал по поводу. Пока не обратил внимание:
__PAGEFLAG(Head, head) CLEARPAGEFLAG(Head, head)
-__PAGEFLAG(Tail, tail)
...
+static inline int PageTail(struct page *page)
{
- BUG_ON(!PageHead(page));
- ClearPageHead(page);
+ return READ_ONCE(page->compound_head) & 1;
}
Человек убрал использование макроса __PAGEFLAG
с аргументами Tail, tail
и добавил функцию PageTail
. Использование макроса с аргументами Head, head
он не добавил. Это навело меня на мысль, что эти макросы могут использоваться для генерации кода для доступа к флагам страницы. И действительно, определение макроса чётко даёт понять:
#define __PAGEFLAG(uname, lname, policy) \
TESTPAGEFLAG(uname, lname, policy) \
__SETPAGEFLAG(uname, lname, policy) \
__CLEARPAGEFLAG(uname, lname, policy)
Внутри этого макроса есть заветный TESTPAGEFLAG(uname, lname, policy)
, который раскрывается в:
#define TESTPAGEFLAG(uname, lname, policy) \
static __always_inline bool folio_test_##lname(struct folio *folio) \
{ return test_bit(PG_##lname, folio_flags(folio, FOLIO_##policy)); } \
static __always_inline int Page##uname(struct page *page) \
{ return test_bit(PG_##lname, &policy(page, 0)->flags); }
— именно этот макрос и генерирует заветный PageHead
(Page##uname
).