Добрый день. Пишу некий хук для нетфильтра(ядро 2.6.10 на однопроцессорной системе), который занимается декодированием пришедших по сети данных. Тип хука NF_IP_LOCAL_IN. Насколько я понимаю хук выполняется из softirq (NET_RX_SOFTIRQ net_rx_action), соответственно в момент выполнения отключено вытеснение (как видим в функции ksoftirqd). Так как декодирование достаточно долгое, и эксперименты показали что иногда функция декодирования приводит к тому что мы начинаем терять пакеты в бэклог, было решено вынести декодер в отдельный поток(условно поток ядра B). Теперь происходит следующее, сам хук просто берет данные из sk_buff и кладет их в некий буфер, которые в дальнейшем обработает поток B. Следовательно необходимо синхронизировать доступ к буферу (использую спинлоки). Насколько я поняла на однопроцессорной системе макрос spin_lock просто отключает вытеснение (preempt_disable), соответственно мы не можем делать вызовы которые могут привести к засыпанию треда внутри лока.
А теперь вопрос. Если поток B захватил spinlock, может ли его каким либо образом вытеснить ksoftirqd и обработать softirq? Единственное место получается где это может произойти, (с учетом того что и в потоке B и в хуке нет переключения контекста) это возврат из обработки аппаратного прерывания. Но если посмотреть на код (ret_from_intr для i386, для всех остальных архитектур наверно также?) то мы видим следующее:
ENTRY(resume_kernel)
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
jnz restore_all
то есть проверка какая-то все-таки есть, следовательно вытеснить наш поток B обработчик softirq все-таки не может?
Правильно ли я понимаю принцип работы?