[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 02/04: Implemented detection of number of CPUs available
From: |
gnunet |
Subject: |
[libmicrohttpd] 02/04: Implemented detection of number of CPUs available for the process on W32 |
Date: |
Wed, 06 Sep 2023 16:42:19 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit cd16ca4d356117ecf2500c969ed3f502a2e75392
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Wed Sep 6 17:22:03 2023 +0300
Implemented detection of number of CPUs available for the process on W32
---
src/tools/mhd_tool_get_cpu_count.c | 204 +++++++++++++++++++++++++++++++++++++
1 file changed, 204 insertions(+)
diff --git a/src/tools/mhd_tool_get_cpu_count.c
b/src/tools/mhd_tool_get_cpu_count.c
index 9addf4be..bd79c69e 100644
--- a/src/tools/mhd_tool_get_cpu_count.c
+++ b/src/tools/mhd_tool_get_cpu_count.c
@@ -70,6 +70,9 @@
#ifdef HAVE_SYS_CPUSET_H
# include <sys/cpuset.h>
#endif /* HAVE_SYS_CPUSET_H */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif /* HAVE_STDBOOL_H */
#if ! defined(HAS_DECL_CPU_SETSIZE) && ! defined(CPU_SETSIZE)
# define CPU_SETSIZE (1024)
@@ -311,6 +314,203 @@ mhd_tool_get_proc_cpu_count_sched_getaffinity_np_ (void)
}
+/**
+ * Detect the number of logical CPU cores available for the process by
+ * W32 API functions.
+ * @return the number of detected logical CPU cores or
+ * -1 if failed to detect (or this function unavailable).
+ */
+static int
+mhd_tool_get_proc_cpu_count_w32_ (void)
+{
+ int ret = -1;
+#if defined(_WIN32) && ! defined(__CYGWIN__)
+ /* W32 Native */
+ /**
+ * Maximum used number of CPU groups.
+ * Improvement: Implement dynamic allocation when it would be reasonable
+ */
+#define MHDT_MAX_GROUP_COUNT 128
+ /**
+ * The count of logical CPUs as returned by GetProcessAffinityMask()
+ */
+ int count_by_proc_aff_mask;
+ count_by_proc_aff_mask = -1;
+ if (1)
+ {
+ DWORD_PTR proc_aff;
+ DWORD_PTR sys_aff;
+
+ if (GetProcessAffinityMask (GetCurrentProcess (), &proc_aff, &sys_aff))
+ {
+ /* Count all set bits */
+ for (count_by_proc_aff_mask = 0; 0 != proc_aff; proc_aff &= proc_aff - 1)
+ ++count_by_proc_aff_mask;
+ }
+ }
+ if (0 < count_by_proc_aff_mask)
+ {
+ HMODULE k32hndl;
+ k32hndl = LoadLibraryA ("kernel32.dll");
+ if (NULL != k32hndl)
+ {
+ typedef BOOL (WINAPI *GPGA_PTR)(HANDLE hProcess,
+ PUSHORT GroupCount,
+ PUSHORT GroupArray);
+ GPGA_PTR ptrGetProcessGroupAffinity;
+ ptrGetProcessGroupAffinity =
+ (GPGA_PTR) (void *) GetProcAddress (k32hndl,
+ "GetProcessGroupAffinity");
+ if (NULL == ptrGetProcessGroupAffinity)
+ {
+ /* Windows version before Win7 */
+ /* No processor groups supported, the process affinity mask gives full
picture */
+ ret = count_by_proc_aff_mask;
+ }
+ else
+ {
+ /* Windows version Win7 or later */
+ /* Processor groups are supported */
+ USHORT arr_elements = MHDT_MAX_GROUP_COUNT;
+ USHORT groups_arr[MHDT_MAX_GROUP_COUNT]; /* Hopefully should be enough
*/
+ /* Improvement: Implement dynamic allocation when it would be
reasonable */
+ /**
+ * Exactly one processor group is assigned to the process
+ */
+ bool single_cpu_group_assigned; /**< Exactly one processor group is
assigned to the process */
+ struct mhdt_GR_AFFINITY
+ {
+ KAFFINITY Mask;
+ WORD Group;
+ WORD Reserved[3];
+ };
+ typedef BOOL (WINAPI *GPDCSM_PTR)(HANDLE Process,
+ struct mhdt_GR_AFFINITY *CpuSetMasks,
+ USHORT CpuSetMaskCount,
+ USHORT *RequiredMaskCount);
+ GPDCSM_PTR ptrGetProcessDefaultCpuSetMasks;
+ bool win_fe_or_later;
+ bool cpu_set_mask_assigned;
+
+ single_cpu_group_assigned = false;
+ if (ptrGetProcessGroupAffinity (GetCurrentProcess (), &arr_elements,
+ groups_arr))
+ {
+ if (1 == arr_elements)
+ {
+ /* Exactly one processor group assigned to the process */
+ single_cpu_group_assigned = true;
+#if 0 /* Disabled code */
+ /* The value returned by GetThreadGroupAffinity() is not relevant
as
+ for the new threads the process affinity mask is used. */
+ ULONG_PTR proc_aff2;
+ typedef BOOL (WINAPI *GTGA_PTR)(HANDLE hThread,
+ struct mhdt_GR_AFFINITY *
+ GroupAffinity);
+ GTGA_PTR ptrGetThreadGroupAffinity;
+ ptrGetThreadGroupAffinity =
+ (GTGA_PTR) (void *) GetProcAddress (k32hndl,
+ "GetThreadGroupAffinity");
+ if (NULL != ptrGetThreadGroupAffinity)
+ {
+ struct mhdt_GR_AFFINITY thr_gr_aff;
+ if (ptrGetThreadGroupAffinity (GetCurrentThread (), &thr_gr_aff))
+ proc_aff2 = (ULONG_PTR) thr_gr_aff.Mask;
+ }
+#endif /* Disabled code */
+ }
+ }
+ ptrGetProcessDefaultCpuSetMasks =
+ (GPDCSM_PTR) (void *) GetProcAddress (k32hndl,
+
"GetProcessDefaultCpuSetMasks");
+ if (NULL != ptrGetProcessDefaultCpuSetMasks)
+ {
+ /* This is Iron Release / Codename Fe
+ (also know as Windows 11 and Windows Server 2022)
+ or later version */
+ struct mhdt_GR_AFFINITY gr_affs[MHDT_MAX_GROUP_COUNT]; /* Hopefully
should be enough */
+ /* Improvement: Implement dynamic allocation when it would be
reasonable */
+ USHORT num_elm;
+
+ win_fe_or_later = true;
+
+ if (ptrGetProcessDefaultCpuSetMasks (GetCurrentProcess (), gr_affs,
+ sizeof (gr_affs)
+ / sizeof (gr_affs[0]),
&num_elm))
+ {
+ if (0 == num_elm)
+ {
+ /* No group mask set */
+ cpu_set_mask_assigned = false;
+ }
+ else
+ cpu_set_mask_assigned = true;
+ }
+ else
+ cpu_set_mask_assigned = true; /* Assume the worst case */
+ }
+ else
+ {
+ win_fe_or_later = false;
+ cpu_set_mask_assigned = false;
+ }
+ if (! win_fe_or_later)
+ {
+ /* The OS is not capable of distributing threads across different
+ processor groups. Results reported by GetProcessAffinityMask()
+ are relevant for the main processor group for the process. */
+ ret = count_by_proc_aff_mask;
+ }
+ else
+ {
+ /* The of is capable of automatic threads distribution across
+ processor groups. */
+ if (cpu_set_mask_assigned)
+ {
+ /* Assigned Default CpuSet Masks combines with "classic"
+ affinity in the not fully clear way. The combination
+ is not documented and this functionality could be changed
+ any moment. */
+ ret = -1;
+ }
+ else
+ {
+ if (! single_cpu_group_assigned)
+ {
+ /* This is a multi processor group process on Win11 (or later).
+ Each processor group may have different affinity and
+ the OS has not API to get it.
+ For example, affinity to the main processor group could be
+ assigned by SetProcessAffinityMask() function, which converts
+ the process to the single-processor-group type, but if
+ SetThreadGroupAffinity() is called later and bind the thread
+ to another processor group, the process becomes
multi-processor-
+ group again, however the initial affinity mask is still used
+ for the initial (main) processor group. There is no API to
read
+ it.
+ It is also possible that processor groups have different
number
+ of processors. */
+ ret = -1;
+ }
+ else
+ {
+ /* Single-processor-group process on Win11 (or later) without
+ assigned Default CpuSet Masks. */
+ ret = count_by_proc_aff_mask;
+ }
+ }
+ }
+ }
+ FreeLibrary (k32hndl);
+ }
+ }
+#endif /* _WIN32 && ! __CYGWIN__ */
+ if (0 >= ret)
+ return -1;
+ return ret;
+}
+
+
/**
* Detect the number of logical CPU cores available for the process.
* The number of cores available for this process could be different from
@@ -352,6 +552,10 @@ mhd_tool_get_proc_cpu_count (void)
if (0 < res)
return res;
+ res = mhd_tool_get_proc_cpu_count_w32_ ();
+ if (0 < res)
+ return res;
+
return -1;
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.