exectos/xtoskrnl/ke/sysres.c
Rafal Kupiec 156cb7bcac
Some checks failed
Builds / ExectOS (amd64) (push) Failing after 28s
Builds / ExectOS (i686) (push) Failing after 28s
Refactor system resources to be able to distinguish if requested resource does not exist or if it is locked and cannot be reused
2024-06-22 18:54:34 +02:00

234 lines
6.9 KiB
C

/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/ke/sysres.c
* DESCRIPTION: System resources management; This code is based on the MinocaOS implementation
* Copyright(C) 2012 Minoca Corp. (https://github.com/minoca/os/blob/master/kernel/ke/sysres.c)
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtos.h>
/**
* Looks for an unacquired system resource of the specified type and acquires it.
*
* @param ResourceType
* Supplies system resource type.
*
* @param ResourceHeader
* Specifies a memory area where a pointer to the system resource header will be stored.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KeAcquireSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType,
OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader)
{
/* Get system resource and acquire an ownership */
return KepGetSystemResource(ResourceType, TRUE, ResourceHeader);
}
/**
* Looks for an unacquired system resource of the specified type and returns it without acquiring an ownership.
*
* @param ResourceType
* Supplies system resource type.
*
* @param ResourceHeader
* Specifies a memory area where a pointer to the system resource header will be stored.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KeGetSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType,
OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader)
{
/* Get system resource without acquiring an ownership */
return KepGetSystemResource(ResourceType, FALSE, ResourceHeader);
}
/**
* Releases system resource.
*
* @param ResourceHeader
* Specifies a pointer to the system resource header.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KeReleaseSystemResource(IN PSYSTEM_RESOURCE_HEADER ResourceHeader)
{
/* Disable interrupts and acquire a spinlock */
ArClearInterruptFlag();
KeAcquireSpinLock(&KepSystemResourcesLock);
/* Release resource lock */
ResourceHeader->ResourceLocked = FALSE;
/* Release spinlock and enable interrupts */
KeReleaseSpinLock(&KepSystemResourcesLock);
ArSetInterruptFlag();
}
/**
* Looks for an unacquired system resource of the specified type.
*
* @param ResourceType
* Supplies system resource type.
*
* @param Acquire
* Specifies whether system resource should be acquired or not.
*
* @param ResourceHeader
* Specifies a memory area where a pointer to the system resource header will be stored.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KepGetSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType,
IN BOOLEAN ResourceLock,
OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader)
{
PSYSTEM_RESOURCE_HEADER Resource;
PLIST_ENTRY ListEntry;
BOOLEAN Interrupts;
XTSTATUS Status;
/* Assume resource found successfully */
Status = STATUS_SUCCESS;
/* Check if interrupts are enabled */
Interrupts = ArInterruptsEnabled();
/* Disable interrupts and acquire a spinlock */
ArClearInterruptFlag();
KeAcquireSpinLock(&KepSystemResourcesLock);
/* Iterate through system resources list */
ListEntry = KepSystemResourcesListHead.Flink;
while(ListEntry != &KepSystemResourcesListHead)
{
/* Get resource header */
Resource = CONTAIN_RECORD(ListEntry, SYSTEM_RESOURCE_HEADER, ListEntry);
/* Check if resource type matches */
if(Resource->ResourceType == ResourceType)
{
/* Check if resource is locked */
if(Resource->ResourceLocked)
{
/* Resource locked, set status code and stop browsing a list */
Status = STATUS_RESOURCE_LOCKED;
break;
}
/* Check if resource lock should be acquired */
if(ResourceLock)
{
/* Acquire resource lock */
Resource->ResourceLocked = TRUE;
}
/* Stop browsing a list */
break;
}
/* Go to the next list entry */
ListEntry = ListEntry->Flink;
}
/* Check if resource was found */
if(ListEntry == &KepSystemResourcesListHead)
{
/* Resource not found, return NULL */
Resource = NULL;
Status = STATUS_NOT_FOUND;
}
/* Release spinlock and re-enable interrupts if necessary */
KeReleaseSpinLock(&KepSystemResourcesLock);
if(Interrupts)
{
/* Re-enable interrupts */
ArSetInterruptFlag();
}
/* Return resource header and status code */
*ResourceHeader = Resource;
return Status;
}
/**
* Initializes system resource management.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTAPI
VOID
KepInitializeSystemResources(VOID)
{
PSYSTEM_RESOURCE_HEADER ResourceHeader;
PLIST_ENTRY ListEntry, NextListEntry;
ULONG ResourceSize;
/* Initialize system resources spin lock and resource list */
KeInitializeSpinLock(&KepSystemResourcesLock);
RtlInitializeListHead(&KepSystemResourcesListHead);
/* Make sure there are some system resources available */
if(!RtlListEmpty(&KeInitializationBlock->SystemResourcesListHead))
{
/* Iterate through system resources list */
ListEntry = KeInitializationBlock->SystemResourcesListHead.Flink;
while(ListEntry != &KeInitializationBlock->SystemResourcesListHead)
{
/* Get resource header and next list entry */
ResourceHeader = CONTAIN_RECORD(ListEntry, SYSTEM_RESOURCE_HEADER, ListEntry);
NextListEntry = ListEntry->Flink;
/* Basic resource type validation */
switch(ResourceHeader->ResourceType)
{
case SystemResourceAcpi:
/* ACPI system resource */
ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI);
break;
case SystemResourceFrameBuffer:
/* FrameBuffer system resource */
ResourceSize = sizeof(SYSTEM_RESOURCE_FRAMEBUFFER);
break;
default:
/* Unknown system resource type, skip it */
ResourceSize = 0;
break;
}
/* Validate resource size */
if(ResourceSize != 0 && ResourceSize == ResourceHeader->ResourceSize)
{
/* Move valid resource to the internal kernel list of system resources */
RtlRemoveEntryList(&ResourceHeader->ListEntry);
RtlInsertTailList(&KepSystemResourcesListHead, &ResourceHeader->ListEntry);
}
/* Go to the next list entry */
ListEntry = NextListEntry;
}
}
}