Освобождение блока
Функция free pages buiko реализует стратегию buddy-системы для освобождения страничных кадров. Она принимает три входных параметра6:
- раде — адрес дескриптора первого страничного кадра в освобождаемом блоке;
- zone — адрес дескриптора зоны;
- order — логарифмический размер блока.
Функция предполагает, что возвращающая ее функция уже отключила локальные прерывания и получила спин-блокировку zone->iock, защищающую
структуры buddy-системы. Функция free pages buiko начинает работу с объявления и инициализации нескольких локальных переменных:
struct page base = zоne->zоne_mem_map; unsigned long buddy_idx, page_idx = page — base; struct page buddy, coalesced; int order_size = 1 « order;
Локальная переменная page idx содержит индекс первого страничного кадра в блоке относительно первого страничного кадра зоны.
Локальная переменная order size служит для увеличения счетчика свободных страничных кадров зоны:
zone->free_pages += order_size;
Затем функция выполняет цикл из максимум Ю-order операций для каждой возможности слияния блока с его buddy-блоком. Функция начинает с блоков наименьшего размера и двигается в направлении увеличения размера:
while (order lru); zone->free_area[order].nr_free—;
ClearPagePrivate(buddy); buddy->private = 0; page_idx &= buddy_idx; order++;}
В теле цикла функция ищет индекс buddy idx блока, являющегося buddy- блоком для блока, у которого индекс дескриптора страницы равен page idx. Оказывается, этот индекс легко вычислить следующим образом:
buddy_idx = page_idx А (1 « order);
Операция ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR), применяющая маску (i «order), переключает значение order-го бита в индексе page idx. Следовательно, если бит был равен 0, то индекс buddy idx равен page idx + order size. И наоборот, если бит был равен 1, индекс buddy idx равен page idx - order size.
Узнав индекс buddy-блока, легко получить дескриптор страницы для этого блока:
buddy = base + buddy_idx;
После этого функция вызывает функцию page is buddyO для проверки, действительно ли дескриптор buddy описывает первую страницу блока из order size свободных страничных кадров:
int page_is_buddy(struct page page, int order){
if (PagePrivate(buddy) && page->private == order &&
!PageReserved(buddy) && page_count(page) =0) return 1; return 0;}
Нетрудно видеть, что первая страница buddy-блока должна быть свободной (поле count равно -1), она должна принадлежать динамической памяти (бит PG reserved сброшен), ее поле private должно содержать осмысленную информацию (бит PG private установлен), И, наконец, В поле private должен храниться порядок освобождаемого блока.
Если все эти условия удовлетворены, buddy-блок свободен, и функция удаляет его из списка свободных блоков порядка order и выполняет одну или несколько итераций в поисках вдвое больших buddy-блоков.
Если хотя бы одно из условий функции page is buddy о нарушено, описываемая функция прерывает цикл, поскольку полученный свободный блок не может быть далее слит с другими свободными блоками. Функция заносит его в соответствующий список и обновляет поле private первого страничного кадра, записывая туда порядок размера блока:
coalesced = base + page_idx; coalesced->private = order;
SetPagePrivate(coalesced);
list_add(&coalesced->lru, &zone->free_area[order].free_list); zone->free_area[order].nr_free++;
Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | Следующая страница