Отложенный вызов bcast для условных переменных - это действительно?

Я реализую переменные условия pthread (основанные на фьютексах Linux), и у меня есть идея, чтобы избежать "эффекта давки" на pthread_cond_broadcast с общими переменными условия процесса. Для cond-переменных, не относящихся к процессу, операции запроса futex традиционно (т. Е. С помощью NPTL) используются для того, чтобы запросить официантов из futex cond var в futex мьютекса, не вызывая их, но это в общем случае невозможно для cond vars, совместно используемых процессом, так как pthread_cond_broadcast может не иметь действительного указателя на связанный мьютекс. В худшем случае мьютекс может даже не отображаться в своем пространстве памяти.

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

Естественно, есть много уродливых условий гонки, чтобы рассмотреть, придерживаюсь ли я этого подхода, но если они могут быть преодолены, есть ли другие причины, по которым такая реализация будет недействительной или нежелательной? Одна потенциальная проблема, о которой я могу подумать, что, возможно, не удастся преодолеть, это гонка, в которой официант (отдельный процесс), ответственный за требование, убивается до того, как он может действовать, но возможно даже преодолеть это, поставив condvar. futex в списке надежных мьютексов, так что ядро ​​выполняет пробуждение по нему, когда процесс умирает.

2 ответа

Решение

Официанты могут принадлежать нескольким адресным пространствам, каждое из которых сопоставило мьютекс, связанный с фьютексом, по другому адресу в памяти. Я не уверен, если FUTEX_REQUEUE безопасно использовать, когда точка запроса не может быть сопоставлена ​​по одному и тому же адресу во всех официантах; если это так, то это не проблема.

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

Обратите внимание, что с надежными фьютексами, вы должны установить значение фьютекса & 0x3FFFFFFF быть TID нити, которую нужно разбудить; Вы также должны установить бит FUTEX_WAITERS если хочешь проснуться. Это означает, что вы должны выбрать, какой поток пробудить из потока вещания, иначе вы не сможете иметь дело со смертью потока сразу после FUTEX_WAKE, Вам также необходимо разобраться с возможностью смерти потока непосредственно перед тем, как поток waker записывает свой TID в переменную состояния - возможно, было бы неплохо иметь поле 'pending master', которое также зарегистрировано в надежной системе мьютексов.

Я не вижу причин, почему это не может сработать, если вы внимательно следите за выходом из потока. Тем не менее, может быть лучше просто определить в ядре расширение для FUTEX_WAIT в качестве аргумента он использует точку реквизита и значение сравнения и позволяет ядру обрабатывать это простым и беспроблемным образом.

Я просто не понимаю, почему вы предполагаете, что соответствующий мьютекс может быть неизвестен. Это четко указано

Эффект использования более одного мьютекса для одновременных операций pthread_cond_timedwait() или pthread_cond_wait() в одной и той же условной переменной не определен; то есть переменная условия становится связанной с уникальным мьютексом, когда поток ожидает условную переменную, и это (динамическое) связывание заканчивается, когда возвращается ожидание.

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

Разрешение пользователям одновременно связывать разные мьютексы с условием - это не то, что я бы поддержал.

Другие вопросы по тегам