v/vlib/v/tests/keep_args_alive_test.v

77 lines
1.7 KiB
V

// vtest retry: 4
/*
* To verify the effect of "[keep_args_alive]", this attribute may be commented out.
* However it is not guaranteed that then this test will fail.
* To provoke a failure it seems to be best to use `gcc` with optimization:
* `gcc -gc boehm -cc gcc-9 -prod test keep_args_alive_test.v`.
* Without optimization, pointer variables may remain on the stack even if
* not used any more.
*/
import rand
import sync
#flag -I@VEXEROOT/vlib/v/tests
#include "keep_args_alive_test_c.h"
fn C.atomic_load_ptr(voidptr) voidptr
fn C.atomic_store_ptr(voidptr, voidptr)
[keep_args_alive]
fn C.calc_expr_after_delay(voidptr, int, voidptr) int
fn set_vals() voidptr {
unsafe {
p := &int(malloc(8000000))
q := &int(malloc(8000000))
aa := p + 769345
*aa = -4578
bb := q + 572397
*bb = 793254
p = &int(0)
q = &int(0)
r := &voidptr(malloc(1000000))
r[456] = aa
r[7932] = bb
aa = &int(0)
bb = &int(0)
return r
}
}
fn tt(mut sem sync.Semaphore) int {
waste_mem(10000, mut sem)
r := &voidptr(set_vals())
g := unsafe { C.calc_expr_after_delay(r[456], 12, r[7932]) }
return g
}
fn waste_mem(n int, mut sem sync.Semaphore) {
mut m := []voidptr{len: 30}
for j := 0; n < 0 || j < n; j++ {
i := rand.intn(30) or { 0 }
m[i] = unsafe { malloc(10000) }
fill := rand.intn(256) or { 0 }
unsafe { C.memset(m[i], fill, 10000) }
if n < 0 && sem.try_wait() {
break
}
}
}
fn test_keep_args_alive_attribute() {
mut sem := sync.new_semaphore()
$if gcboehm ? {
go waste_mem(-1, mut sem)
go waste_mem(-1, mut sem)
waste_mem(10000, mut sem)
}
r := &voidptr(set_vals())
v := unsafe { C.calc_expr_after_delay(r[456], 12, r[7932]) }
$if gcboehm ? {
sem.post()
sem.post()
}
assert v == 738318
}