WINAPI GetLogicalProcessorInformation

  • Hi, ich brauche mal Hilfe von den "C++ Könnern" unter euch....

    Die Funktion "WINAPI GetLogicalProcessorInformation" ist leider nicht in den AutoIt Includes zu finden, also wollte ich sie selber basteln; ....leider ohne Erfolg.
    Einfache Funktionen konnte ich schon adaptieren, aber diese weicht irgendwie ins Unbekannte ab.

    Ich hoffe mir kann jemand helfen.... und dann sollte die Funktion in die Includes rein (WinAPISys.au3). :thumbup:


    C
    BOOL WINAPI GetLogicalProcessorInformation(
      _Out_   PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
      _Inout_ PDWORD                                ReturnLength
    );

    https://msdn.microsoft.com/en-us/library/…4(v=vs.85).aspx



    https://msdn.microsoft.com/en-us/library/…4(v=vs.85).aspx

    CODe auf dem Bildschirm....

  • So, fertig. Müsste so klappen. Zumindest produziert das Beispiel bei mir eine sinnvolle Ausgabe.
    Zu erwähnen ist, dass die Funktion a) Quick'n'Dirty umgesetzt ist und b) in der Struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION bei dem Union NumaNode das Byte Flags nur über Umwege lesbar ist (Adresse von NodeNumber holen und Struct mit Byte an selber Stelle erstellen ODER Bit-Operationen mit NodeNumber).

    Kannst ja mal rumprobieren, ob das so passt.

    [autoit]


    #include <Array.au3>
    #include <Memory.au3>

    [/autoit][autoit][/autoit][autoit]

    #cs
    BOOL WINAPI GetLogicalProcessorInformation(
    _Out_ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
    _Inout_ PDWORD ReturnLength
    );

    [/autoit][autoit][/autoit][autoit]

    AUS: Kernel32.dll
    #ce
    Global Const $RELATIONPROCESSORCORE = 0

    [/autoit][autoit][/autoit][autoit]

    $atSLPI = GetLogicalProcessorInformation()
    $hMem = @extended
    $iCores = 0
    For $i = 0 To UBound($atSLPI) - 1
    If $atSLPI[$i].Relationship = $RELATIONPROCESSORCORE Then
    $iCores += 1
    EndIf
    Next
    ConsoleWrite("Detected " & $iCores & " processor cores on your system." & @CRLF)
    _MemGlobalFree($hMem) ;Immer dran denken, den Speicher wieder freizugeben!!!

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func GetLogicalProcessorInformation()
    Local $hDll, $hMem, $tBufferSize, $tBuffer, $tSLPI, $atSLPI, $tagSLPI, $iOffset
    $hDll = DllOpen("Kernel32.dll")
    $tBufferSize = DllStructCreate("dword size;")
    DllCall($hDll, "bool", "GetLogicalProcessorInformation", "struct*", 0, "DWORD_PTR", DllStructGetPtr($tBufferSize, "size"))

    [/autoit][autoit][/autoit][autoit]

    $hMem = _MemGlobalAlloc($tBufferSize.size, $GPTR) ;Nötig, da sonst nach Verlassen der Funktion der Speicherbereich freigegeben wird...
    $tBuffer = DllStructCreate("byte[" & $tBufferSize.size & "]", $hMem)
    DllCall($hDll, "bool", "GetLogicalProcessorInformation", "struct*", DllStructGetPtr($tBuffer), "DWORD_PTR", DllStructGetPtr($tBufferSize, "size"))

    [/autoit][autoit][/autoit][autoit]

    $tagSLPI = "ULONG_PTR ProcessorMask; WORD Relationship; STRUCT; DWORD NodeNumber; ENDSTRUCT; STRUCT; BYTE Level; BYTE Associativity; WORD LineSize; DWORD Size; INT Type; ENDSTRUCT; UINT64 Reserved[2]"
    $iOffset = 0
    Local $atSLPI[0]
    While ($iOffset + 40) < $tBufferSize.size
    $tSLPI = DllStructCreate($tagSLPI, DllStructGetPtr($tBuffer) + $iOffset)
    _ArrayAdd($atSLPI, $tSLPI)
    $iOffset += DllStructGetSize($tSLPI)
    WEnd

    [/autoit][autoit][/autoit][autoit]

    DllClose($hDll)
    Return SetExtended($hMem, $atSLPI)
    EndFunc

    [/autoit]
  • Hi,
    @chesstiger, gut angefangen, dann stark nachgelassen^^
    Du hast die "UNION" nicht in deine Struct verbaut....und auch nicht die Anzahl der Cores aus der Anzahl der gesetzten Bits aus ProcessorMask.
    Die Struct ist mitnichten 40Bytes (s. meinen nächsten Post^^), das Ergebnis deiner "Berechnung" entspricht also nicht der Erwartung. Mein AMD-Quadcore wird mit deinem Script mit 7 Cores ausgegeben....

    Bei 32bit ist eine "Line" der Struct 24 Bytes (4 Bytes ProcessorMask + 4 Bytes Relationship + 16 Bytes, in denen die UNION residiert)
    Bei 64bit ist eine "Line" der Struct 32 Bytes (8 Bytes ProcessorMask + 8 Bytes Relationship + 16 Bytes, in denen die UNION residiert)


    Mach da mal ne schicke auch für 64Bit gültige Version draus, incl. dem OO-Gedöns zum Abfragen der Struct-Items, das sieht nämlich wenigstens gut aus^^ //siehe EDIT unten


    //EDIT bitte auch für 64Bit testen!

  • Mit meinem Ansatz war ich voll auf dem Holzweg.....

    Da ich absolut kein C-Fuzzi bin, habe ich mir entsprechenden Code/Dokumentationen angeschaut und trotzdem nicht durchgeblickt ! :rtfm: <--hat auch nichts gebracht....
    Ich habe mir die _SYSTEM_LOGICAL_PROCESSOR_INFORMATION -Struct mit 48 Bytes vorgestellt (anhand des inhaltes des kompletten Speicherbereichs, daher auch die Aufteilung/Visualisierung mittels StringMid() ), allerdings nie begriffen, wie die Einzelteile mit der UNION korrespondieren...nachts um 2 dann ins Bett und geträumt....

    Nach 4h Schlaf besinnt man sich auf seine Fähigkeiten:

    Was IMMER, und zwar in jeder Programmiersprache funktioniert, ist Debugging!
    Also habe ich erst mal versucht, folgenden Code zu compilieren, was aber mit einem Linker-Fehler nicht funktionieren wollte (MinGW):
    https://msdn.microsoft.com/de-de/library/…4(v=vs.85).aspx

    Da nicht compilierbar, habe ich dann folgendes hingefriemelt:

    Nach geschmeidigem Hieb auf F8 (Compile and Execute) hat sich dann herausgestellt, dass die Struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION nur 24Bytes groß war!

    Dann fiel es mir wie Schuppen aus den Haaren und alles bekam Sinn:
    Jeweils 4 Bytes für ProcessorMask(ulong_ptr) und LOGICAL_PROCESSOR_RELATIONSHIP Relationship (eine Aufzählung, Typ ist UINT(-ptr)) sind zusammen 8 Bytes, der Rest musste die UNION sein.
    In der UNION wird der gleiche Speicher mit unterschiedlichen Typen belegt, der größte "zählt", also die beiden ULONGLONG (jeweils 8 = 16 bytes) Reserved[2].
    Der Rest war simpel, es wurde jeweils eine Struct "in" der UNION erstellt, mit entsprechenden Typen.
    "Alte Hasen" kennen mein Beispiel DllStruct Funktionen für Autoit

    Letztendlich sehe ich in diesem Vorgehen keinen großen Sinn, es ist beschissen zu lesen/verstehen und noch beschissener umzusetzen (man sehe sich den C-Code an!)
    Ich gehe mal davon aus dass jemand das so gemacht hat "weil er es kann" bzw. weil die Sprache das kann...naja :/

  • @UEZ, in keinem der dort verlinkten Scripte finde ich etwas dazu, außer :

    Zitat von Ascend4ent

    GetLogicalProcessorInformation should report the right information too, but at the moment I don't know how to interpret it ....

    Die sind alle mit anderen Funktionen weitergekommen :D