Files
nt-lite/code/kernel/ke_irql.c
T

83 lines
2.5 KiB
C

// ke_irql.c - software IRQL skeleton
#include <ke_irql.h>
#include <ke_debug.h>
#include <ke_apc.h>
// Single-CPU bring-up state. When SMP arrives this becomes per-CPU state.
static volatile KIRQL gCurrentIrql = PASSIVE_LEVEL;
__declspec(dllexport) const char* KeIrqlName(KIRQL irql) {
switch (irql) {
case PASSIVE_LEVEL: return "PASSIVE_LEVEL";
case APC_LEVEL: return "APC_LEVEL";
case DISPATCH_LEVEL: return "DISPATCH_LEVEL";
case HIGH_LEVEL: return "HIGH_LEVEL";
default:
if (irql >= DIRQL_BASE && irql < HIGH_LEVEL)
return "DIRQL";
return "INVALID_IRQL";
}
}
__declspec(dllexport) KIRQL KeGetCurrentIrql(void) {
return gCurrentIrql;
}
__declspec(dllexport) KIRQL KeRaiseIrql(KIRQL newIrql) {
KIRQL oldIrql = gCurrentIrql;
if (newIrql > HIGH_LEVEL) {
KePanic("KeRaiseIrql: invalid target IRQL %u\n", (unsigned)newIrql);
}
if (newIrql < oldIrql) {
KePanic("KeRaiseIrql: attempted raise from %s(%u) down to %s(%u)\n",
KeIrqlName(oldIrql), (unsigned)oldIrql,
KeIrqlName(newIrql), (unsigned)newIrql);
}
gCurrentIrql = newIrql;
return oldIrql;
}
__declspec(dllexport) void KeLowerIrql(KIRQL oldIrql) {
KIRQL currentIrql = gCurrentIrql;
if (oldIrql > HIGH_LEVEL) {
KePanic("KeLowerIrql: invalid target IRQL %u\n", (unsigned)oldIrql);
}
if (oldIrql > currentIrql) {
KePanic("KeLowerIrql: attempted lower from %s(%u) up to %s(%u)\n",
KeIrqlName(currentIrql), (unsigned)currentIrql,
KeIrqlName(oldIrql), (unsigned)oldIrql);
}
gCurrentIrql = oldIrql;
if (oldIrql == PASSIVE_LEVEL && currentIrql != PASSIVE_LEVEL)
KiDeliverKernelApcs();
}
__declspec(dllexport) void KeAssertIrql(KIRQL expected) {
KIRQL currentIrql = KeGetCurrentIrql();
if (currentIrql != expected) {
KePanic("IRQL assertion failed: expected %s(%u), current %s(%u)\n",
KeIrqlName(expected), (unsigned)expected,
KeIrqlName(currentIrql), (unsigned)currentIrql);
}
}
__declspec(dllexport) void KeAssertIrqlAtOrBelow(KIRQL maxIrql) {
KIRQL currentIrql = KeGetCurrentIrql();
if (currentIrql > maxIrql) {
KePanic("IRQL assertion failed: expected <= %s(%u), current %s(%u)\n",
KeIrqlName(maxIrql), (unsigned)maxIrql,
KeIrqlName(currentIrql), (unsigned)currentIrql);
}
}
__declspec(dllexport) int KeCanWait(void) {
return KeGetCurrentIrql() == PASSIVE_LEVEL;
}