Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform | страница 54



Состояние «потребителя»Состояние «производителя»
«потребитель» блокирует мутекс«потребитель»READYINTERRUPT
«потребитель» проверяет флаг data_ready«потребитель»READYINTERRUPT
потребитель вызывает функцию pthread_sleepon_wait()«потребитель»READYINTERRUPT
функция pthread_sleepon_wait() разблокирует мутексмутекс свободенREADYINTERRUPT
функция pthread_sleepon_wait() блокируетсямутекс свободенCONDVARINTERRUPT
пауза до прерываниямутекс свободенCONDVARINTERRUPT
аппаратные средства генерируют данныемутекс свободенCONDVARREADY
«производитель» блокирует мутекс«производитель»CONDVARREADY
«производитель» устанавливает флаг data_ready«производитель»CONDVARREADY
«производитель» вызывает pthread_sleepon_signal()«производитель»CONDVARREADY
«потребитель» «пробуждается», функция pthread_sleepon_wait() пытается заблокировать мутекс«производитель»MUTEXREADY
«производитель» разблокирует мутексмутекс свободенMUTEXREADY
«потребитель» получает мутекс«потребитель»READYREADY
«потребитель» обрабатывает данные«потребитель»READYREADY
«производитель» ждет новых данных от аппаратуры«потребитель»READYINTERRUPT
пауза («потребитель» обрабатывает полученные данные)«потребитель»READYINTERRUPT
«потребитель» завершает обработку и разблокирует мутексмутекс свободенREADYINTERRUPT
«потребитель» возвращается в начало цикла и блокирует мутекс«потребитель»READYINTERRUPT

Последняя строка в таблице повторяет первую — мы совершили один полный цикл.

Каково назначение флага data_ready? Он служит для двух целей:

• Он является флагом состояния — посредником между «потребителем» и «производителем», указывающим на состояние системы. Если флаг установлен в состояние 1, это означает, что данные доступны для обработки; если этот флаг установлено в состояние 0, это означает, что данных нет, и поток-потребитель должен быть заблокирован.

• Он выполняет функцию «места, где происходит синхронизация со ждущей блокировкой». Более формально говоря, адрес переменной data_ready используется как уникальный идентификатор объекта, по которому осуществляется ждущая блокировка. Мы запросто могли бы применить «>(void*)12345» вместо «>&data_ready» — библиотеке ждущих блокировок все равно, что это за идентификатор, лишь бы он был уникален и корректно использовался. Использование же в качестве идентификатора адреса переменной есть надежный способ сгенерировать уникальный номер, поскольку не бывает же двух переменных с одинаковым адресом!

• К обсуждению различий между функциями