Отложенное пробуждение bcast для условных переменных - это действительно? - PullRequest
0 голосов
/ 24 сентября 2011

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

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

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

Ответы [ 2 ]

2 голосов
/ 24 сентября 2011

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

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

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

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

0 голосов
/ 24 сентября 2011

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

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

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

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

...