replace the VHD/diskpart disk image pipeline with a directory-based vvfat root, we'll see when it breaks, fix /O2, add an all_tests, generalize the fat32 driver into a fat 16+32 driver, change policy on volume drivers, collapse KCPU's fields into a single atomic KE_CPU_STATE state machine, move scheduler ticking to per-CPU LAPIC timers, gate verbose SMP topology logging behind selftest diagnostics and add SMP pool-checkpoint validation around AP admission, add checked intrusive list helpers behind a new KE_DEBUG_LIST_CHECKS flag, add ObInitializeObjectHeader/ObTryReferenceObject, add waitable display clock objects and a SYS_OPEN_DISPLAY_CLOCK syscall for vsync-style waits, refactor kernel input into a per-queue KE_INPUT_CONTEXT with its own key/mouse ring buffers and DPC-driven key repeat, add KeInputQueuePeekEvent/ReadEvent/WaitKey and a SYS_QUERY_GLOBAL_INPUT_STATE syscall, split the kernel pool allocator out of mm_virt, new video files!
This commit is contained in:
1 parent
485a6bbfe7
commit
8b254f84f4
74 files changed
+4488
-2503
No files matched your search
+88
-23
@@ -1,8 +1,10 @@
|
||||
// Object manager. This file owns reference-counted kernel objects and handle-table lifetime rules.
|
||||
// Object manager. This file owns reference-counted kernel objects and their terminal lifetime transitions.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
#include <kernel/ob_object.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
#include <kernel/mm_virt.h>
|
||||
|
||||
// Returns a diagnostic pool tag for the object type.
|
||||
@@ -28,39 +30,102 @@ static uint32_t KiObjectPoolTag(OBJECT_TYPE type) {
|
||||
case ObjectTypeImageSection: return MM_POOL_TAG('i', 'm', 's', 'e');
|
||||
case ObjectTypeTimer: return MM_POOL_TAG('t', 'm', 'r', ' ');
|
||||
case ObjectTypeModule: return MM_POOL_TAG('m', 'o', 'd', 'u');
|
||||
case ObjectTypeDisplayClock: return MM_POOL_TAG('d', 'c', 'l', 'k');
|
||||
default: return MM_POOL_TAG('o', 'b', 'j', ' ');
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes a caller-owned object header in the live, inserted state.
|
||||
__declspec(dllexport) void ObInitializeObjectHeader(OBJECT* object, OBJECT_TYPE type) {
|
||||
if (!object)
|
||||
return;
|
||||
|
||||
object->Type = type;
|
||||
object->RefCount = 1;
|
||||
object->LifetimeState = ObjectAlive;
|
||||
object->Flags = OBJECT_FLAG_INSERTED;
|
||||
object->Destroy = (void*)0;
|
||||
}
|
||||
|
||||
// Creates a zeroed, tagged object with one initial reference.
|
||||
__declspec(dllexport) OBJECT* ObAllocateObject(OBJECT_TYPE type, size_t size) {
|
||||
if (size < sizeof(OBJECT)) size = sizeof(OBJECT);
|
||||
|
||||
OBJECT* obj = (OBJECT *)MmAllocatePoolTag(size, KiObjectPoolTag(type));
|
||||
if (!obj) return (OBJECT *)0;
|
||||
OBJECT* object = (OBJECT*)MmAllocatePoolTag(size, KiObjectPoolTag(type));
|
||||
if (!object) return (OBJECT*)0;
|
||||
|
||||
memset(obj, 0, size);
|
||||
obj->Type = type;
|
||||
obj->RefCount = 1;
|
||||
obj->Destroy = (void *)0; // caller fills this in
|
||||
return obj;
|
||||
memset(object, 0, size);
|
||||
ObInitializeObjectHeader(object, type);
|
||||
return object;
|
||||
}
|
||||
|
||||
// Implements the reference Object operation.
|
||||
__declspec(dllexport) void ObReferenceObject(OBJECT* object) {
|
||||
if (!object) return;
|
||||
_InterlockedIncrement(&object->RefCount);
|
||||
}
|
||||
// Acquires a reference without allowing zero-to-one resurrection.
|
||||
__declspec(dllexport) bool ObTryReferenceObject(OBJECT* object) {
|
||||
if (!object)
|
||||
return false;
|
||||
|
||||
// Implements the dereference Object operation.
|
||||
__declspec(dllexport) void ObDereferenceObject(OBJECT* object) {
|
||||
if (!object) return;
|
||||
long prev = _InterlockedDecrement(&object->RefCount);
|
||||
if (prev == 0) {
|
||||
// Reference count hit zero - run the destructor then free.
|
||||
if (object->Destroy) {
|
||||
object->Destroy(object);
|
||||
}
|
||||
MmFreePool(object);
|
||||
for (;;) {
|
||||
if (_InterlockedCompareExchange(&object->LifetimeState, 0, 0) != ObjectAlive)
|
||||
return false;
|
||||
if ((_InterlockedCompareExchange(&object->Flags, 0, 0) & OBJECT_FLAG_INSERTED) == 0)
|
||||
return false;
|
||||
|
||||
long refs = _InterlockedCompareExchange(&object->RefCount, 0, 0);
|
||||
if (refs <= 0 || refs == 0x7fffffffL)
|
||||
return false;
|
||||
|
||||
if (_InterlockedCompareExchange(&object->RefCount, refs + 1, refs) == refs)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Acquires a required reference and catches stale pointers at the caller site.
|
||||
__declspec(dllexport) void ObReferenceObject(OBJECT* object) {
|
||||
if (!object)
|
||||
return;
|
||||
if (ObTryReferenceObject(object))
|
||||
return;
|
||||
|
||||
KePanic(KE_PANIC_CODE_GENERIC,
|
||||
"object: stale reference object=0x%016llX type=%u refs=%ld state=%ld flags=0x%08x\n",
|
||||
(uint64_t)(uintptr_t)object,
|
||||
(unsigned)object->Type,
|
||||
object->RefCount,
|
||||
object->LifetimeState,
|
||||
(unsigned)object->Flags);
|
||||
}
|
||||
|
||||
// Releases a reference and performs the one-way Alive-to-Dying-to-Dead transition.
|
||||
__declspec(dllexport) void ObDereferenceObject(OBJECT* object) {
|
||||
if (!object)
|
||||
return;
|
||||
|
||||
long refs = _InterlockedDecrement(&object->RefCount);
|
||||
if (refs > 0)
|
||||
return;
|
||||
if (refs < 0) {
|
||||
KePanic(KE_PANIC_CODE_GENERIC,
|
||||
"object: reference underflow object=0x%016llX type=%u refs=%ld state=%ld flags=0x%08x\n",
|
||||
(uint64_t)(uintptr_t)object,
|
||||
(unsigned)object->Type,
|
||||
refs,
|
||||
object->LifetimeState,
|
||||
(unsigned)object->Flags);
|
||||
}
|
||||
|
||||
if (_InterlockedCompareExchange(&object->LifetimeState, ObjectDying, ObjectAlive) != ObjectAlive) {
|
||||
KePanic(KE_PANIC_CODE_GENERIC,
|
||||
"object: duplicate terminal transition object=0x%016llX type=%u state=%ld flags=0x%08x\n",
|
||||
(uint64_t)(uintptr_t)object,
|
||||
(unsigned)object->Type,
|
||||
object->LifetimeState,
|
||||
(unsigned)object->Flags);
|
||||
}
|
||||
|
||||
_InterlockedExchange(&object->Flags, OBJECT_FLAG_UNLINKED);
|
||||
if (object->Destroy)
|
||||
object->Destroy(object);
|
||||
|
||||
_InterlockedExchange(&object->LifetimeState, ObjectDead);
|
||||
MmFreePool(object);
|
||||
}
|
||||
Reference in new issue
Block a user