code wiki / _hdl_build / nx_sysload.nx

nx_sysload.nx source

↩ module page · 97 lines · 4063 B

1// nx_sysload.nx -- sovereign host-resource readers (/proc) so the governor senses the REAL system it runs 2// on (operator: "without overwhelming this system or any system they are on"). Reads load average, CPU 3// count, and available memory. license_tier: ORIGINAL Feeds nx_resource_governor. 4 5import "nx_syscalls.nx" 6const K_MAGIC_1024: i64 = 1024 7 8// count non-overlapping occurrences of `needle` (len nl) in buf (len n). 9func sl_count_substr(buf: *u8, n: i64, needle: *u8, nl: i64) -> i64 { 10 var c: i64 = 0; var i: i64 = 0 11 while i <= n - nl { 12 var j: i64 = 0; var ok: i64 = 1 13 while j < nl { if buf[i+j] != needle[j] { ok = 0; j = nl } j = j + 1 } 14 if ok == 1 { c = c + 1; i = i + nl } else { i = i + 1 } 15 } 16 return c 17} 18 19// /proc/loadavg first field -> MILLI cores (e.g. "0.52 ..." -> 520). returns -1 on read failure. 20func sl_loadavg_milli() -> i64 { 21 let len: *i64 = sys_mmap(16) as *i64 22 let buf: *u8 = sys_read_file("/proc/loadavg" as *u8, len) 23 if (buf as i64) == 0 { return 0 - 1 } 24 let n: i64 = len[0] 25 var i: i64 = 0; var ip: i64 = 0; var done: i64 = 0 26 while done == 0 { 27 if i >= n { done = 1 } 28 else { let c: i64 = buf[i] as i64 29 if c >= 48 { if c <= 57 { ip = ip*10 + (c - 48); i = i + 1 } else { done = 1 } } else { done = 1 } } 30 } 31 var frac: i64 = 0; var dd: i64 = 0 32 if i < n { if (buf[i] as i64) == 46 { 33 i = i + 1; var fdone: i64 = 0 34 while fdone == 0 { 35 if dd >= 2 { fdone = 1 } 36 else { if i >= n { fdone = 1 } 37 else { let c: i64 = buf[i] as i64 38 if c >= 48 { if c <= 57 { frac = frac*10 + (c - 48); i = i + 1; dd = dd + 1 } else { fdone = 1 } } else { fdone = 1 } } } 39 } 40 } } 41 while dd < 2 { frac = frac * 10; dd = dd + 1 } 42 return ip * 1000 + frac * 10 43} 44 45// CPU count via counting "processor" lines in /proc/cpuinfo (>=1; safe default 1). 46func sl_ncpu() -> i64 { 47 let len: *i64 = sys_mmap(16) as *i64 48 let buf: *u8 = sys_read_file("/proc/cpuinfo" as *u8, len) 49 if (buf as i64) == 0 { return 1 } 50 let c: i64 = sl_count_substr(buf, len[0], "processor" as *u8, 9) 51 if c < 1 { return 1 } 52 return c 53} 54 55// HOSTING-load signal: count ESTABLISHED connections on the hosting port :8443 (0x20FB) from /proc/net/tcp. 56// On a node that is ALSO the hosting platform, this is the signal that the web daemon is actively serving -- 57// the loop must yield to it. /proc/net/tcp uses UPPERCASE hex; ":20FB" is the local port; subtract the 1 58// LISTEN socket. (Conservative: TIME_WAIT/CLOSE_WAIT also count -> we err toward yielding.) returns 0 if idle. 59func sl_active_conns_8443() -> i64 { 60 let len: *i64 = sys_mmap(16) as *i64 61 let buf: *u8 = sys_read_file("/proc/net/tcp" as *u8, len) 62 if (buf as i64) == 0 { return 0 } 63 let c: i64 = sl_count_substr(buf, len[0], ":20FB" as *u8, 5) 64 if c <= 1 { return 0 } 65 return c - 1 66} 67 68// MemAvailable from /proc/meminfo, in MB. returns -1 on failure. 69func sl_freemem_mb() -> i64 { 70 let len: *i64 = sys_mmap(16) as *i64 71 let buf: *u8 = sys_read_file("/proc/meminfo" as *u8, len) 72 if (buf as i64) == 0 { return 0 - 1 } 73 let n: i64 = len[0] 74 // find "MemAvailable:" 75 var i: i64 = 0; var at: i64 = 0 - 1 76 let key: *u8 = "MemAvailable:" as *u8 77 while i <= n - 13 { 78 var j: i64 = 0; var ok: i64 = 1 79 while j < 13 { if buf[i+j] != key[j] { ok = 0; j = 13 } j = j + 1 } 80 if ok == 1 { at = i + 13; i = n } else { i = i + 1 } 81 } 82 if at < 0 { return 0 - 1 } 83 // skip spaces 84 var k: i64 = at; var sdone: i64 = 0 85 while sdone == 0 { 86 if k >= n { sdone = 1 } 87 else { if (buf[k] as i64) == 32 { k = k + 1 } else { sdone = 1 } } 88 } 89 // parse the kB number 90 var kb: i64 = 0; var pdone: i64 = 0 91 while pdone == 0 { 92 if k >= n { pdone = 1 } 93 else { let c: i64 = buf[k] as i64 94 if c >= 48 { if c <= 57 { kb = kb*10 + (c - 48); k = k + 1 } else { pdone = 1 } } else { pdone = 1 } } 95 } 96 return kb / K_MAGIC_1024 97}