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}