mirror of
https://github.com/vlang/v.git
synced 2025-08-03 09:47:15 -04:00
runtime: make free_memory() and total_memory() return Result types to allow for reporting errors (#24651)
This commit is contained in:
parent
061da6aac6
commit
8c573cf355
@ -104,8 +104,8 @@ fn (mut a App) collect_info() {
|
||||
}
|
||||
a.line('OS', '${os_kind}, ${os_details}')
|
||||
a.line('Processor', arch_details.join(', '))
|
||||
total_memory := f32(runtime.total_memory()) / (1024.0 * 1024.0 * 1024.0)
|
||||
free_memory := f32(runtime.free_memory()) / (1024.0 * 1024.0 * 1024.0)
|
||||
total_memory := f32(runtime.total_memory() or { 0 }) / (1024.0 * 1024.0 * 1024.0)
|
||||
free_memory := f32(runtime.free_memory() or { 0 }) / (1024.0 * 1024.0 * 1024.0)
|
||||
if total_memory != 0 && free_memory != 0 {
|
||||
a.line('Memory', '${free_memory:.2}GB/${total_memory:.2}GB')
|
||||
} else {
|
||||
|
@ -1,6 +1,7 @@
|
||||
module runtime
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
|
||||
@[typedef]
|
||||
pub struct C.vm_size_t {
|
||||
@ -17,21 +18,46 @@ pub struct C.vm_statistics64_data_t {
|
||||
@[typedef]
|
||||
pub struct C.host_t {}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.task_t {}
|
||||
|
||||
fn C.mach_host_self() C.host_t
|
||||
fn C.mach_task_self() C.task_t
|
||||
fn C.mach_port_deallocate(task C.task_t, host C.host_t) int
|
||||
fn C.host_page_size(host C.host_t, out_page_size &C.vm_size_t) int
|
||||
fn C.host_statistics64(host C.host_t, flavor int, host_info_out &int, host_info_outCnt &u32) int
|
||||
|
||||
fn free_memory_impl() usize {
|
||||
fn free_memory_impl() !usize {
|
||||
$if macos {
|
||||
mut hs := C.vm_statistics64_data_t{}
|
||||
mut vmsz := u32(C.HOST_VM_INFO64_COUNT)
|
||||
mut hps := u32(0)
|
||||
mut host := C.mach_host_self()
|
||||
defer {
|
||||
// Critical: Release send right for host port
|
||||
// --------------------------------------------------
|
||||
// Mach ports are system resources. Calling mach_host_self()
|
||||
// increments the port's reference count. We must manually release
|
||||
// to prevent resource leaks (port exhaustion can cause kernel failures).
|
||||
// mach_port_deallocate decrements the reference count, allowing
|
||||
// system resource reclamation when count reaches zero.
|
||||
// Parameters:
|
||||
// C.mach_task_self() - Port for current task
|
||||
// host - Host port to release
|
||||
// Return value ignored (_) since we only care about resource cleanup
|
||||
_ := C.mach_port_deallocate(C.mach_task_self(), host)
|
||||
}
|
||||
unsafe {
|
||||
C.host_statistics64(host, C.HOST_VM_INFO64, &int(&hs), &vmsz)
|
||||
C.host_page_size(host, &C.vm_size_t(&hps))
|
||||
retval_1 := C.host_statistics64(host, C.HOST_VM_INFO64, &int(&hs), &vmsz)
|
||||
if retval_1 != C.KERN_SUCCESS {
|
||||
return error('free_memory: `C.host_statistics64()` return = ${retval_1}')
|
||||
}
|
||||
retval_2 := C.host_page_size(host, &C.vm_size_t(&hps))
|
||||
if retval_2 != C.KERN_SUCCESS {
|
||||
return error('free_memory: `C.host_page_size()` return = ${retval_2}')
|
||||
}
|
||||
}
|
||||
return usize(u64(hs.free_count) * u64(hps))
|
||||
}
|
||||
return 1
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
module runtime
|
||||
|
||||
fn free_memory_impl() usize {
|
||||
return 1
|
||||
fn free_memory_impl() !usize {
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
|
@ -2,21 +2,37 @@ module runtime
|
||||
|
||||
fn C.sysctlnametomib(name charptr, mib &int, len &usize) int
|
||||
|
||||
fn free_memory_impl() usize {
|
||||
fn free_memory_impl() !usize {
|
||||
$if cross ? {
|
||||
return 1
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
$if !cross ? {
|
||||
$if freebsd {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('free_memory: `C.sysconf()` return error code = ${c_errno_1}')
|
||||
}
|
||||
mut mib := [4]int{}
|
||||
mut len := usize(4)
|
||||
unsafe { C.sysctlnametomib(c'vm.stats.vm.v_free_count', &mib[0], &len) }
|
||||
retval_2 := unsafe {
|
||||
C.sysctlnametomib(c'vm.stats.vm.v_free_count', &mib[0], &len)
|
||||
}
|
||||
c_errno_2 := C.errno
|
||||
if retval_2 == -1 {
|
||||
return error('free_memory: `C.sysctlnametomib()` return error code = ${c_errno_2}')
|
||||
}
|
||||
mut free_pages := int(0)
|
||||
bufsize := usize(4)
|
||||
unsafe { C.sysctl(&mib[0], mib.len, &free_pages, &bufsize, 0, 0) }
|
||||
retval_3 := unsafe {
|
||||
C.sysctl(&mib[0], mib.len, &free_pages, &bufsize, 0, 0)
|
||||
}
|
||||
c_errno_3 := C.errno
|
||||
if retval_3 == -1 {
|
||||
return error('free_memory: `C.sysctl()` return error code = ${c_errno_3}')
|
||||
}
|
||||
return page_size * usize(free_pages)
|
||||
}
|
||||
}
|
||||
return 1
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
|
@ -1,15 +1,23 @@
|
||||
module runtime
|
||||
|
||||
fn free_memory_impl() usize {
|
||||
fn free_memory_impl() !usize {
|
||||
$if cross ? {
|
||||
return 1
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
$if !cross ? {
|
||||
$if linux {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('free_memory: `C.sysconf(C._SC_PAGESIZE)` return error code = ${c_errno_1}')
|
||||
}
|
||||
av_phys_pages := usize(C.sysconf(C._SC_AVPHYS_PAGES))
|
||||
c_errno_2 := C.errno
|
||||
if av_phys_pages == usize(-1) {
|
||||
return error('free_memory: `C.sysconf(C._SC_AVPHYS_PAGES)` return error code = ${c_errno_2}')
|
||||
}
|
||||
return page_size * av_phys_pages
|
||||
}
|
||||
}
|
||||
return 1
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
|
@ -8,18 +8,22 @@ struct C.uvmexp {
|
||||
free int
|
||||
}
|
||||
|
||||
fn free_memory_impl() usize {
|
||||
fn free_memory_impl() !usize {
|
||||
$if cross ? {
|
||||
return 1
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
$if !cross ? {
|
||||
$if openbsd {
|
||||
mib := [C.CTL_VM, C.VM_UVMEXP]!
|
||||
mut uvm := C.uvmexp{0, 0}
|
||||
mut len := sizeof(C.uvmexp)
|
||||
unsafe { C.sysctl(&mib[0], mib.len, &uvm, &len, C.NULL, 0) }
|
||||
retval := unsafe { C.sysctl(&mib[0], mib.len, &uvm, &len, C.NULL, 0) }
|
||||
c_errno := C.errno
|
||||
if retval == -1 {
|
||||
return error('free_memory: `C.sysctl()` return error code = ${c_errno}')
|
||||
}
|
||||
return usize(uvm.pagesize) * usize(uvm.free)
|
||||
}
|
||||
}
|
||||
return 1
|
||||
return error('free_memory: not implemented')
|
||||
}
|
||||
|
@ -8,15 +8,23 @@ pub fn nr_cpus() int {
|
||||
}
|
||||
|
||||
// total_memory returns total physical memory found on the system.
|
||||
pub fn total_memory() usize {
|
||||
pub fn total_memory() !usize {
|
||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
||||
c_errno_1 := C.errno
|
||||
if page_size == usize(-1) {
|
||||
return error('total_memory: `C.sysconf(C._SC_PAGESIZE)` return error code = ${c_errno_1}')
|
||||
}
|
||||
phys_pages := usize(C.sysconf(C._SC_PHYS_PAGES))
|
||||
c_errno_2 := C.errno
|
||||
if phys_pages == usize(-1) {
|
||||
return error('total_memory: `C.sysconf(C._SC_PHYS_PAGES)` return error code = ${c_errno_2}')
|
||||
}
|
||||
return page_size * phys_pages
|
||||
}
|
||||
|
||||
// free_memory returns free physical memory found on the system.
|
||||
// Note: implementation available only on Darwin, FreeBSD, Linux, OpenBSD and
|
||||
// Windows. Otherwise, returns 1.
|
||||
pub fn free_memory() usize {
|
||||
return free_memory_impl()
|
||||
// Windows. Otherwise, returns 'free_memory: not implemented'.
|
||||
pub fn free_memory() !usize {
|
||||
return free_memory_impl()!
|
||||
}
|
||||
|
@ -1,11 +1,17 @@
|
||||
import runtime
|
||||
|
||||
fn test_physical_memory() {
|
||||
total := runtime.total_memory()
|
||||
free := runtime.free_memory()
|
||||
println('total memory: ${total}')
|
||||
println('free memory: ${free}')
|
||||
assert total > 0 && free > 0
|
||||
$if windows || linux || darwin || freebsd || openbsd {
|
||||
total := runtime.total_memory()!
|
||||
free := runtime.free_memory()!
|
||||
println('total memory: ${total}')
|
||||
println('free memory: ${free}')
|
||||
assert total > 0 && free > 0
|
||||
} $else {
|
||||
total := runtime.total_memory()!
|
||||
_ := runtime.free_memory() or { assert err.msg().contains('not implemented') }
|
||||
assert total > 0
|
||||
}
|
||||
}
|
||||
|
||||
fn test_nr_cpus() {
|
||||
|
@ -23,14 +23,14 @@ pub fn nr_cpus() int {
|
||||
}
|
||||
|
||||
// total_memory returns total physical memory found on the system.
|
||||
pub fn total_memory() usize {
|
||||
pub fn total_memory() !usize {
|
||||
memory_status := C.MEMORYSTATUS{}
|
||||
C.GlobalMemoryStatus(&memory_status)
|
||||
return memory_status.dwTotalPhys
|
||||
}
|
||||
|
||||
// free_memory returns free physical memory found on the system.
|
||||
pub fn free_memory() usize {
|
||||
pub fn free_memory() !usize {
|
||||
memory_status := C.MEMORYSTATUS{}
|
||||
C.GlobalMemoryStatus(&memory_status)
|
||||
return memory_status.dwAvailPhys
|
||||
|
Loading…
x
Reference in New Issue
Block a user