1*99cea7ebSRuslan Valiyev#!/usr/bin/env python3 2*99cea7ebSRuslan Valiyev# SPDX-License-Identifier: GPL-2.0 3*99cea7ebSRuslan Valiyev 4*99cea7ebSRuslan Valiyevimport os 5*99cea7ebSRuslan Valiyevimport subprocess 6*99cea7ebSRuslan Valiyevimport time 7*99cea7ebSRuslan Valiyev 8*99cea7ebSRuslan Valiyevimport _damon_sysfs 9*99cea7ebSRuslan Valiyev 10*99cea7ebSRuslan Valiyevdef main(): 11*99cea7ebSRuslan Valiyev # Continuously access a memory region for far longer than the test needs, 12*99cea7ebSRuslan Valiyev # so the kdamond always has a live target to monitor while we poll. 13*99cea7ebSRuslan Valiyev sz_region = 10 * 1024 * 1024 14*99cea7ebSRuslan Valiyev proc = subprocess.Popen( 15*99cea7ebSRuslan Valiyev ['./access_memory', '1', '%d' % sz_region, '60000', 'repeat']) 16*99cea7ebSRuslan Valiyev 17*99cea7ebSRuslan Valiyev # A 'stat' scheme with the default (maximally wide) access pattern matches 18*99cea7ebSRuslan Valiyev # every monitored region, so its 'nr_tried' stat increases as the kdamond 19*99cea7ebSRuslan Valiyev # runs. refresh_ms should make DAMON update the schemes' stats files under 20*99cea7ebSRuslan Valiyev # sysfs on its own, without a manual 'update_schemes_stats' request. 21*99cea7ebSRuslan Valiyev kdamond = _damon_sysfs.Kdamond( 22*99cea7ebSRuslan Valiyev refresh_ms=100, 23*99cea7ebSRuslan Valiyev contexts=[_damon_sysfs.DamonCtx( 24*99cea7ebSRuslan Valiyev ops='vaddr', 25*99cea7ebSRuslan Valiyev targets=[_damon_sysfs.DamonTarget(pid=proc.pid)], 26*99cea7ebSRuslan Valiyev schemes=[_damon_sysfs.Damos(action='stat')], 27*99cea7ebSRuslan Valiyev )]) 28*99cea7ebSRuslan Valiyev kdamonds = _damon_sysfs.Kdamonds([kdamond]) 29*99cea7ebSRuslan Valiyev 30*99cea7ebSRuslan Valiyev err = kdamonds.start() 31*99cea7ebSRuslan Valiyev if err is not None: 32*99cea7ebSRuslan Valiyev # Kernels older than the refresh_ms feature have no such file; treat 33*99cea7ebSRuslan Valiyev # that as unsupported rather than a failure. 34*99cea7ebSRuslan Valiyev if not os.path.exists(os.path.join(kdamond.sysfs_dir(), 'refresh_ms')): 35*99cea7ebSRuslan Valiyev proc.terminate() 36*99cea7ebSRuslan Valiyev proc.wait() 37*99cea7ebSRuslan Valiyev print('kdamond has no refresh_ms file; skipping') 38*99cea7ebSRuslan Valiyev exit(_damon_sysfs.ksft_skip) 39*99cea7ebSRuslan Valiyev proc.terminate() 40*99cea7ebSRuslan Valiyev proc.wait() 41*99cea7ebSRuslan Valiyev print('kdamond start failed: %s' % err) 42*99cea7ebSRuslan Valiyev exit(1) 43*99cea7ebSRuslan Valiyev 44*99cea7ebSRuslan Valiyev scheme = kdamond.contexts[0].schemes[0] 45*99cea7ebSRuslan Valiyev nr_tried_path = os.path.join(scheme.sysfs_dir(), 'stats', 'nr_tried') 46*99cea7ebSRuslan Valiyev 47*99cea7ebSRuslan Valiyev try: 48*99cea7ebSRuslan Valiyev # Poll the stat file directly. We never request an update (e.g. 49*99cea7ebSRuslan Valiyev # 'update_schemes_stats'), so 'nr_tried' can become non-zero only 50*99cea7ebSRuslan Valiyev # through the periodic refresh that refresh_ms enables. 51*99cea7ebSRuslan Valiyev nr_tried = 0 52*99cea7ebSRuslan Valiyev deadline = time.monotonic() + 10 53*99cea7ebSRuslan Valiyev while time.monotonic() < deadline: 54*99cea7ebSRuslan Valiyev if proc.poll() is not None: 55*99cea7ebSRuslan Valiyev print('the access_memory target exited unexpectedly') 56*99cea7ebSRuslan Valiyev exit(1) 57*99cea7ebSRuslan Valiyev content, err = _damon_sysfs.read_file(nr_tried_path) 58*99cea7ebSRuslan Valiyev if err is not None: 59*99cea7ebSRuslan Valiyev print('reading %s failed: %s' % (nr_tried_path, err)) 60*99cea7ebSRuslan Valiyev exit(1) 61*99cea7ebSRuslan Valiyev nr_tried = int(content) 62*99cea7ebSRuslan Valiyev if nr_tried > 0: 63*99cea7ebSRuslan Valiyev break 64*99cea7ebSRuslan Valiyev time.sleep(0.1) 65*99cea7ebSRuslan Valiyev finally: 66*99cea7ebSRuslan Valiyev kdamonds.stop() 67*99cea7ebSRuslan Valiyev proc.terminate() 68*99cea7ebSRuslan Valiyev proc.wait() 69*99cea7ebSRuslan Valiyev 70*99cea7ebSRuslan Valiyev if nr_tried == 0: 71*99cea7ebSRuslan Valiyev print('refresh_ms did not auto-update the schemes stats') 72*99cea7ebSRuslan Valiyev exit(1) 73*99cea7ebSRuslan Valiyev 74*99cea7ebSRuslan Valiyevif __name__ == '__main__': 75*99cea7ebSRuslan Valiyev main() 76