могу предположить, что если кто-то ждёт нашего запертого спинлока, то ядро переводит страницу со спинлоком в r/o и по пейджфолту выясняет, когда мы его отпираем
Это слишком сурово. Фьютекс усыпляет поток, пока значение блокировки равно проверяемому значению. У мьютекса три состояния: 0 — свободен, 1 — захвачен одним потоком, 2 — захвачен и есть ожидающие потоки.
<code class="cpp">mutex_lock(mutex *lock)
{
//увеличиваем блокировку на 1 и проверяем предыдущее значение
//если был 0, то теперь там 1 и поток успешно захватил мьютекс
if(xchg_add(&lock,1) == 0)
return;
//ядро приостановит поток пока lock равен 2
while(xchg(&lock, 2) != 0)
syscall_futex(&lock, 2);
}
В идеальном случае lock равен 0 и захват обойдётся в одну операцию xchg_add (xadd для x86)
mutex_unlock(mutex *lock)
{
if(xchg(&lock, 0) != 1)
{
//есть ожидающие потоки
//разбудим один
syscall_futex_wake(&lock,1);
}
}
Аналогично, если нет ожидающих потоков lock равен 1 и освобождение происходит за одну операцию xchg,
в противном случае вызывается FUTEX_WAKE </code>
У вас в тесте размер выделяемого блока линейно растёт с приращением в 1 килобайт. Интересно посмотреть результаты с произвольными размерами блоков. И самое главное — тест однопоточный. Не известно какие результаты будут при большем числе потоков.
Роберт Харрис в «Энигме» подробно описал процесс взлома четырёхроторной машины, применявшейся на подводных лодках. Немецкие лодки передавали шифрованные сводки погоды. Эти сводки принимались метеостанциями на побережье, но там пользовались обычными трёхроторными Энигмами. Поэтому радисты на лодках отключали четвёртый ротор при передаче метеосводок. Англичане научились ломать зашифрованные метеосводки используя захваченные на U-459 тетрадь позывных и метеорологический шифр. Так они получали настройки трёх роторов, после чего подбирали настройку четвёртого и взламывали основной радиообмен.
Добавлю про GPU. К сожалению, единственный реальный путь к использованию GPU ATI/AMD лежит через портирование LLVM. Первая попытка закончилась неудачно, но я не теряю надежды.
<code class="cpp">mutex_lock(mutex *lock) { //увеличиваем блокировку на 1 и проверяем предыдущее значение //если был 0, то теперь там 1 и поток успешно захватил мьютекс if(xchg_add(&lock,1) == 0) return; //ядро приостановит поток пока lock равен 2 while(xchg(&lock, 2) != 0) syscall_futex(&lock, 2); } В идеальном случае lock равен 0 и захват обойдётся в одну операцию xchg_add (xadd для x86) mutex_unlock(mutex *lock) { if(xchg(&lock, 0) != 1) { //есть ожидающие потоки //разбудим один syscall_futex_wake(&lock,1); } } Аналогично, если нет ожидающих потоков lock равен 1 и освобождение происходит за одну операцию xchg, в противном случае вызывается FUTEX_WAKE </code>