Beispiel #1
0
        /// <summary>
        /// Gets the number of logical cores. We use this rather than Environment.ProcessorCount when possible to handle machines with > 64 cores (the single group limit available to the .NET framework).
        /// </summary>
        /// <returns>The number of logical cores.</returns>
        public static int GetLogicalProcessorCount()
        {
            // This function uses Windows P/Invoke calls; if we're on Mono, just return the default.
            if (!Utils.IsRunningOnMono)
            {
                const int ERROR_INSUFFICIENT_BUFFER = 122;

                // Determine the required buffer size to store the processor information
                uint ReturnLength = 0;
                if (!GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup, IntPtr.Zero, ref ReturnLength) && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                {
                    // Allocate a buffer for it
                    IntPtr Ptr = Marshal.AllocHGlobal((int)ReturnLength);
                    try
                    {
                        if (GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup, Ptr, ref ReturnLength))
                        {
                            int Count = 0;
                            for (int Pos = 0; Pos < ReturnLength;)
                            {
                                LOGICAL_PROCESSOR_RELATIONSHIP Type = (LOGICAL_PROCESSOR_RELATIONSHIP)Marshal.ReadInt16(Ptr, Pos);
                                if (Type == LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup)
                                {
                                    // Read the values from the embedded GROUP_RELATIONSHIP structure
                                    int GroupRelationshipPos = Pos + 8;
                                    int ActiveGroupCount     = Marshal.ReadInt16(Ptr, GroupRelationshipPos + 2);

                                    // Read the processor counts from the embedded PROCESSOR_GROUP_INFO structures
                                    int GroupInfoPos = GroupRelationshipPos + 24;
                                    for (int GroupIdx = 0; GroupIdx < ActiveGroupCount; GroupIdx++)
                                    {
                                        Count        += Marshal.ReadByte(Ptr, GroupInfoPos + 1);
                                        GroupInfoPos += 40 + IntPtr.Size;
                                    }
                                }
                                Pos += Marshal.ReadInt32(Ptr, Pos + 4);
                            }
                            return(Count);
                        }
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(Ptr);
                    }
                }
            }
            return(Environment.ProcessorCount);
        }
Beispiel #2
0
        /// <summary>
        /// Gets the number of physical cores, excluding hyper threading.
        /// </summary>
        /// <returns>The number of physical cores, or -1 if it could not be obtained</returns>
        public static int GetPhysicalProcessorCount()
        {
            // This function uses Windows P/Invoke calls; if we're on Mono, just fail.
            if (Utils.IsRunningOnMono)
            {
                return(-1);
            }

            const int ERROR_INSUFFICIENT_BUFFER = 122;

            // Determine the required buffer size to store the processor information
            uint ReturnLength = 0;

            if (!GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, IntPtr.Zero, ref ReturnLength) && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
            {
                // Allocate a buffer for it
                IntPtr Ptr = Marshal.AllocHGlobal((int)ReturnLength);
                try
                {
                    if (GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, Ptr, ref ReturnLength))
                    {
                        // As per-MSDN, this will return one structure per physical processor. Each SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX structure is of a variable size, so just skip
                        // through the list and count the number of entries.
                        int Count = 0;
                        for (int Pos = 0; Pos < ReturnLength;)
                        {
                            LOGICAL_PROCESSOR_RELATIONSHIP Type = (LOGICAL_PROCESSOR_RELATIONSHIP)Marshal.ReadInt16(Ptr, Pos);
                            if (Type == LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore)
                            {
                                Count++;
                            }
                            Pos += Marshal.ReadInt32(Ptr, Pos + 4);
                        }
                        return(Count);
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(Ptr);
                }
            }

            return(-1);
        }
Beispiel #3
0
 private static extern void GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP lpr, out IntPtr ptr, ref IntPtr ReturnLength);
Beispiel #4
0
 extern static bool GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, IntPtr Buffer, ref uint ReturnedLength);
Beispiel #5
0
 private static extern bool GetLogicalProcessorInformationEx(
     LOGICAL_PROCESSOR_RELATIONSHIP relationshipType,
     IntPtr buffer,
     ref UInt32 returnedLength);
 public static unsafe void Can_call_extern_function(LOGICAL_PROCESSOR_RELATIONSHIP relType)
 {
     bool successful = GetLogicalProcessorInformationEx(
         relType, default, out int bytesRequired);
 public static extern BOOL GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, [NativeTypeName("PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX")] SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *Buffer, [NativeTypeName("PDWORD")] uint *ReturnedLength);
 internal static extern bool GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, IntPtr Buffer, ref uint ReturnedLength);
        private int GetProcessorInfo(LOGICAL_PROCESSOR_RELATIONSHIP coreCountType)
        {
            var  buffer       = new List <ISYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>();
            uint returnLength = 0;

            GetLogicalProcessorInformationEx(coreCountType, IntPtr.Zero, ref returnLength);
            if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
            {
                var ptr = Marshal.AllocHGlobal((int)returnLength);
                try
                {
                    if (GetLogicalProcessorInformationEx(coreCountType, ptr, ref returnLength))
                    {
                        var item      = ptr;
                        var readCount = 0;
                        //int size = Marshal.SizeOf(typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX));
                        //int len = (int)returnLength / size;
                        //for (int i = 0; i < len; i++)
                        while (readCount < returnLength)
                        {
                            var type = (LOGICAL_PROCESSOR_RELATIONSHIP)Marshal.ReadInt32(item);
                            var size = Marshal.ReadInt32(item, 4);
                            var data = new byte[size];
                            Marshal.Copy(item, data, 0, size);

                            switch (type)
                            {
                            case LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorPackage:
                            case LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore:
                                buffer.Add((SLPI_PROCESSOR_RELATIONSHIP)Marshal.PtrToStructure(item, typeof(SLPI_PROCESSOR_RELATIONSHIP)));
                                break;

                            case LOGICAL_PROCESSOR_RELATIONSHIP.RelationNumaNode:
                                buffer.Add((SLPI_NUMA_NODE_RELATIONSHIP)Marshal.PtrToStructure(item, typeof(SLPI_NUMA_NODE_RELATIONSHIP)));
                                break;

                            case LOGICAL_PROCESSOR_RELATIONSHIP.RelationCache:
                                buffer.Add((SLPI_CACHE_RELATIONSHIP)Marshal.PtrToStructure(item, typeof(SLPI_CACHE_RELATIONSHIP)));
                                break;

                            case LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup:
                                buffer.Add((SLPI_GROUP_RELATIONSHIP)Marshal.PtrToStructure(item, typeof(SLPI_GROUP_RELATIONSHIP)));
                                break;
                            }

                            item      += size;
                            readCount += size;
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(ptr);
                }
            }
            //foreach (var proc in buffer)
            //{
            //    Console.WriteLine(proc.ProcRelationship.ToString());
            //}

            return(buffer.Count);
        }
        /// <summary>
        /// Generic method for calling GetLogicalProcessorInformationEx that returns the correct structure type.
        /// </summary>
        /// <typeparam name="T">The structure type that should be returned. Must match the relationship type.</typeparam>
        /// <param name="relationshipType">The relationship type to call GetLogicalProcessorInformationEx with.</param>
        /// <returns></returns>
        private static T[] GetLogicalProcessorInformationEx <T>(LOGICAL_PROCESSOR_RELATIONSHIP relationshipType) where T : struct
        {
            // validate that the lookup type and class parameter matches properly
            var typeClassLooukp = new Dictionary <LOGICAL_PROCESSOR_RELATIONSHIP, Type>
            {
                { LOGICAL_PROCESSOR_RELATIONSHIP.ProcessorCore, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_PROCESSOR) },
                { LOGICAL_PROCESSOR_RELATIONSHIP.ProcessorPackage, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_PROCESSOR) },
                { LOGICAL_PROCESSOR_RELATIONSHIP.NumaNode, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_NUMA_NODE) },
                { LOGICAL_PROCESSOR_RELATIONSHIP.Cache, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_CACHE) },
                { LOGICAL_PROCESSOR_RELATIONSHIP.Group, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX_GROUP) },
            };

            if (typeClassLooukp[relationshipType] != typeof(T))
            {
                throw new InvalidCastException($"Generic type {typeof(T).Name} passed does not match the relationship type {relationshipType}.");
            }

            /* TODO: Rework this to fix the race condition in which the internal data changes between the first call to GetLogicalProcessorInformationEx and the second.
             * This is a rare or impossible case for everything but groups, which may techncially change over time. For now this code will work in 99.999999% of cases.
             */


            // find the length required for the buffer
            uint requiredLength = 0;
            bool success        = NativeMethods.GetLogicalProcessorInformationEx(relationshipType, IntPtr.Zero, ref requiredLength);

            if (!success && Marshal.GetLastWin32Error() != NativeMethods.ERROR_INSUFFICIENT_BUFFER)
            {
                throw new InvalidOperationException($"The call to GetLogicalProcessorInformationEx failed. Last error: {Marshal.GetLastWin32Error()}");
            }

            // pad allocation up to the nearest 64-bit boundary
            requiredLength += 8 - (requiredLength % 8);

            if (requiredLength > int.MaxValue)
            {
                throw new InvalidOperationException($"The call to GetLogicalProcessorInformationEx returned a required data size ({requiredLength}) that exceeded the maximum signed integer value.");
            }

            IntPtr memProcInfo = Marshal.AllocHGlobal((int)requiredLength);

            try
            {
                uint bufferLength = requiredLength;
                success = NativeMethods.GetLogicalProcessorInformationEx(relationshipType, memProcInfo, ref bufferLength);
                if (!success)
                {
                    throw new InvalidOperationException($"The call to GetLogicalProcessorInformationEx failed. Last error: {Marshal.GetLastWin32Error()}");
                }

#if OLD_DOT_NET_VERSION
                uint structLength = (uint)Marshal.SizeOf(typeof(T));
#else
                uint structLength = (uint)Marshal.SizeOf <T>();
#endif

                if (bufferLength > requiredLength || bufferLength < structLength)
                {
                    throw new InvalidOperationException($"The call to GetLogicalProcessorInformationEx returned an invalid data length ({bufferLength}).");
                }

                uint   arrayCount  = bufferLength / structLength;
                var    structArray = new T[arrayCount];
                IntPtr pointer     = memProcInfo;
                for (int i = 0; i < arrayCount; i++)
                {
#if OLD_DOT_NET_VERSION
                    structArray[i] = (T)Marshal.PtrToStructure(pointer, typeof(T));
#else
                    structArray[i] = Marshal.PtrToStructure <T>(pointer);
#endif
                    pointer += (int)structLength;
                }

                return(structArray);
            }
            finally
            {
                Marshal.FreeHGlobal(memProcInfo);
            }
        }
Beispiel #11
0
 public static extern unsafe bool GetLogicalProcessorInformationEx(
     LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType,
     SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *Buffer,
     ref int ReturnedLength
     );