Именно такова форма и многопоточного эквивалента в API QNX —
rand_r
.
2. В этом варианте мы сохраняем прототип описания функции без изменений за счет использования различных экземпляров собственных данных потока. (Весь приведенный ниже код размещен в отдельной единице компиляции; все имена, за исключением
rand
, невидимы и недоступны из точки вызова, что подчеркнуто явным использованием квалификатора
этом варианте, в отличие от предыдущего, весь код вызывающего фрагмента при переходе к многопоточной реализации остается текстуально неизменным:
void* thrfunc(void*) {
// ...
while (true) {
... = rand(x);
}
}
Перевод всего программного проекта на использование потоковой среды состоит в замене объектной единицы (объектного файла, библиотеки), содержащей реализацию
rand
, и новой сборке приложения с этой объектной единицей.
При таком способе изменяются под потоковую безопасность и стандартные общеизвестные библиотечные функции API, написанные в своем первозданном виде 25 лет назад… (по крайней мере, так предлагает это делать стандарт POSIX, вводящий в обиход собственные данные потоков).
Диспетчеризация потоков
Каждому потоку, участвующему в процессе диспетчеризации, соответствует экземпляр структуры, определенной в файле
<sys/target_nto.h>
, в котором находятся все фундаментальные для ОС QNX определения:
, имеет отношение только к спорадической диспетчеризации (спорадическая диспетчеризация была введена значительно позже других, и ей будет уделено достаточно много внимания). Для всех остальных типов диспетчеризации потока это поле заполняется фиктивным полем
reserved
, и именно так в укороченном виде) определялась структура диспетчеризации в версии QNX 6.1.
Сейчас нас интересуют начальные поля этой структуры, не зависящие от типа диспетчеризации потока:
sched_priority
— статический приоритет, который присваивается потоку при его создании и который может быть программно изменен по ходу выполнения потока;
sched_curpriority
— текущий приоритет, с которым выполняется (и согласно которому диспетчеризируется) данный поток в текущий момент времени. Это значение приоритета образуется системой на основе заданного статического приоритета, но оно может динамически изменяться системой, например при отработке дисциплин наследования приоритетов или граничных приоритетов для потока. Программа не имеет средств воздействия на это значение [20] , но может его считывать.
20
Пользователь может изменять это поле, однако это лишено смысла и не влечет за собой никаких последствий, ведь значением текущего приоритета «управляет» ОС, например для осуществления наследования приоритетов. С другой стороны, иногда целесообразно считать значение именно этого поля, чтобы определить значение динамического приоритета потока, установленного, например, в результате того же наследования.
Еще раз подчеркнем достаточно очевидную вещь: дисциплина диспетчеризации определяется относительно потока и на уровне потока (но не процесса). Проследить за дисциплиной диспетчеризации (и убедиться в справедливости утверждения предыдущей фразы) можно командой
pidin
. Вот несколько строк ее вывода, относящиеся к составным частям самой системы: