162306a36Sopenharmony_ci#!/usr/bin/env drgn 262306a36Sopenharmony_ci# 362306a36Sopenharmony_ci# Copyright (C) 2023 Tejun Heo <tj@kernel.org> 462306a36Sopenharmony_ci# Copyright (C) 2023 Meta Platforms, Inc. and affiliates. 562306a36Sopenharmony_ci 662306a36Sopenharmony_cidesc = """ 762306a36Sopenharmony_ciThis is a drgn script to show the current workqueue configuration. For more 862306a36Sopenharmony_ciinfo on drgn, visit https://github.com/osandov/drgn. 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciAffinity Scopes 1162306a36Sopenharmony_ci=============== 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciShows the CPUs that can be used for unbound workqueues and how they will be 1462306a36Sopenharmony_cigrouped by each available affinity type. For each type: 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci nr_pods number of CPU pods in the affinity type 1762306a36Sopenharmony_ci pod_cpus CPUs in each pod 1862306a36Sopenharmony_ci pod_node NUMA node for memory allocation for each pod 1962306a36Sopenharmony_ci cpu_pod pod that each CPU is associated to 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciWorker Pools 2262306a36Sopenharmony_ci============ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciLists all worker pools indexed by their ID. For each pool: 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci ref number of pool_workqueue's associated with this pool 2762306a36Sopenharmony_ci nice nice value of the worker threads in the pool 2862306a36Sopenharmony_ci idle number of idle workers 2962306a36Sopenharmony_ci workers number of all workers 3062306a36Sopenharmony_ci cpu CPU the pool is associated with (per-cpu pool) 3162306a36Sopenharmony_ci cpus CPUs the workers in the pool can run on (unbound pool) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciWorkqueue CPU -> pool 3462306a36Sopenharmony_ci===================== 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciLists all workqueues along with their type and worker pool association. For 3762306a36Sopenharmony_cieach workqueue: 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci NAME TYPE[,FLAGS] POOL_ID... 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci NAME name of the workqueue 4262306a36Sopenharmony_ci TYPE percpu, unbound or ordered 4362306a36Sopenharmony_ci FLAGS S: strict affinity scope 4462306a36Sopenharmony_ci POOL_ID worker pool ID associated with each possible CPU 4562306a36Sopenharmony_ci""" 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciimport sys 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciimport drgn 5062306a36Sopenharmony_cifrom drgn.helpers.linux.list import list_for_each_entry,list_empty 5162306a36Sopenharmony_cifrom drgn.helpers.linux.percpu import per_cpu_ptr 5262306a36Sopenharmony_cifrom drgn.helpers.linux.cpumask import for_each_cpu,for_each_possible_cpu 5362306a36Sopenharmony_cifrom drgn.helpers.linux.idr import idr_for_each 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciimport argparse 5662306a36Sopenharmony_ciparser = argparse.ArgumentParser(description=desc, 5762306a36Sopenharmony_ci formatter_class=argparse.RawTextHelpFormatter) 5862306a36Sopenharmony_ciargs = parser.parse_args() 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cidef err(s): 6162306a36Sopenharmony_ci print(s, file=sys.stderr, flush=True) 6262306a36Sopenharmony_ci sys.exit(1) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cidef cpumask_str(cpumask): 6562306a36Sopenharmony_ci output = "" 6662306a36Sopenharmony_ci base = 0 6762306a36Sopenharmony_ci v = 0 6862306a36Sopenharmony_ci for cpu in for_each_cpu(cpumask[0]): 6962306a36Sopenharmony_ci while cpu - base >= 32: 7062306a36Sopenharmony_ci output += f'{hex(v)} ' 7162306a36Sopenharmony_ci base += 32 7262306a36Sopenharmony_ci v = 0 7362306a36Sopenharmony_ci v |= 1 << (cpu - base) 7462306a36Sopenharmony_ci if v > 0: 7562306a36Sopenharmony_ci output += f'{v:08x}' 7662306a36Sopenharmony_ci return output.strip() 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciworker_pool_idr = prog['worker_pool_idr'] 7962306a36Sopenharmony_ciworkqueues = prog['workqueues'] 8062306a36Sopenharmony_ciwq_unbound_cpumask = prog['wq_unbound_cpumask'] 8162306a36Sopenharmony_ciwq_pod_types = prog['wq_pod_types'] 8262306a36Sopenharmony_ciwq_affn_dfl = prog['wq_affn_dfl'] 8362306a36Sopenharmony_ciwq_affn_names = prog['wq_affn_names'] 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ciWQ_UNBOUND = prog['WQ_UNBOUND'] 8662306a36Sopenharmony_ciWQ_ORDERED = prog['__WQ_ORDERED'] 8762306a36Sopenharmony_ciWQ_MEM_RECLAIM = prog['WQ_MEM_RECLAIM'] 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ciWQ_AFFN_CPU = prog['WQ_AFFN_CPU'] 9062306a36Sopenharmony_ciWQ_AFFN_SMT = prog['WQ_AFFN_SMT'] 9162306a36Sopenharmony_ciWQ_AFFN_CACHE = prog['WQ_AFFN_CACHE'] 9262306a36Sopenharmony_ciWQ_AFFN_NUMA = prog['WQ_AFFN_NUMA'] 9362306a36Sopenharmony_ciWQ_AFFN_SYSTEM = prog['WQ_AFFN_SYSTEM'] 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciprint('Affinity Scopes') 9662306a36Sopenharmony_ciprint('===============') 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciprint(f'wq_unbound_cpumask={cpumask_str(wq_unbound_cpumask)}') 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cidef print_pod_type(pt): 10162306a36Sopenharmony_ci print(f' nr_pods {pt.nr_pods.value_()}') 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci print(' pod_cpus', end='') 10462306a36Sopenharmony_ci for pod in range(pt.nr_pods): 10562306a36Sopenharmony_ci print(f' [{pod}]={cpumask_str(pt.pod_cpus[pod])}', end='') 10662306a36Sopenharmony_ci print('') 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci print(' pod_node', end='') 10962306a36Sopenharmony_ci for pod in range(pt.nr_pods): 11062306a36Sopenharmony_ci print(f' [{pod}]={pt.pod_node[pod].value_()}', end='') 11162306a36Sopenharmony_ci print('') 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci print(f' cpu_pod ', end='') 11462306a36Sopenharmony_ci for cpu in for_each_possible_cpu(prog): 11562306a36Sopenharmony_ci print(f' [{cpu}]={pt.cpu_pod[cpu].value_()}', end='') 11662306a36Sopenharmony_ci print('') 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cifor affn in [WQ_AFFN_CPU, WQ_AFFN_SMT, WQ_AFFN_CACHE, WQ_AFFN_NUMA, WQ_AFFN_SYSTEM]: 11962306a36Sopenharmony_ci print('') 12062306a36Sopenharmony_ci print(f'{wq_affn_names[affn].string_().decode().upper()}{" (default)" if affn == wq_affn_dfl else ""}') 12162306a36Sopenharmony_ci print_pod_type(wq_pod_types[affn]) 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciprint('') 12462306a36Sopenharmony_ciprint('Worker Pools') 12562306a36Sopenharmony_ciprint('============') 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cimax_pool_id_len = 0 12862306a36Sopenharmony_cimax_ref_len = 0 12962306a36Sopenharmony_cifor pi, pool in idr_for_each(worker_pool_idr): 13062306a36Sopenharmony_ci pool = drgn.Object(prog, 'struct worker_pool', address=pool) 13162306a36Sopenharmony_ci max_pool_id_len = max(max_pool_id_len, len(f'{pi}')) 13262306a36Sopenharmony_ci max_ref_len = max(max_ref_len, len(f'{pool.refcnt.value_()}')) 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cifor pi, pool in idr_for_each(worker_pool_idr): 13562306a36Sopenharmony_ci pool = drgn.Object(prog, 'struct worker_pool', address=pool) 13662306a36Sopenharmony_ci print(f'pool[{pi:0{max_pool_id_len}}] ref={pool.refcnt.value_():{max_ref_len}} nice={pool.attrs.nice.value_():3} ', end='') 13762306a36Sopenharmony_ci print(f'idle/workers={pool.nr_idle.value_():3}/{pool.nr_workers.value_():3} ', end='') 13862306a36Sopenharmony_ci if pool.cpu >= 0: 13962306a36Sopenharmony_ci print(f'cpu={pool.cpu.value_():3}', end='') 14062306a36Sopenharmony_ci else: 14162306a36Sopenharmony_ci print(f'cpus={cpumask_str(pool.attrs.cpumask)}', end='') 14262306a36Sopenharmony_ci print(f' pod_cpus={cpumask_str(pool.attrs.__pod_cpumask)}', end='') 14362306a36Sopenharmony_ci if pool.attrs.affn_strict: 14462306a36Sopenharmony_ci print(' strict', end='') 14562306a36Sopenharmony_ci print('') 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ciprint('') 14862306a36Sopenharmony_ciprint('Workqueue CPU -> pool') 14962306a36Sopenharmony_ciprint('=====================') 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciprint('[ workqueue \ type CPU', end='') 15262306a36Sopenharmony_cifor cpu in for_each_possible_cpu(prog): 15362306a36Sopenharmony_ci print(f' {cpu:{max_pool_id_len}}', end='') 15462306a36Sopenharmony_ciprint(' dfl]') 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cifor wq in list_for_each_entry('struct workqueue_struct', workqueues.address_of_(), 'list'): 15762306a36Sopenharmony_ci print(f'{wq.name.string_().decode()[-24:]:24}', end='') 15862306a36Sopenharmony_ci if wq.flags & WQ_UNBOUND: 15962306a36Sopenharmony_ci if wq.flags & WQ_ORDERED: 16062306a36Sopenharmony_ci print(' ordered ', end='') 16162306a36Sopenharmony_ci else: 16262306a36Sopenharmony_ci print(' unbound', end='') 16362306a36Sopenharmony_ci if wq.unbound_attrs.affn_strict: 16462306a36Sopenharmony_ci print(',S ', end='') 16562306a36Sopenharmony_ci else: 16662306a36Sopenharmony_ci print(' ', end='') 16762306a36Sopenharmony_ci else: 16862306a36Sopenharmony_ci print(' percpu ', end='') 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci for cpu in for_each_possible_cpu(prog): 17162306a36Sopenharmony_ci pool_id = per_cpu_ptr(wq.cpu_pwq, cpu)[0].pool.id.value_() 17262306a36Sopenharmony_ci field_len = max(len(str(cpu)), max_pool_id_len) 17362306a36Sopenharmony_ci print(f' {pool_id:{field_len}}', end='') 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci if wq.flags & WQ_UNBOUND: 17662306a36Sopenharmony_ci print(f' {wq.dfl_pwq.pool.id.value_():{max_pool_id_len}}', end='') 17762306a36Sopenharmony_ci print('') 178