nx_game_shader_backend_owned_candidate_t218.nx source
↩ module page · 114 lines · 5295 B
1// One shader-capture owner for normal and explicitly selected staged builds.
2// Digest checks bracket each execution; they detect changed files, not hostile swap-and-restore races.
3import "nx_game_page_artifact_lib.nx"
4import "nx_tool_run.nx"
5const GSB_LIVE: *u8 = "./nx_wgsl.elf"
6const GSB_LIVE_ABS: *u8 = "/volume1/homes/elderwesto/nishihost/nx_wgsl.elf"
7const GSB_STAGED: *u8 = "/volume1/homes/elderwesto/nishihost/nx_wgsl.sov.elf.new"
8static gsb_selected_path: *u8
9static gsb_expected: *u8
10static gsb_failed: i64
11static gsb_expected_bytes: i64
12
13func gsb_artifact_matches(path:*u8,expected:*u8,expected_bytes:i64) -> i64 {
14 if path==(0 as *u8)||expected==(0 as *u8)||expected_bytes<=0 {return 0}
15 if vw_slen(expected)!=GPA_SHA_HEX {return 0}
16 var h:i64=0;while h<GPA_SHA_HEX {if gpa_hex_digit(expected[h] as i64)<0 {return 0};h=h+1}
17 let fd: i64 = sys_openat_rd(path)
18 if fd < 0 { return 0 }
19 let extent: i64 = sys_lseek(fd,0,2)
20 sys_close(fd)
21 if extent != expected_bytes { return 0 }
22 var size: i64 = 0
23 let bytes: *u8 = sys_read_file(path, &size)
24 if (bytes as i64) == 0 { return 0 }
25 var ok: i64 = 0
26 if size == expected_bytes {
27 let digest: *u8 = sys_mmap(GPA_SHA_HEX + 1)
28 gpa_sha(bytes,size,digest)
29 ok = fsx_seq(digest,expected)
30 sys_munmap(digest,GPA_SHA_HEX + 1)
31 }
32 sys_free_file(bytes,size)
33 return ok
34}
35func gsb_matches()->i64 {return gsb_artifact_matches(gsb_selected_path,gsb_expected,gsb_expected_bytes)}
36func gsb_select_at(path: *u8,expected: *u8,expected_bytes: i64) -> i64 {
37 gsb_selected_path = path
38 // A rejected explicit selection must never recover through the live fallback.
39 gsb_failed = 1
40 gsb_expected = 0 as *u8
41 if expected_bytes <= 0 { return 0 }
42 gsb_expected_bytes = expected_bytes
43 if vw_slen(expected) != GPA_SHA_HEX { return 0 }
44 var i: i64 = 0
45 while i < GPA_SHA_HEX {
46 if gpa_hex_digit(expected[i] as i64) < 0 { return 0 }
47 i = i + 1
48 }
49 gsb_expected = expected
50 if gsb_matches() != 1 { return 0 }
51 gsb_failed = 0
52 return 1
53}
54func gsb_once(path: *u8,command: *u8,buf: *u8,cap: i64,ol: *i64,timeout_ms: i64) -> i64 {
55 let argv: *i64 = sys_mmap(24) as *i64
56 argv[0]=path as i64;argv[1]=command as i64;argv[2]=0
57 var truncated: i64 = TR_FIT
58 let rc: i64 = tr_run_capture_tr(path,argv,buf,cap,ol,timeout_ms,&truncated)
59 sys_munmap(argv as *u8,24)
60 if rc != 0 || truncated != TR_FIT { ol[0]=0;return -1 }
61 return 0
62}
63func gsb_capture(command: *u8,buf: *u8,cap: i64,ol: *i64,timeout_ms: i64) -> i64 {
64 ol[0]=0
65 if gsb_failed != 0 { return -1 }
66 if (gsb_expected as i64) != 0 {
67 if gsb_failed != 0 || gsb_matches() != 1 { gsb_failed=1;return -1 }
68 let rc: i64=gsb_once(gsb_selected_path,command,buf,cap,ol,timeout_ms)
69 if rc != 0 || gsb_matches() != 1 { ol[0]=0;gsb_failed=1;return -1 }
70 return 0
71 }
72 var rc: i64=gsb_once(GSB_LIVE,command,buf,cap,ol,timeout_ms)
73 if ol[0] <= 0 { rc=gsb_once(GSB_LIVE_ABS,command,buf,cap,ol,timeout_ms) }
74 return rc
75}
76
77func gsb_capture_selected(path:*u8,expected:*u8,expected_bytes:i64,command:*u8,buf:*u8,cap:i64,ol:*i64,timeout_ms:i64)->i64 {
78 ol[0]=0
79 if gsb_failed!=0 {return -1}
80 if gsb_artifact_matches(path,expected,expected_bytes)!=1 {gsb_failed=1;return -1}
81 let rc:i64=gsb_once(path,command,buf,cap,ol,timeout_ms)
82 if rc!=0||ol[0]<=0||gsb_artifact_matches(path,expected,expected_bytes)!=1 {ol[0]=0;gsb_failed=1;return -1}
83 return 0
84}
85
86func gsb_select(expected:*u8,expected_bytes:i64)->i64 {return gsb_select_at(GSB_STAGED,expected,expected_bytes)}
87
88// Owned-size capture is additive: retained fixed-buffer callers keep their bounded contract.
89// Source identity checks still bracket exactly one producer invocation.
90func gsb_once_owned(path:*u8,command:*u8,owned:*NxBufOwned,timeout_ms:i64,max_bytes:i64)->i64{
91 let argv:*i64=sys_mmap_try(24) as *i64;if (argv as i64)<=0{return TR_ERR_ALLOC}
92 argv[0]=path as i64;argv[1]=command as i64;argv[2]=0
93 let rc:i64=tr_run_capture_owned(path,argv,owned,timeout_ms,max_bytes,0 as *u8)
94 sys_munmap_direct(argv as *u8,24);return rc
95}
96func gsb_capture_selected_owned(path:*u8,expected:*u8,expected_bytes:i64,command:*u8,owned:*NxBufOwned,timeout_ms:i64,max_bytes:i64)->i64{
97 if (owned as i64)<=0{return TR_ERR_DRAIN}
98 if gsb_failed!=0{return -1}
99 if gsb_artifact_matches(path,expected,expected_bytes)!=1{gsb_failed=1;return -1}
100 let rc:i64=gsb_once_owned(path,command,owned,timeout_ms,max_bytes)
101 if rc!=0||owned.len<=0||gsb_artifact_matches(path,expected,expected_bytes)!=1{
102 gsb_failed=1;if rc!=0{return rc};return -1
103 };return 0
104}
105func gsb_capture_owned(command:*u8,owned:*NxBufOwned,timeout_ms:i64,max_bytes:i64)->i64{
106 if (owned as i64)<=0{return TR_ERR_DRAIN};if gsb_failed!=0{return -1}
107 if (gsb_expected as i64)!=0{return gsb_capture_selected_owned(gsb_selected_path,gsb_expected,gsb_expected_bytes,command,owned,timeout_ms,max_bytes)}
108 // Resolve the known relative/absolute location before execution, never by rerunning an exit127.
109 let fd:i64=sys_openat_rd(GSB_LIVE)
110 if fd==0-2{return gsb_once_owned(GSB_LIVE_ABS,command,owned,timeout_ms,max_bytes)}
111 if fd<0{return TR_ERR_DRAIN}
112 sys_close(fd)
113 return gsb_once_owned(GSB_LIVE,command,owned,timeout_ms,max_bytes)
114}