В обработчике прерывания клавиатуры (пс2) есть вызов KeStallExecutionProcessor. Судя по мсдн эта функция может быть вызвана с произвольным уровнем IRQL. Но, как оказалось, в Вин7 KeStallExecutionProcessor вызывает KeSetSystemGroupAffinityThread которая в свою очередь работает только при IRQL <= APC_LEVEL. Имеется в наличии миндамп совершенно явно показывающой, что прерывание произошло в контексте потока бегущего с HIGH_LEVEL, и вызов KeSetSystemGroupAffinityThread бросает IRQL_NOT_LESS_OR_EQUAL. Теперь самое удивительное... Стандартный обработчик прерываний от клавиатуры i8042I8042prt!KeyboardInterruptService сам по себе вызывает KeStallExecutionProcessor. Исходник KeyboardInterruptService можно найти в DDK. Также я пореверсил i8042prt.sys в Вин7, чтоб достоверно убедиться, что это так. Совершенно непонятно почему KeyboardInterruptService может нормально работать в стандартном обработчилке прерывания.
А чем можно заменить KeStallExecutionProcessor , чтоб гаратированно выполнялось даже на высокоприоритетный IRQL?
Циклом типа такого: int i = 0; while (true) { __asm nop; ++ i; if ( i == 10000000 ) { break; } } Правда это будет работать только в случае, если тебе не важна точная величина задержки.
KeStallExecutionProcessor выполняется на любом IRQL. В частности, я пробовал вызывать на IPI_LEVEL, на Win7. Ради интереса посмотрел код hal!KeStallExecutionProcessor. KeSetSystemGroupAffinityThread там не нашёл (тоже Win7). Возможно, у вас какая-то другая проблема или специфичный hal ? Дайте больше информации.
katrus Зачем KeStallExecutionProcessor может запрашивать привязку? Возможно, для того, чтобы не допустить перепланирование потока на _других_ процессорах. Почему KeSetSystemGroupAffinityThread должна выполняться на IRQL ниже DPC? Вероятно, из-за того, что при вызове может потребоваться перепланирование потока на другом процессоре – а на уровне DPC+ это слегка невозможно. Может ли быть, что Майкрософт жульничает и позволяет вызывать KeSetSystemGroupAffinityThread на повышенных IRQL если целевой процессор\группа совпадают с текущим? Но это не делает чувства – на таких IRQL поток и так не планируется. Что ж, посмотрим на дизасм. [зырк-зырк] KeStallExecutionProcessor может придти к nt!KeSetSystemGroupAffinityThread только таким путём: hal!KeStallExecutionProcessor -> hal!HalpTscStallExecutionProcessor -> nt!KeSetSystemGroupAffinityThread Код (Text): lkd> vertarget Windows 7 Kernel Version 7600 MP (2 procs) Free x64 lkd> uf hal!HalpTscStallExecutionProcessor hal!HalpTscStallExecutionProcessor: [..] hal!HalpTscStallExecutionProcessor+0x3c: fffff800`0281f110 mov rax,cr8 ; <<<< fffff800`0281f114 cmp al,2 ; <<<< Ta-da! fffff800`0281f116 jae hal!HalpTscStallExecutionProcessor+0x6b (fffff800`0281f13f) Branch hal!HalpTscStallExecutionProcessor+0x44: fffff800`0281f118 xor ecx,ecx fffff800`0281f11a mov sil,1 fffff800`0281f11d call qword ptr [hal!_imp_KeGetCurrentProcessorNumberEx (fffff800`0282d5e8)] fffff800`0281f123 lea rcx,[rsp+20h] fffff800`0281f128 mov edx,eax fffff800`0281f12a call hal!KeProcessorGroupAffinity (fffff800`0282c118) fffff800`0281f12f lea rdx,[rsp+30h] fffff800`0281f134 lea rcx,[rsp+20h] fffff800`0281f139 call qword ptr [hal!_imp_KeSetSystemGroupAffinityThread (fffff800`0282d1c8)] ; ^ больше путей прихода к KeSetSystemGroupAffinityThread в этой функции нет ^ hal!HalpTscStallExecutionProcessor+0x6b: fffff800`0281f13f rdtsc [..] Таким образом, всё решено наилучшим образом и без читерства – простой проверкой текущего IQRL и условным переходом. Действительно, незачем привязываться к процессору\группе на таких IRQL.