Являются ли спин-блокировки Linux/SMP излишне медленными?
Прочитав Understanding the Linux kernel (Bovet & Cesati),
глава о синхронизации ядра утверждает, что код получения спин-блокировки сводится к следующему:
1: lock:
btsl $0, slp
jnc 3
2: testb $1, slp
jne 2
jmp 1
3:
Теперь я изначально думал, что иметь вложенные циклы было бы расточительно, и вы могли бы реализовать что-то вроде:
1: lock:
btsl $0, slp
jc 1
что было бы намного проще. Однако я понимаю, почему они сделали это с lock
влияет на другие процессоры и время для btsl
больше, чем для простого testb
,
Единственное, что я не смог обдумать, - это последующее освобождение спин-блокировки. Книга утверждает, что она дает следующее:
lock:
btrl $0, slp
Мой вопрос в основном почему? Мне кажется, что lock/mov-immediate
комбо быстрее.
Вам не нужно возвращать старое состояние к флагу переноса, поскольку, следуя правилу, согласно которому ядро не содержит ошибок (предполагается, что во многих других местах внутри этого ядра) старое состояние будет равно 1 (вы не будете пытаясь выпустить его, если вы его еще не приобрели).
И mov
гораздо быстрее, чем btrl
по крайней мере на 386.
Так чего мне не хватает?
Изменились ли сроки для этих инструкций на более поздних чипах?
Было ли ядро обновлено с тех пор, как книга была напечатана?
Книга просто неверна (или показывает упрощенные инструкции)?
Я пропустил какой-то другой аспект, связанный с синхронизацией между процессорами, который не удовлетворяет более быстрая инструкция?
1 ответ
Что ж, Understanding the Linux Kernel
Старый. С тех пор как было написано, ядро Linux было обновлено для использования так называемых спин-блокировок билетов. Блокировка - это 16-битная величина, разделенная на два байта: Next
(как следующий билет в раздаточном устройстве) и другие Owner
(например, номер "Сейчас на службе" за прилавком). Спин-блокировка инициализируется с обеими частями, установленными на ноль. Locking отмечает значение спин-блокировки и увеличивает Next далее, атомарно. Если значение Next до приращения равно Owner, блокировка получена. В противном случае он вращается до тех пор, пока значение Owner не увеличится до нужного значения и т. Д.
Соответствующий код находится в asm / spinlock.h (для x86). Операция разблокировки действительно намного быстрее и проще, чем говорится в книге:
static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
{
asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
: "+m" (lock->slock)
:
: "memory", "cc");
}
поскольку inc
примерно в 8 или 9 раз быстрее, чем btr
,
Надеюсь это поможет; если нет, я был бы счастлив копать глубже.