Чтение онлайн

на главную - закладки

Жанры

Разработка ядра Linux (Второе издание)
Шрифт:

Объявления всего, что необходимо для использования целочисленных атомарных операций, находятся в заголовочном файле

<asm/atomic.h>
. Для некоторых аппаратных платформ существуют дополнительные средства, которые уникальны только для этой платформы, но для всех аппаратных платформ существует минимальный набор операций, которые используются в ядре повсюду. При написании кода ядра необходимо гарантировать, что соответствующие операции доступны и правильно реализованы для всех аппаратных платформ.

Объявление переменных типа

atomic_t
производится обычным образом. При необходимости можно установить заданное значение этой переменной.

atomic_t u; /* определение переменной u */

atomic_t v = ATOMIC_INIT(0); /* определение переменной v

и инициализация ее в значение нуль */

Выполнять

операции так же просто.

atomic_set(&v, 4); /* v=4 (атомарно) */

atomic_add(2, &v); /* v = v + 2 = 6 (атомарно) */

atomic_inc(&v); /* v = v+1 = 7 (атомарно) */

Если необходимо конвертировать тип

atomic_t
в тип
int
, то нужно использовать функцию
atomic_read
.

printk("%d\n", atomic_read(&v)); /* будет напечатано "7" */

Наиболее частое использование атомарных целочисленных операций — это инкремент счетчиков. Защищать один счетчик с помощью сложной системы блокировок — это глупо, поэтому разработчики используют вызовы

atomic_inc
и
atomic_dec
, которые значительно быстрее. Еще одно использование атомарных целочисленных операций — это атомарное выполнение операции с проверкой результата. Наиболее распространенный пример — это атомарные декремент и проверка результата, с помощью функции

int atomic_dec_and_test(atomic_t *v);

Эта функция уменьшает на единицу значение заданной переменной атомарного типа. Если результат выполнения операции равен нулю, то возвращается значение

true
, иначе возвращается
false
. Полный список всех атомарных операций с целыми числами (т.е. тех, которые доступны для всех аппаратных платформ) приведен в табл. 9.1. Все операции, которые реализованы для определенной аппаратной платформы, приведены в файле
<asm/atomic.h>
.

Таблица 9.1. Полный список всех атомарных операций с целыми числами

Атомарная целочисленная операция Описание
ATOMIC_INIT(int i)
Объявление и инициализация в значение i переменной типа
atomic
_t
int atomic_ read(atomic_t *v)
Атомарное считывание значения целочисленной переменной
v
void atomic_set(atomic_t *v, int i)
Атомарно установить переменную
v
в значение
i
void atomic_add(int i, atomic_t *v)
Атомарно прибавить значение
i
к переменной v
void atomic_sub(int i, atomic_t *v)
Атомарно вычесть значение 1 из переменной
v
void atomic_inc(atomic_t *v)
Атомарно прибавить единицу к переменной
v
void atomic_dec(atomic_t *v)
Атомарно вычесть единицу из переменной
v
int atomic_sub_and_test(int i, atomic_t *v)
Атомарно вычесть значение
i
из переменной
v
и возвратить
true
, если результат равен нулю, и
false
в противном случае
int atomic_add_negative(int i, atomic_t *v)
Атомарно прибавить значение
i
к переменной
v
и возвратить
true
, если результат операции меньше нуля, иначе возвратить
false
int atomic_dec_and_test(atomic_t *v)
Атомарно вычесть единицу из переменной
v
и возвратить
true
, если результат операции равен нулю, иначе
возвратить
false
int atomic_inc_and_test(atomic_t *v)
Атомарно прибавить единицу к переменной
v
и возвратить
true
, если результат операции равен нулю, иначе возвратить
false

Обычно атомарные операции реализованы как функции с подстановкой тела и встраиваемыми инструкциями на языке ассемблера (разработчики ядра любят

inline
). В случае если какая-либо из функций обладает внутренней атомарностью, то обычно она выполняется в виде макроса. Например, для большинства нормальных аппаратных платформ считывание одного машинного слова данных — это атомарная операция. Операция считывания всегда возвращает машинное слово в непротиворечивом состоянии или перед операцией записи, или после нее, но во время операции записи чтение не может быть выполнено никогда. Следовательно, функция
atomic_read
обычно реализуется как макрос, который возвращает целочисленное значение переменной типа
atomic_t
.

Атомарность и порядок выполнения

От атомарных операций чтения перейдем к различиям между атомарностью и порядком выполнения. Как уже рассказывалось, операции чтения одного машинного слова всегда выполняются атомарно. Эти операции никогда не перекрываются операциями записи того же машинного слова. Иными словами, операция чтения данных всегда возвращает машинное слово в консистентном состоянии: иногда возвращается значение, которое было до записи, а иногда — то, которое стало после записи, но никогда не возвращается значение, которое было во время записи. Например, если целочисленное значение вначале было равно 42, а потом стало 365, то операция чтения всегда вернет значение 42 или 365, но никогда не смешанное значение. Это называется атомарностью.

Иногда бывает так, что вашему коду необходимо нечто большее, например операция чтения всегда выполняется перед ожидающей операцией записи. Это называется не атомарностью, а порядком выполнения (ordering). Атомарность гарантирует, что инструкции выполняются не прерываясь и что они либо выполняются полностью, либо не выполняются совсем. Порядок выполнения же гарантирует, что две или более инструкций, даже если они выполняются разными потоками или разными процессами, всегда выполняются в нужном порядке.

Атомарные операции, которые обсуждаются в этом разделе, гарантируют только атомарность. Порядок выполнения гарантируется с помощью операций барьеров (barrier), которые будут рассмотрены дальше в текущей главе.

В любом коде использование атомарных операций, где это возможно, более предпочтительно по сравнению со сложными механизмами блокировок. Для большинства аппаратных платформ одна или две атомарные операции приводят к меньшим накладным затратам и к более эффективному использованию процессорного кэша, чем в случае более сложных методов синхронизации. Как и в случае любого кода, который чувствителен к производительности, всегда разумным будет протестировать несколько вариантов.

Битовые атомарные операции

В дополнение к атомарным операциям с целыми числами, ядро также предоставляет семейство функций, которые позволяют работать на уровне отдельных битов. Не удивительно, что эти операции зависят от аппаратной платформы и определены в файле

<asm/bitops.h>
.

Тем не менее может вызвать удивление то, что функции, которые реализуют битовые операции, работают с обычными адресами памяти. Аргументами функций являются указатель и номер бита. Бит 0 — это наименее значащий бит числа, которое находится по указанному адресу. На 32-разрядных машинах бит 31 — это наиболее значащий бит, а бит 0 — наименее значащий бит машинного слова. Нет ограничений на значение номера бита, которое передается в функцию, хотя большинство пользователей работают с машинными словами и номерами битов от 0 до 31 (или до 63 для 64-битовых машин).

Так как функции работают с обычными указателями, то в этом случае нет аналога типу

atomic_t
, который используется для операций с целыми числами. Вместо этого можно использовать указатель на любые данные. Рассмотрим следующий пример.

unsigned long word = 0;

set_bit(0, &word); /* атомарно устанавливается бит 0 */

set_bit(1, &word); /* атомарно устанавливается бит 1 */

printk("%ul\n", word); /* будет напечатано "3" */

Поделиться:
Популярные книги

70 Рублей

Кожевников Павел
1. 70 Рублей
Фантастика:
фэнтези
боевая фантастика
попаданцы
постапокалипсис
6.00
рейтинг книги
70 Рублей

Жатва душ. Остров мертвых

Сугралинов Данияр
Фантастика:
боевая фантастика
рпг
5.20
рейтинг книги
Жатва душ. Остров мертвых

Сердце Дракона. Том 9

Клеванский Кирилл Сергеевич
9. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.69
рейтинг книги
Сердце Дракона. Том 9

Как я строил магическую империю 6

Зубов Константин
6. Как я строил магическую империю
Фантастика:
попаданцы
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 6

Леди для короля. Оборотная сторона короны

Воронцова Александра
3. Королевская охота
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Леди для короля. Оборотная сторона короны

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Газлайтер. Том 4

Володин Григорий
4. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 4

АллатРа

Новых Анастасия
Научно-образовательная:
психология
история
философия
обществознание
физика
6.25
рейтинг книги
АллатРа

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Дорога к счастью

Меллер Юлия Викторовна
Любовные романы:
любовно-фантастические романы
6.11
рейтинг книги
Дорога к счастью

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

Камень Книга седьмая

Минин Станислав
7. Камень
Фантастика:
фэнтези
боевая фантастика
6.22
рейтинг книги
Камень Книга седьмая

Николай I Освободитель. Книга 2

Савинков Андрей Николаевич
2. Николай I
Фантастика:
героическая фантастика
альтернативная история
5.00
рейтинг книги
Николай I Освободитель. Книга 2

Секретарша генерального

Зайцева Мария
Любовные романы:
современные любовные романы
эро литература
короткие любовные романы
8.46
рейтинг книги
Секретарша генерального