Jump to content

Recommended Posts

Posted (edited)

Hi guys,

thanks to this request, I wrote my version of GetLogicalProcessorInformation UDF for x86 e x64:

; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_GetLogicalProcessorInformation
; Description ...: Retrieves information about logical processors and related hardware.
; Syntax.........: _WinAPI_GetLogicalProcessorInformation()
; Return values .: On success it returns a bidimensional array: on rows there is the list of processor sets, these are the columns:
;                  |[0] - A logical processor affinity mask, which indicates the logical processors that the information applies to.
;                  |[1] - If setted, then the specified logical processors share a single processor core.
;                  |[2] - How many active processors that share functional units are in the relationship
;                         (it is setted only if the previous element is setted too)
;                  |[3] - If setted, it identifies the NUMA node (it can be 0).
;                  |[4] - If setted, the specified logical processors share a physical package.
;                  |[5] - A bidimensional array: on rows there is the cache list, these are the columns:
;                         |[0] - The cache level
;                         |[1] - The cache associativity
;                         |[2] - The cache line size, in bytes
;                         |[3] - The cache size, in bytes
;                         |[4] - The cache type
;                  On failure it returns -1 and sets @error to non zero:
;                  |-1 - internal error
;                  |-2 - missing DLL (Ws2_32.dll)
; Remarks .......: Search GetLogicalProcessorInformation in MSDN Library.
; Author ........: j0kky
; Modified ......: 1.0.0
; Links .........: https://msdn.microsoft.com/it-it/library/windows/desktop/ms683194(v=vs.85).aspx
; ====================================================================================================================================
Func _WinAPI_GetLogicalProcessorInformation()
    Local $hDll = DllOpen("kernel32.dll")
    If @error Then Return SetError(-2, 0, -1)
    Local Const $ERROR_INSUFFICIENT_BUFFER = 122
    Local $aRet = DllCall($hDll, "BOOL", "GetLogicalProcessorInformation", "ptr", Null, "dword*", 0)
    If @error Or Not (DllCall($hDll, "DWORD", "GetLastError")[0] = $ERROR_INSUFFICIENT_BUFFER) Then
        DllClose($hDll)
        Return SetError(-1, 0, -1)
    EndIf
    Local $nReturnLength = $aRet[2]
    Local $tBuffer = DllStructCreate("byte[" & $nReturnLength & "]")
    Local $pBuffer = DllStructGetPtr($tBuffer)
    $aRet = DllCall($hDll, "BOOL", "GetLogicalProcessorInformation", "ptr", $pBuffer, "dword*", $nReturnLength)
    If @error Or Not $aRet[0] Then
        DllClose($hDll)
        Return SetError(-1, 0, -1)
    EndIf
    Local Const $tagSYSTEM_LOGICAL_PROCESSOR_INFORMATION = "ULONG_PTR ProcessorMask; INT_PTR Relationship; BYTE UnionBuffer[16]"
    Local $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION = DllStructCreate($tagSYSTEM_LOGICAL_PROCESSOR_INFORMATION, $pBuffer)
    Local $nSize = DllStructGetSize($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION), $tCACHE_DESCRIPTOR, _
            $aResult[1][6], _ ;mask, core, logical, numa, package, cache
            $aCacheModel[0][5], _ ;level, associativity, line size, size, processor cache type
            $nOffset = 0, $nArraySize, $aCache, $vProcessor, $nProcessorMask
    $aResult[0][0] = $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION.ProcessorMask
    $aResult[0][5] = $aCacheModel
    Do
        $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION = DllStructCreate($tagSYSTEM_LOGICAL_PROCESSOR_INFORMATION, $pBuffer + $nOffset)
        $nProcessorMask = $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION.ProcessorMask
        $nArraySize = UBound($aResult)
        For $i = 0 To ($nArraySize - 1)
            If $aResult[$i][0] = $nProcessorMask Then
                $vProcessor = $i
                ExitLoop
            EndIf
        Next
        If $vProcessor = Null Then
            ReDim $aResult[$nArraySize + 1][6]
            $aResult[$nArraySize][0] = $nProcessorMask
            $aResult[$nArraySize][5] = $aCacheModel
            $vProcessor = $nArraySize
        EndIf
        Switch $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION.Relationship
            Case 0 ;RelationProcessorCore
                $aResult[$vProcessor][1] += 1
                If (DllStructCreate("byte Flags", DllStructGetPtr($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION, "UnionBuffer")).Flags) = 1 Then
                    For $i = 1 To (($nSize = 24) ? 32 : 64)
                        $aResult[$vProcessor][2] += (Mod($nProcessorMask, 2) ? 1 : 0)
                        $nProcessorMask = Floor($nProcessorMask / 2)
                    Next
                EndIf
            Case 1 ;RelationNumaNode
                $aResult[$vProcessor][3] = DllStructCreate("dword NodeNumber", DllStructGetPtr($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION, "UnionBuffer")).NodeNumber
            Case 2 ;RelationCache
                $tCACHE_DESCRIPTOR = DllStructCreate("byte Level; byte Associativity; word LineSize; dword Size; INT Type", _
                        DllStructGetPtr($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION, "UnionBuffer"))
                $aCache = $aResult[$vProcessor][5]
                $nArraySize = UBound($aCache)
                ReDim $aCache[$nArraySize + 1][5]
                $aCache[$nArraySize][0] = $tCACHE_DESCRIPTOR.Level
                $aCache[$nArraySize][1] = $tCACHE_DESCRIPTOR.Associativity
                $aCache[$nArraySize][2] = $tCACHE_DESCRIPTOR.LineSize
                $aCache[$nArraySize][3] = $tCACHE_DESCRIPTOR.Size
                $aCache[$nArraySize][4] = $tCACHE_DESCRIPTOR.Type
                $aResult[$vProcessor][5] = $aCache
            Case 3 ;RelationProcessorPackage
                $aResult[$vProcessor][4] += 1
        EndSwitch
        $nOffset += $nSize
        $vProcessor = Null
    Until $nOffset = $nReturnLength
    DllClose($hDll)
    Return $aResult
EndFunc   ;==>_WinAPI_GetLogicalProcessorInformation

Usage example:

#include <array.au3>
$array = _WinAPI_GetLogicalProcessorInformation()

_ArrayDisplay($array, "Processor set list:")
For $i = 0 To UBound($array) - 1
    _ArrayDisplay($array[$i][5], "Processor set " & $i + 1 & " cache:")
Next

:)

Edited by j0kky
Posted

 Nice version. Thank you. dllcall return type should be BOOL instead BOOLEAN.

 

Saludos

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...