Переносимая потокобезопасность в C?

Цель

Я пишу небольшую библиотеку, для которой переносимость является самой большой проблемой. Он был разработан для использования только в среде, в основном совместимой с C90 (ISO/IEC 9899:1990)... не более того. Набор функций, предоставляемых библиотекой, работает (чтение/запись) с внутренней структурой данных. Я рассматривал некоторые другие варианты дизайна, но ничего другого не представляется возможным для библиотеки пытается достичь.

Вопрос

Существуют ли какие-либо переносимые алгоритмы, методы или заклинания, которые можно использовать для обеспечения потокобезопасности? Я не беспокоюсь о том, чтобы сделать функции реентерабельными. Более того, меня не волнует скорость или (возможно) трата ресурсов, если алгоритм/техника/заклинание переносимы. В идеале я не хочу зависеть от каких-либо библиотек (таких как GNU Pth) или специфичных для системы операций (таких как atomic test-and-set).

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

Любая помощь приветствуется.


person Community    schedule 02.08.2009    source источник


Ответы (4)


Алгоритм пекарни Лэмпорта, вероятно, сработает; к сожалению, с ним все еще есть практические проблемы. В частности, многие процессоры реализуют операции с памятью вне порядка: даже если вы скомпилировали ваш код в совершенно правильную последовательность инструкций, ЦП при выполнении вашего кода может принять решение изменить порядок инструкций на лету для достижения лучшей производительности. Единственный способ обойти это — использовать барьеры памяти, которые сильно нагружают систему и процессор. -специфический.

Здесь у вас действительно есть только два варианта: либо (1) сохранить вашу библиотеку небезопасной для потоков и сообщить об этом вашим пользователям в документации, либо (2) использовать мьютекс для конкретной платформы. Вариант 2 можно упростить, используя другую библиотеку, которая реализует мьютексы для большого количества платформ и предоставляет вам унифицированный абстрактный интерфейс.

person Community    schedule 02.08.2009
comment
Алгоритму Лампорта также требуются когерентные кэши памяти? Я не видел доказательства, но мне кажется, что текущий поток полагается на то, что каждый Entering[j] считается истинным в период между потоком j, который пишет ему true, и потоком j, который пишет ему false. Таким образом, даже если порядок записи может быть обработан, этот код может не работать, например, на многоядерных машинах ARM. Опять же, необходимы барьеры памяти или атомарный CAS. - person Steve Jessop; 03.08.2009

Без поддержки ОС/железа, по крайней мере атомарного CAS, вы не сможете сделать ничего практичного. Однако существуют существующие переносимые библиотеки, объединяющие различные платформы в общий интерфейс.

http://www.gnu.org/software/pth/related.html

person Community    schedule 02.08.2009

В наши дни почти все системы (даже Windows) могут запускать libpthread.

person Community    schedule 02.08.2009
comment
Где я могу получить больше информации о libpthread? Простой поиск в Google выдал кучу мусора. - person ; 03.08.2009
comment
Вы можете использовать pthreads в Windows с pthreads-win32; см. sourceware.org/pthreads-win32. - person Adam Rosenfield; 03.08.2009
comment
pthreads изначально доступен практически для любого *nix, а реализация для Windows находится по адресу sourceware.org/pthreads- win32 Официальная документация находится здесь: opengroup.org/onlinepubs/007908799 /xsh/pthread.h.html Если вы пойдете по этому пути, довольно легко предоставить pthreads пользователям вашей библиотеки, что не всегда желательно. - person nos; 03.08.2009
comment
Сейчас я рассматриваю возможность абстрагирования процедур блокировки и разблокировки и использования некоторых макросов препроцессора для поддержки различных библиотек потоков. - person ; 03.08.2009
comment
Это, вероятно, лучший способ сделать это. Я просто предоставляю mutex_init(void**); mutex_lock (пусто*); и mutex_unlock(void *); который использует мой проект. Добавьте реализацию тех, что в mutex_posix.c и mutex_win32.c, которые, естественно, компилируются условно, предоставляя другую реализацию для чего-то столь же простого, как мьютексы, легко, если есть доступная собственная реализация (что почти всегда есть, если платформа поддерживает многопоточность) - person nos; 03.08.2009
comment
Если уж на то пошло, то до тех пор, пока вам не нужно какое-либо причудливое поведение планировщика, такое как предотвращение инверсии приоритетов (что, как я предполагаю, не нужно спрашивающему, поскольку он рассматривает форму спин-блокировки), вам даже не нужен мьютекс для реализовать критическую секцию. Унарный семафор подойдет. Где-то может быть реализация C, в которой есть потоки, но нет примитива, который может легко реализовать исключение, но если это так, я не хочу встречаться с ним ;-) - person Steve Jessop; 03.08.2009

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

person Community    schedule 02.08.2009