Browse Source

Merge pull request #2292 from colrdavidson/get_core_count

add get core count
gingerBill 2 years ago
parent
commit
dd3fac7523

+ 4 - 0
core/os/os.odin

@@ -261,3 +261,7 @@ heap_allocator :: proc() -> mem.Allocator {
 		data = nil,
 	}
 }
+
+processor_core_count :: proc() -> int {
+	return _processor_core_count()
+}

+ 13 - 0
core/os/os_darwin.odin

@@ -314,6 +314,7 @@ foreign libc {
 	@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
 
 	@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring ---
+	@(link_name="sysctlbyname") _sysctlbyname    :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
 
 	@(link_name="exit")    _unix_exit :: proc(status: c.int) -> ! ---
 }
@@ -771,6 +772,18 @@ get_page_size :: proc() -> int {
 	return page_size
 }
 
+@(private)
+_processor_core_count :: proc() -> int {
+	count : int = 0
+	count_size := size_of(count)
+	if _sysctlbyname("hw.logicalcpu", &count, &count_size, nil, 0) == 0 {
+		if count > 0 {
+			return count
+		}
+	}
+
+	return 1
+}
 
 _alloc_command_line_arguments :: proc() -> []string {
 	res := make([]string, len(runtime.args__))

+ 14 - 0
core/os/os_freebsd.odin

@@ -287,6 +287,7 @@ foreign libc {
 	
 	@(link_name="getenv")           _unix_getenv        :: proc(cstring) -> cstring ---
 	@(link_name="realpath")         _unix_realpath      :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
+	@(link_name="sysctlbyname")     _sysctlbyname       :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
 
 	@(link_name="exit")             _unix_exit          :: proc(status: c.int) -> ! ---
 }
@@ -702,6 +703,19 @@ get_page_size :: proc() -> int {
 	return page_size
 }
 
+@(private)
+_processor_core_count :: proc() -> int {
+	count : int = 0
+	count_size := size_of(count)
+	if _sysctlbyname("hw.logicalcpu", &count, &count_size, nil, 0) == 0 {
+		if count > 0 {
+			return count
+		}
+	}
+
+	return 1
+}
+
 
 _alloc_command_line_arguments :: proc() -> []string {
 	res := make([]string, len(runtime.args__))

+ 5 - 0
core/os/os_linux.odin

@@ -404,6 +404,7 @@ foreign libc {
 	@(link_name="__errno_location") __errno_location    :: proc() -> ^int ---
 
 	@(link_name="getpagesize")      _unix_getpagesize   :: proc() -> c.int ---
+	@(link_name="get_nprocs")       _unix_get_nprocs    :: proc() -> c.int ---
 	@(link_name="fdopendir")        _unix_fdopendir     :: proc(fd: Handle) -> Dir ---
 	@(link_name="closedir")         _unix_closedir      :: proc(dirp: Dir) -> c.int ---
 	@(link_name="rewinddir")        _unix_rewinddir     :: proc(dirp: Dir) ---
@@ -878,6 +879,10 @@ get_page_size :: proc() -> int {
 	return page_size
 }
 
+@(private)
+_processor_core_count :: proc() -> int {
+	return int(_unix_get_nprocs())
+}
 
 _alloc_command_line_arguments :: proc() -> []string {
 	res := make([]string, len(runtime.args__))

+ 8 - 1
core/os/os_openbsd.odin

@@ -269,6 +269,7 @@ foreign libc {
 	@(link_name="mkdir")	_unix_mkdir	:: proc(path: cstring, mode: mode_t) -> c.int ---
 
 	@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
+	@(link_name="sysconf") _sysconf :: proc(name: c.int) -> c.long ---
 	@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
 	@(link_name="closedir")	_unix_closedir	:: proc(dirp: Dir) -> c.int ---
 	@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
@@ -704,6 +705,12 @@ get_page_size :: proc() -> int {
 	return page_size
 }
 
+_SC_NPROCESSORS_ONLN :: 503
+
+@(private)
+_processor_core_count :: proc() -> int {
+	return int(_sysconf(_SC_NPROCESSORS_ONLN))
+}
 
 _alloc_command_line_arguments :: proc() -> []string {
 	res := make([]string, len(runtime.args__))
@@ -711,4 +718,4 @@ _alloc_command_line_arguments :: proc() -> []string {
 		res[i] = string(arg)
 	}
 	return res
-}
+}

+ 4 - 1
core/os/os_wasi.odin

@@ -89,7 +89,10 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
 current_thread_id :: proc "contextless" () -> int {
 	return 0
 }
-
+@(private)
+_processor_core_count :: proc() -> int {
+	return 1
+}
 
 file_size :: proc(fd: Handle) -> (i64, Errno) {
 	stat, err := wasi.fd_filestat_get(wasi.fd_t(fd))

+ 23 - 1
core/os/os_windows.odin

@@ -3,6 +3,7 @@ package os
 
 import win32 "core:sys/windows"
 import "core:runtime"
+import "core:intrinsics"
 
 Handle    :: distinct uintptr
 File_Time :: distinct u64
@@ -126,7 +127,28 @@ get_page_size :: proc() -> int {
 	return page_size
 }
 
+@(private)
+_processor_core_count :: proc() -> int {
+	length : win32.DWORD = 0
+	result := win32.GetLogicalProcessorInformation(nil, &length)
 
+	thread_count := 0
+	if !result && win32.GetLastError() == 122 && length > 0 {
+		processors := make([]win32.SYSTEM_LOGICAL_PROCESSOR_INFORMATION, length, context.temp_allocator)
+
+		result = win32.GetLogicalProcessorInformation(&processors[0], &length)
+		if result {
+			for processor in processors {
+				if processor.Relationship == .RelationProcessorCore {
+					thread := intrinsics.count_ones(processor.ProcessorMask)
+					thread_count += int(thread)
+				}
+			}
+		}
+	}
+
+	return thread_count
+}
 
 exit :: proc "contextless" (code: int) -> ! {
 	runtime._cleanup_runtime_contextless()
@@ -214,4 +236,4 @@ is_windows_10 :: proc() -> bool {
 is_windows_11 :: proc() -> bool {
 	osvi := get_windows_version_w()
 	return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber >= WINDOWS_11_BUILD_CUTOFF)
-}
+}

+ 48 - 0
core/sys/windows/kernel32.odin

@@ -370,6 +370,8 @@ foreign kernel32 {
 		lpTotalNumberOfBytes: PULARGE_INTEGER,
 		lpTotalNumberOfFreeBytes: PULARGE_INTEGER,
 	) -> BOOL ---
+
+	GetLogicalProcessorInformation :: proc(buffer: ^SYSTEM_LOGICAL_PROCESSOR_INFORMATION, returnedLength: PDWORD) -> BOOL ---
 }
 
 
@@ -999,3 +1001,49 @@ foreign kernel32 {
 	ConvertThreadToFiber :: proc(lpParameter: LPVOID) -> LPVOID ---
 	SwitchToFiber :: proc(lpFiber: LPVOID) ---
 }
+
+LOGICAL_PROCESSOR_RELATIONSHIP :: enum c_int {
+	RelationProcessorCore,
+	RelationNumaNode,
+	RelationCache,
+	RelationProcessorPackage,
+	RelationGroup,
+	RelationProcessorDie,
+	RelationNumaNodeEx,
+	RelationProcessorModule,
+	RelationAll = 0xffff,
+}
+
+PROCESSOR_CACHE_TYPE :: enum c_int {
+	CacheUnified,
+	CacheInstruction,
+	CacheData,
+	CacheTrace,
+}
+
+CACHE_DESCRIPTOR :: struct {
+	Level: BYTE,
+	Associativity: BYTE,
+	LineSize: WORD,
+	Size: DWORD,
+	Type: PROCESSOR_CACHE_TYPE,
+}
+
+ProcessorCore :: struct {
+	Flags: BYTE,
+}
+NumaNode :: struct {
+	NodeNumber: DWORD,
+}
+DUMMYUNIONNAME_u :: struct #raw_union {
+	Core: ProcessorCore,
+	Node: NumaNode,
+	Cache: CACHE_DESCRIPTOR,
+	Reserved: [2]ULONGLONG,
+}
+
+SYSTEM_LOGICAL_PROCESSOR_INFORMATION :: struct {
+	ProcessorMask: ULONG_PTR,
+	Relationship: LOGICAL_PROCESSOR_RELATIONSHIP,
+	DummyUnion: DUMMYUNIONNAME_u,
+}