Подключить событие для прерывания
#include <sys/neutrino.h>int InterruptAttachEvent( int intr,const struct sigevent *event,unsigned flags );int InterruptAttachEvent_r( int intr,const struct sigevent *event,unsigned flags );
libc
Системные вызовы InterruptAttachEvent() и InterruptAttachEvent_r() подключают получение события при возникновении аппаратного прерывания intr. Прерывание при этом автоматически включается (размаскируется).
Функции идентичны за исключением способа возврата ошибок.
Перед вызовом любой из этих функций поток должен запросить привилегии ввода-вывода, вызвав:
ThreadCtl( _NTO_TCTL_IO, 0 );
Если поток этого не сделает, он может получить SIGSEGV
при вызове InterruptAttachEvent() или InterruptAttachEvent_r().
Для предотвращения бесконечной рекурсии прерываний, ядро автоматически маскирует прерывание intr с помощью InterruptMask() при доставке события. После того, как поток обработки прерывания обработает событие, он должен вызвать InterruptUnmask(), чтобы размаскировать прерывание.
При выборе типа события учитывайте следующее:
SIGEV_PULSE
для срабатывания отправки через канал.
SIGEV_INTR
в качестве типа события и InterruptWait() в качестве блокирующего вызова.
SIGEV_SIGNAL
, SIGEV_SIGNAL_CODE
или SIGEV_SIGNAL_THREAD
не рекомендуется. Это менее эффективно, чем другие механизмы доставки событий. В многоядерной системе поток, получающий событие, подключенное InterruptAttachEvent(), выполняется на любом ядре, ограничения накладываются только планировщиком и маской выполнения (см. ThreadCtl() и команду _NTO_TCTL_RUNMASK
).
Флаги
Аргумент flags представляет собой либо 0
, либо побитовое ИЛИ следующих значений:
Поместить новое событие в конец списка существующих событий вместо начала.
Аппаратное прерывание может быть разделяемым (один номер прерывания для нескольких устройств). Например, если два процесса вызывают InterruptAttachEvent() для одного и того же физического прерывания, оба события отправляются последовательно. Когда подключается новое событие, оно помещается перед любыми существующими событиями для этого прерывания и доставляется первым. Можно изменить это поведение, установив флаг _NTO_INTR_FLAGS_END
в аргументе flags. Это добавит событие в конец списка любых существующих событий.
Связать событие с процессом, а не потоком.
Добавление _NTO_INTR_FLAGS_PROCESS к флагам flags связывает получение события с процессом, а не потоком. Отключение события происходит при выходе из процесса, вместо потока.
![]() | Ядро пытается автоматически установить флаг _NTO_INTR_FLAGS_PROCESS , если событие предназначено процессу (для событий SIGEV_SIGNAL , SIGEV_SIGNAL_CODE и SIGEV_PULSE ). |
Отслеживать количество вызовов InterruptMask() и InterruptUnmask(), чтобы сделать отключение обработчика прерываний более безопасным.
Флаг _NTO_INTR_FLAGS_TRK_MSK
и аргумент id для InterruptMask() и InterruptUnmask() указывают ядру отслеживать, сколько раз было замаскировано конкретное прерывание. Затем, когда происходит отключение от прерывания, ядро выполняет необходимое количество размаскирований, чтобы гарантировать нормальную работу прерывания. Это важно для разделяемых прерываний.
![]() | Следует всегда устанавливать _NTO_INTR_FLAGS_TRK_MSK . |
Преимущества и недостатки
InterruptAttachEvent() имеет несколько преимуществ по сравнению с InterruptAttach():
Недостатки:
Можно смешивать вызовы InterruptAttach() и InterruptAttachEvent() для конкретного прерывания.
Данный вызов неблокирующий.
-1
, код ошибки записывается в errno.Используйте полученный идентификатор в качестве аргумента функции InterruptDetach(), чтобы отключить получение события при возникновении прерывания.
ЗОСРВ «Нейтрино»
InterruptAttach(), InterruptDetach(), InterruptLock(), InterruptMask(), InterruptUnlock(), InterruptUnmask(), InterruptWait(), struct sigevent
Предыдущий раздел: Описание API системной библиотеки