From: Katharine Chui kwchuiaa@connect.ust.hk
Normally Cyberpunk 2077 spawns #cpu_threads of dispatcher threads. However with Freebsd, since create_logical_proc_info was a stub, the game would instead spawn a single dispatcher thread, causing the game to just crawl.
Working around the issue by adding a barebone implementation of create_logical_proc_info for FreeBSD so that the game would at least get a thread count through ntdll. --- dlls/ntdll/unix/system.c | 68 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+)
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 72bdd6b31a5..baffaa360d4 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -1242,6 +1242,74 @@ static NTSTATUS create_logical_proc_info(void) return STATUS_SUCCESS; }
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + +/* + * this is currently mostly a reduced clone of the macos implementation + * it only reports thread counts so that cb2077 don't spawn a single dispatch thread only, and would spawn #threads instead + * TODO list: + * smt information + * numa information + * cache information + * package count + * it is also tempting to rely on lscpu output, however that would make freebsd wine packaging dependent on lscpu, don't know if that's a good idea + * or perhaps go for cpuid directly? however that'd would introduce quite the amount of boiler plates + * yet another alternative would be to rely on /compat/linux/sys, however FreeBSD only lists the number of online cores without smt, numa, cache nor package information, and linux compat has to be enabled + */ +static NTSTATUS create_logical_proc_info(void) +{ + unsigned int pkgs_no, cores_no, lcpu_no, lcpu_per_core, cores_per_package; + ULONG_PTR all_cpus_mask = 0; + size_t size; + unsigned int p, i, j, k; + + /* HW_NCPU works in FreeBSD */ + lcpu_no = peb->NumberOfProcessors; + + /* TODO assume one package */ + pkgs_no = 1; + + /* TODO assume no SMT */ + /* physical core number can be fetch with sysctl kern.smp.cores */ + cores_no = lcpu_no; + + TRACE("%u logical CPUs from %u physical cores across %u packages\n", + lcpu_no, cores_no, pkgs_no); + + lcpu_per_core = lcpu_no / cores_no; + cores_per_package = cores_no / pkgs_no; + + for(p = 0; p < pkgs_no; ++p) + { + for(j = 0; j < cores_per_package && p * cores_per_package + j < cores_no; ++j) + { + ULONG_PTR mask = 0; + DWORD phys_core; + + for(k = 0; k < lcpu_per_core; ++k) mask |= (ULONG_PTR)1 << (j * lcpu_per_core + k); + + all_cpus_mask |= mask; + + /* add to package */ + if(!logical_proc_info_add_by_id( RelationProcessorPackage, p, mask )) + return STATUS_NO_MEMORY; + + /* add new core */ + phys_core = p * cores_per_package + j; + if(!logical_proc_info_add_by_id( RelationProcessorCore, phys_core, mask )) + return STATUS_NO_MEMORY; + } + } + + /* TODO numa infomration */ + if(!logical_proc_info_add_numa_node( all_cpus_mask, 0 )) + return STATUS_NO_MEMORY; + + logical_proc_info_add_group( lcpu_no, all_cpus_mask ); + + return STATUS_SUCCESS; +} + #else
static NTSTATUS create_logical_proc_info(void)