mirror of
https://github.com/vlang/v.git
synced 2025-09-07 22:30:57 -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('OS', '${os_kind}, ${os_details}')
|
||||||
a.line('Processor', arch_details.join(', '))
|
a.line('Processor', arch_details.join(', '))
|
||||||
total_memory := f32(runtime.total_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()) / (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 {
|
if total_memory != 0 && free_memory != 0 {
|
||||||
a.line('Memory', '${free_memory:.2}GB/${total_memory:.2}GB')
|
a.line('Memory', '${free_memory:.2}GB/${total_memory:.2}GB')
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
module runtime
|
module runtime
|
||||||
|
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
|
#include <mach/task.h>
|
||||||
|
|
||||||
@[typedef]
|
@[typedef]
|
||||||
pub struct C.vm_size_t {
|
pub struct C.vm_size_t {
|
||||||
@ -17,21 +18,46 @@ pub struct C.vm_statistics64_data_t {
|
|||||||
@[typedef]
|
@[typedef]
|
||||||
pub struct C.host_t {}
|
pub struct C.host_t {}
|
||||||
|
|
||||||
|
@[typedef]
|
||||||
|
pub struct C.task_t {}
|
||||||
|
|
||||||
fn C.mach_host_self() C.host_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_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 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 {
|
$if macos {
|
||||||
mut hs := C.vm_statistics64_data_t{}
|
mut hs := C.vm_statistics64_data_t{}
|
||||||
mut vmsz := u32(C.HOST_VM_INFO64_COUNT)
|
mut vmsz := u32(C.HOST_VM_INFO64_COUNT)
|
||||||
mut hps := u32(0)
|
mut hps := u32(0)
|
||||||
mut host := C.mach_host_self()
|
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 {
|
unsafe {
|
||||||
C.host_statistics64(host, C.HOST_VM_INFO64, &int(&hs), &vmsz)
|
retval_1 := C.host_statistics64(host, C.HOST_VM_INFO64, &int(&hs), &vmsz)
|
||||||
C.host_page_size(host, &C.vm_size_t(&hps))
|
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 usize(u64(hs.free_count) * u64(hps))
|
||||||
}
|
}
|
||||||
return 1
|
return error('free_memory: not implemented')
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
module runtime
|
module runtime
|
||||||
|
|
||||||
fn free_memory_impl() usize {
|
fn free_memory_impl() !usize {
|
||||||
return 1
|
return error('free_memory: not implemented')
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,37 @@ module runtime
|
|||||||
|
|
||||||
fn C.sysctlnametomib(name charptr, mib &int, len &usize) int
|
fn C.sysctlnametomib(name charptr, mib &int, len &usize) int
|
||||||
|
|
||||||
fn free_memory_impl() usize {
|
fn free_memory_impl() !usize {
|
||||||
$if cross ? {
|
$if cross ? {
|
||||||
return 1
|
return error('free_memory: not implemented')
|
||||||
}
|
}
|
||||||
$if !cross ? {
|
$if !cross ? {
|
||||||
$if freebsd {
|
$if freebsd {
|
||||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
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 mib := [4]int{}
|
||||||
mut len := usize(4)
|
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)
|
mut free_pages := int(0)
|
||||||
bufsize := usize(4)
|
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 page_size * usize(free_pages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1
|
return error('free_memory: not implemented')
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
module runtime
|
module runtime
|
||||||
|
|
||||||
fn free_memory_impl() usize {
|
fn free_memory_impl() !usize {
|
||||||
$if cross ? {
|
$if cross ? {
|
||||||
return 1
|
return error('free_memory: not implemented')
|
||||||
}
|
}
|
||||||
$if !cross ? {
|
$if !cross ? {
|
||||||
$if linux {
|
$if linux {
|
||||||
page_size := usize(C.sysconf(C._SC_PAGESIZE))
|
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))
|
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 page_size * av_phys_pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1
|
return error('free_memory: not implemented')
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,22 @@ struct C.uvmexp {
|
|||||||
free int
|
free int
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free_memory_impl() usize {
|
fn free_memory_impl() !usize {
|
||||||
$if cross ? {
|
$if cross ? {
|
||||||
return 1
|
return error('free_memory: not implemented')
|
||||||
}
|
}
|
||||||
$if !cross ? {
|
$if !cross ? {
|
||||||
$if openbsd {
|
$if openbsd {
|
||||||
mib := [C.CTL_VM, C.VM_UVMEXP]!
|
mib := [C.CTL_VM, C.VM_UVMEXP]!
|
||||||
mut uvm := C.uvmexp{0, 0}
|
mut uvm := C.uvmexp{0, 0}
|
||||||
mut len := sizeof(C.uvmexp)
|
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 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.
|
// 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))
|
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))
|
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
|
return page_size * phys_pages
|
||||||
}
|
}
|
||||||
|
|
||||||
// free_memory returns free physical memory found on the system.
|
// free_memory returns free physical memory found on the system.
|
||||||
// Note: implementation available only on Darwin, FreeBSD, Linux, OpenBSD and
|
// Note: implementation available only on Darwin, FreeBSD, Linux, OpenBSD and
|
||||||
// Windows. Otherwise, returns 1.
|
// Windows. Otherwise, returns 'free_memory: not implemented'.
|
||||||
pub fn free_memory() usize {
|
pub fn free_memory() !usize {
|
||||||
return free_memory_impl()
|
return free_memory_impl()!
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
import runtime
|
import runtime
|
||||||
|
|
||||||
fn test_physical_memory() {
|
fn test_physical_memory() {
|
||||||
total := runtime.total_memory()
|
$if windows || linux || darwin || freebsd || openbsd {
|
||||||
free := runtime.free_memory()
|
total := runtime.total_memory()!
|
||||||
println('total memory: ${total}')
|
free := runtime.free_memory()!
|
||||||
println('free memory: ${free}')
|
println('total memory: ${total}')
|
||||||
assert total > 0 && free > 0
|
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() {
|
fn test_nr_cpus() {
|
||||||
|
@ -23,14 +23,14 @@ pub fn nr_cpus() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// total_memory returns total physical memory found on the system.
|
// total_memory returns total physical memory found on the system.
|
||||||
pub fn total_memory() usize {
|
pub fn total_memory() !usize {
|
||||||
memory_status := C.MEMORYSTATUS{}
|
memory_status := C.MEMORYSTATUS{}
|
||||||
C.GlobalMemoryStatus(&memory_status)
|
C.GlobalMemoryStatus(&memory_status)
|
||||||
return memory_status.dwTotalPhys
|
return memory_status.dwTotalPhys
|
||||||
}
|
}
|
||||||
|
|
||||||
// free_memory returns free physical memory found on the system.
|
// free_memory returns free physical memory found on the system.
|
||||||
pub fn free_memory() usize {
|
pub fn free_memory() !usize {
|
||||||
memory_status := C.MEMORYSTATUS{}
|
memory_status := C.MEMORYSTATUS{}
|
||||||
C.GlobalMemoryStatus(&memory_status)
|
C.GlobalMemoryStatus(&memory_status)
|
||||||
return memory_status.dwAvailPhys
|
return memory_status.dwAvailPhys
|
||||||
|
Loading…
x
Reference in New Issue
Block a user