mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-17 20:12:38 +00:00
189 lines
4.9 KiB
Odin
189 lines
4.9 KiB
Odin
package sysinfo
|
|
|
|
import "base:runtime"
|
|
import "core:strings"
|
|
import "core:strconv"
|
|
|
|
#assert(
|
|
ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || \
|
|
ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64 || \
|
|
ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 || \
|
|
ODIN_ARCH == .riscv64,
|
|
"This package is unsupported on this architecture.")
|
|
|
|
/*
|
|
Retrieves the number of physical and logical CPU cores
|
|
|
|
Returns:
|
|
- physical: The number of physical cores
|
|
- logical: The number of logical cores
|
|
- ok: `true` when we could retrieve the CPU information, `false` otherwise
|
|
*/
|
|
cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) {
|
|
return _cpu_core_count()
|
|
}
|
|
|
|
/*
|
|
Retrieves CPU features where available
|
|
|
|
The results are cached
|
|
|
|
Returns:
|
|
- features: An architecture-specific `bit_set`
|
|
- ok: `true` when we could retrieve the CPU features, `false` otherwise
|
|
*/
|
|
cpu_features :: proc "contextless" () -> (features: CPU_Features, ok: bool) {
|
|
return _cpu_features()
|
|
}
|
|
|
|
/*
|
|
Retrieves the CPU's name
|
|
|
|
The results are cached
|
|
|
|
Returns:
|
|
- name: A `string` containing the CPU model name, empty if the lookup failed
|
|
*/
|
|
cpu_name :: proc() -> (name: string) {
|
|
return _cpu_name()
|
|
}
|
|
|
|
/*
|
|
Retrieves RAM statistics
|
|
|
|
Unavailable stats will be returned as `0` bytes
|
|
|
|
Returns:
|
|
- total_ram: Total RAM reported by the operating system, in bytes
|
|
- free_ram: Free RAM reported by the operating system, in bytes
|
|
- total_swap: Total SWAP reported by the operating system, in bytes
|
|
- free_swap: Free SWAP reported by the operating system, in bytes
|
|
- ok: `true` when we could retrieve RAM statistics, `false` otherwise
|
|
*/
|
|
ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) {
|
|
return _ram_stats()
|
|
}
|
|
|
|
/*
|
|
Retrieves OS version information
|
|
|
|
*Allocates Using Provided Allocator*
|
|
|
|
You can use `destroy_os_version` to free the results
|
|
|
|
Inputs:
|
|
- allocator: A `runtime.Allocator` on which the version strings will be allocated
|
|
- loc: The caller location
|
|
|
|
Returns:
|
|
- res: An `OS_Version` struct
|
|
- ok: `true` when we could retrieve OS version information, `false` otherwise
|
|
*/
|
|
os_version :: proc(allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) {
|
|
return _os_version(allocator = allocator, loc = loc)
|
|
}
|
|
|
|
/*
|
|
Releases an `OS_Version`'s strings
|
|
|
|
*Frees Using Provided Allocator*
|
|
|
|
Inputs:
|
|
- version: An `OS_Version` struct
|
|
- allocator: A `runtime.Allocator` on which the version strings will be freed
|
|
*/
|
|
destroy_os_version :: proc(version: OS_Version, allocator: runtime.Allocator) {
|
|
delete(version.full, allocator)
|
|
// `version.release` is part of `version.full` and does not need to be freed separately.
|
|
}
|
|
|
|
OS_Version :: struct {
|
|
platform: OS_Version_Platform, // Windows, Linux, MacOS, iOS, etc.
|
|
full: string, // e.g. Windows 10 Professional (version: 22H2), build: 19045.6575
|
|
release: string, // e.g. 22H2
|
|
|
|
os: Version, // e.g. {major = 10, minor = 10, patch = 0}
|
|
kernel: Version, // e.g. {major = 10, minor = 19045, patch = 6575}
|
|
}
|
|
|
|
OS_Version_Platform :: enum {
|
|
Unknown,
|
|
Windows,
|
|
Linux,
|
|
MacOS,
|
|
iOS,
|
|
FreeBSD,
|
|
OpenBSD,
|
|
NetBSD,
|
|
}
|
|
|
|
Version :: struct {
|
|
major, minor, patch: int,
|
|
}
|
|
|
|
/*
|
|
Iterates over GPU adapters
|
|
|
|
On Windows: Enumerates `Computer\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}`
|
|
Elsewhere: Unsupported at the moment, returns `{}, 0, false`
|
|
|
|
Important: The `vendor` name, `model` name and `driver` version strings are backed by the `GPU_Iterator`.
|
|
Clone them if you want to these to persist.
|
|
|
|
Inputs:
|
|
- it: A pointer to a `GPU_Iterator`
|
|
- minimum_vram: The number of bytes of VRAM an adapter has to have to be considered, default 256 MiB
|
|
(This excludes most screen mirroring / remote desktop drivers)
|
|
|
|
Returns:
|
|
gpu: A `GPU` struct which contains `vendor` name, `model` name, `driver` version and `vram` in bytes
|
|
index: Loop index, optional
|
|
ok: `true` if this was a success and we should continue, `false` otherwise
|
|
*/
|
|
iterate_gpus :: proc(it: ^GPU_Iterator, minimum_vram := i64(256 * 1024 * 1024)) -> (gpu: GPU, index: int, ok: bool) {
|
|
when ODIN_OS == .Windows {
|
|
return _iterate_gpus(it, minimum_vram)
|
|
} else {
|
|
// Not implemented on another OS, yet
|
|
return {}, 0, false
|
|
}
|
|
}
|
|
|
|
GPU :: struct {
|
|
vendor: string,
|
|
model: string,
|
|
driver: string,
|
|
vram: i64,
|
|
}
|
|
|
|
GPU_Iterator :: struct {
|
|
// Public iterator index
|
|
index: int,
|
|
|
|
// Internal buffer + index
|
|
_buffer: [512]u8,
|
|
_index: int,
|
|
}
|
|
|
|
@(private)
|
|
_parse_version :: proc (str: string) -> (res: Version) {
|
|
str := str
|
|
i: int
|
|
for part in strings.split_iterator(&str, ".") {
|
|
defer i += 1
|
|
dst: ^int
|
|
switch i {
|
|
case 0: dst = &res.major
|
|
case 1: dst = &res.minor
|
|
case 2: dst = &res.patch
|
|
case: return
|
|
}
|
|
|
|
if num, num_ok := strconv.parse_int(part); !num_ok {
|
|
return
|
|
} else {
|
|
dst^ = num
|
|
}
|
|
}
|
|
return
|
|
} |