Существуют ли какие-либо эквиваленты futex в Linux/Unix?

Я ищу что-то, что можно было бы использовать для опроса (например, select, kqueue, epoll то есть не занятый опрос) в C/С++. Другими словами, мне нужно заблокировать поток, а затем разбудить его в другом потоке с как можно меньше накладных расходов.

A mutex + condition variable работает, но накладных расходов много. A futex также работает, но только для Linux (или, может быть, нет?). Дополнительная синхронизация не требуется, если сам опрос работает правильно, например. нет гонки, когда я вызываю wait и wake в двух потоках.

Изменить: если такой "объект" не существует в FreeBSD, как создать его с помощью встроенных типов и системных вызовов С++ 11?

Edit2: Поскольку этот вопрос перенесен в SO, я хотел бы сделать его более общим (не только для FreeBSD)

Ответ 1

семафоры не являются мьютексами и будут работать со слегка меньшими накладными расходами (например, при повторном блокировании mutex + condvar)

Обратите внимание: поскольку любое решение, в котором поток спит до тех пор, пока woken не будет задействован в syscall ядра, все равно не дешево. Предполагая, что x86_64 glibc и FreeBSD libc являются разумными реализациями, неизбежная стоимость выглядит следующим образом:

  • пользовательская синхронизация счета (с CAS или аналогичным)
  • управление ядрами очереди ожидания и спящий/ждущий поток

Я предполагаю, что накладные расходы mutex + condvar, о которых вы беспокоитесь, - это последовательность разблокировки cond_wait- > re-lock- > , которая здесь действительно отсутствует.

Ответ 2

Вам нужны семафоры, а не мьютексы для сигнализации между потоками.

http://man7.org/linux/man-pages/man3/sem_wait.3.html

Семафоры могут использоваться как счетчик, например, если у вас есть очередь, вы увеличиваете (отправляете) на семафор каждый раз, когда вы вставляете сообщение, а ваш приемник уменьшает (ждать) на семафоре для каждого полученного им сообщения. Если счетчик достигнет нуля, приемник будет блокироваться до тех пор, пока что-то не будет отправлено.

Таким образом, типичный шаблон заключается в объединении мьютекса и семафора, например:

sender:
    mutex.lock
    insert message in shared queue
    mutex.unlock
    semaphore.post

receiver:
    semaphore.wait
    mutex.lock
    dequeue message from shared structure
    mutex.unlock