~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/workqueue/wq_dump.py

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/workqueue/wq_dump.py (Architecture sparc64) and /tools/workqueue/wq_dump.py (Architecture m68k)


  1 #!/usr/bin/env drgn                                 1 #!/usr/bin/env drgn
  2 #                                                   2 #
  3 # Copyright (C) 2023 Tejun Heo <tj@kernel.org>       3 # Copyright (C) 2023 Tejun Heo <tj@kernel.org>
  4 # Copyright (C) 2023 Meta Platforms, Inc. and       4 # Copyright (C) 2023 Meta Platforms, Inc. and affiliates.
  5                                                     5 
  6 desc = """                                          6 desc = """
  7 This is a drgn script to show the current work      7 This is a drgn script to show the current workqueue configuration. For more
  8 info on drgn, visit https://github.com/osandov      8 info on drgn, visit https://github.com/osandov/drgn.
  9                                                     9 
 10 Affinity Scopes                                    10 Affinity Scopes
 11 ===============                                    11 ===============
 12                                                    12 
 13 Shows the CPUs that can be used for unbound wo     13 Shows the CPUs that can be used for unbound workqueues and how they will be
 14 grouped by each available affinity type. For e     14 grouped by each available affinity type. For each type:
 15                                                    15 
 16   nr_pods   number of CPU pods in the affinity     16   nr_pods   number of CPU pods in the affinity type
 17   pod_cpus  CPUs in each pod                       17   pod_cpus  CPUs in each pod
 18   pod_node  NUMA node for memory allocation fo     18   pod_node  NUMA node for memory allocation for each pod
 19   cpu_pod   pod that each CPU is associated to     19   cpu_pod   pod that each CPU is associated to
 20                                                    20 
 21 Worker Pools                                       21 Worker Pools
 22 ============                                       22 ============
 23                                                    23 
 24 Lists all worker pools indexed by their ID. Fo     24 Lists all worker pools indexed by their ID. For each pool:
 25                                                    25 
 26   ref       number of pool_workqueue's associa     26   ref       number of pool_workqueue's associated with this pool
 27   nice      nice value of the worker threads i     27   nice      nice value of the worker threads in the pool
 28   idle      number of idle workers                 28   idle      number of idle workers
 29   workers   number of all workers                  29   workers   number of all workers
 30   cpu       CPU the pool is associated with (p     30   cpu       CPU the pool is associated with (per-cpu pool)
 31   cpus      CPUs the workers in the pool can r     31   cpus      CPUs the workers in the pool can run on (unbound pool)
 32                                                    32 
 33 Workqueue CPU -> pool                              33 Workqueue CPU -> pool
 34 =====================                              34 =====================
 35                                                    35 
 36 Lists all workqueues along with their type and     36 Lists all workqueues along with their type and worker pool association. For
 37 each workqueue:                                    37 each workqueue:
 38                                                    38 
 39   NAME TYPE[,FLAGS] POOL_ID...                     39   NAME TYPE[,FLAGS] POOL_ID...
 40                                                    40 
 41   NAME      name of the workqueue                  41   NAME      name of the workqueue
 42   TYPE      percpu, unbound or ordered             42   TYPE      percpu, unbound or ordered
 43   FLAGS     S: strict affinity scope               43   FLAGS     S: strict affinity scope
 44   POOL_ID   worker pool ID associated with eac     44   POOL_ID   worker pool ID associated with each possible CPU
 45 """                                                45 """
 46                                                    46 
 47 import sys                                         47 import sys
 48                                                    48 
 49 import drgn                                        49 import drgn
 50 from drgn.helpers.linux.list import list_for_e     50 from drgn.helpers.linux.list import list_for_each_entry,list_empty
 51 from drgn.helpers.linux.percpu import per_cpu_     51 from drgn.helpers.linux.percpu import per_cpu_ptr
 52 from drgn.helpers.linux.cpumask import for_eac     52 from drgn.helpers.linux.cpumask import for_each_cpu,for_each_possible_cpu
 53 from drgn.helpers.linux.nodemask import for_ea     53 from drgn.helpers.linux.nodemask import for_each_node
 54 from drgn.helpers.linux.idr import idr_for_eac     54 from drgn.helpers.linux.idr import idr_for_each
 55                                                    55 
 56 import argparse                                    56 import argparse
 57 parser = argparse.ArgumentParser(description=d     57 parser = argparse.ArgumentParser(description=desc,
 58                                  formatter_cla     58                                  formatter_class=argparse.RawTextHelpFormatter)
 59 args = parser.parse_args()                         59 args = parser.parse_args()
 60                                                    60 
 61 def err(s):                                        61 def err(s):
 62     print(s, file=sys.stderr, flush=True)          62     print(s, file=sys.stderr, flush=True)
 63     sys.exit(1)                                    63     sys.exit(1)
 64                                                    64 
 65 def cpumask_str(cpumask):                          65 def cpumask_str(cpumask):
 66     output = ""                                    66     output = ""
 67     base = 0                                       67     base = 0
 68     v = 0                                          68     v = 0
 69     for cpu in for_each_cpu(cpumask[0]):           69     for cpu in for_each_cpu(cpumask[0]):
 70         while cpu - base >= 32:                    70         while cpu - base >= 32:
 71             output += f'{hex(v)} '                 71             output += f'{hex(v)} '
 72             base += 32                             72             base += 32
 73             v = 0                                  73             v = 0
 74         v |= 1 << (cpu - base)                     74         v |= 1 << (cpu - base)
 75     if v > 0:                                      75     if v > 0:
 76         output += f'{v:08x}'                       76         output += f'{v:08x}'
 77     return output.strip()                          77     return output.strip()
 78                                                    78 
 79 wq_type_len = 9                                    79 wq_type_len = 9
 80                                                    80 
 81 def wq_type_str(wq):                               81 def wq_type_str(wq):
 82     if wq.flags & WQ_BH:                           82     if wq.flags & WQ_BH:
 83         return f'{"bh":{wq_type_len}}'             83         return f'{"bh":{wq_type_len}}'
 84     elif wq.flags & WQ_UNBOUND:                    84     elif wq.flags & WQ_UNBOUND:
 85         if wq.flags & WQ_ORDERED:                  85         if wq.flags & WQ_ORDERED:
 86             return f'{"ordered":{wq_type_len}}     86             return f'{"ordered":{wq_type_len}}'
 87         else:                                      87         else:
 88             if wq.unbound_attrs.affn_strict:       88             if wq.unbound_attrs.affn_strict:
 89                 return f'{"unbound,S":{wq_type     89                 return f'{"unbound,S":{wq_type_len}}'
 90             else:                                  90             else:
 91                 return f'{"unbound":{wq_type_l     91                 return f'{"unbound":{wq_type_len}}'
 92     else:                                          92     else:
 93         return f'{"percpu":{wq_type_len}}'         93         return f'{"percpu":{wq_type_len}}'
 94                                                    94 
 95 worker_pool_idr         = prog['worker_pool_id     95 worker_pool_idr         = prog['worker_pool_idr']
 96 workqueues              = prog['workqueues']       96 workqueues              = prog['workqueues']
 97 wq_unbound_cpumask      = prog['wq_unbound_cpu     97 wq_unbound_cpumask      = prog['wq_unbound_cpumask']
 98 wq_pod_types            = prog['wq_pod_types']     98 wq_pod_types            = prog['wq_pod_types']
 99 wq_affn_dfl             = prog['wq_affn_dfl']      99 wq_affn_dfl             = prog['wq_affn_dfl']
100 wq_affn_names           = prog['wq_affn_names'    100 wq_affn_names           = prog['wq_affn_names']
101                                                   101 
102 WQ_BH                   = prog['WQ_BH']           102 WQ_BH                   = prog['WQ_BH']
103 WQ_UNBOUND              = prog['WQ_UNBOUND']      103 WQ_UNBOUND              = prog['WQ_UNBOUND']
104 WQ_ORDERED              = prog['__WQ_ORDERED']    104 WQ_ORDERED              = prog['__WQ_ORDERED']
105 WQ_MEM_RECLAIM          = prog['WQ_MEM_RECLAIM    105 WQ_MEM_RECLAIM          = prog['WQ_MEM_RECLAIM']
106                                                   106 
107 WQ_AFFN_CPU             = prog['WQ_AFFN_CPU']     107 WQ_AFFN_CPU             = prog['WQ_AFFN_CPU']
108 WQ_AFFN_SMT             = prog['WQ_AFFN_SMT']     108 WQ_AFFN_SMT             = prog['WQ_AFFN_SMT']
109 WQ_AFFN_CACHE           = prog['WQ_AFFN_CACHE'    109 WQ_AFFN_CACHE           = prog['WQ_AFFN_CACHE']
110 WQ_AFFN_NUMA            = prog['WQ_AFFN_NUMA']    110 WQ_AFFN_NUMA            = prog['WQ_AFFN_NUMA']
111 WQ_AFFN_SYSTEM          = prog['WQ_AFFN_SYSTEM    111 WQ_AFFN_SYSTEM          = prog['WQ_AFFN_SYSTEM']
112                                                   112 
113 POOL_BH                 = prog['POOL_BH']         113 POOL_BH                 = prog['POOL_BH']
114                                                   114 
115 WQ_NAME_LEN             = prog['WQ_NAME_LEN'].    115 WQ_NAME_LEN             = prog['WQ_NAME_LEN'].value_()
116 cpumask_str_len         = len(cpumask_str(wq_u    116 cpumask_str_len         = len(cpumask_str(wq_unbound_cpumask))
117                                                   117 
118 print('Affinity Scopes')                          118 print('Affinity Scopes')
119 print('===============')                          119 print('===============')
120                                                   120 
121 print(f'wq_unbound_cpumask={cpumask_str(wq_unb    121 print(f'wq_unbound_cpumask={cpumask_str(wq_unbound_cpumask)}')
122                                                   122 
123 def print_pod_type(pt):                           123 def print_pod_type(pt):
124     print(f'  nr_pods  {pt.nr_pods.value_()}')    124     print(f'  nr_pods  {pt.nr_pods.value_()}')
125                                                   125 
126     print('  pod_cpus', end='')                   126     print('  pod_cpus', end='')
127     for pod in range(pt.nr_pods):                 127     for pod in range(pt.nr_pods):
128         print(f' [{pod}]={cpumask_str(pt.pod_c    128         print(f' [{pod}]={cpumask_str(pt.pod_cpus[pod])}', end='')
129     print('')                                     129     print('')
130                                                   130 
131     print('  pod_node', end='')                   131     print('  pod_node', end='')
132     for pod in range(pt.nr_pods):                 132     for pod in range(pt.nr_pods):
133         print(f' [{pod}]={pt.pod_node[pod].val    133         print(f' [{pod}]={pt.pod_node[pod].value_()}', end='')
134     print('')                                     134     print('')
135                                                   135 
136     print(f'  cpu_pod ', end='')                  136     print(f'  cpu_pod ', end='')
137     for cpu in for_each_possible_cpu(prog):       137     for cpu in for_each_possible_cpu(prog):
138         print(f' [{cpu}]={pt.cpu_pod[cpu].valu    138         print(f' [{cpu}]={pt.cpu_pod[cpu].value_()}', end='')
139     print('')                                     139     print('')
140                                                   140 
141 for affn in [WQ_AFFN_CPU, WQ_AFFN_SMT, WQ_AFFN    141 for affn in [WQ_AFFN_CPU, WQ_AFFN_SMT, WQ_AFFN_CACHE, WQ_AFFN_NUMA, WQ_AFFN_SYSTEM]:
142     print('')                                     142     print('')
143     print(f'{wq_affn_names[affn].string_().dec    143     print(f'{wq_affn_names[affn].string_().decode().upper()}{" (default)" if affn == wq_affn_dfl else ""}')
144     print_pod_type(wq_pod_types[affn])            144     print_pod_type(wq_pod_types[affn])
145                                                   145 
146 print('')                                         146 print('')
147 print('Worker Pools')                             147 print('Worker Pools')
148 print('============')                             148 print('============')
149                                                   149 
150 max_pool_id_len = 0                               150 max_pool_id_len = 0
151 max_ref_len = 0                                   151 max_ref_len = 0
152 for pi, pool in idr_for_each(worker_pool_idr):    152 for pi, pool in idr_for_each(worker_pool_idr):
153     pool = drgn.Object(prog, 'struct worker_po    153     pool = drgn.Object(prog, 'struct worker_pool', address=pool)
154     max_pool_id_len = max(max_pool_id_len, len    154     max_pool_id_len = max(max_pool_id_len, len(f'{pi}'))
155     max_ref_len = max(max_ref_len, len(f'{pool    155     max_ref_len = max(max_ref_len, len(f'{pool.refcnt.value_()}'))
156                                                   156 
157 for pi, pool in idr_for_each(worker_pool_idr):    157 for pi, pool in idr_for_each(worker_pool_idr):
158     pool = drgn.Object(prog, 'struct worker_po    158     pool = drgn.Object(prog, 'struct worker_pool', address=pool)
159     print(f'pool[{pi:0{max_pool_id_len}}] flag    159     print(f'pool[{pi:0{max_pool_id_len}}] flags=0x{pool.flags.value_():02x} ref={pool.refcnt.value_():{max_ref_len}} nice={pool.attrs.nice.value_():3} ', end='')
160     print(f'idle/workers={pool.nr_idle.value_(    160     print(f'idle/workers={pool.nr_idle.value_():3}/{pool.nr_workers.value_():3} ', end='')
161     if pool.cpu >= 0:                             161     if pool.cpu >= 0:
162         print(f'cpu={pool.cpu.value_():3}', en    162         print(f'cpu={pool.cpu.value_():3}', end='')
163         if pool.flags & POOL_BH:                  163         if pool.flags & POOL_BH:
164             print(' bh', end='')                  164             print(' bh', end='')
165     else:                                         165     else:
166         print(f'cpus={cpumask_str(pool.attrs.c    166         print(f'cpus={cpumask_str(pool.attrs.cpumask)}', end='')
167         print(f' pod_cpus={cpumask_str(pool.at    167         print(f' pod_cpus={cpumask_str(pool.attrs.__pod_cpumask)}', end='')
168         if pool.attrs.affn_strict:                168         if pool.attrs.affn_strict:
169             print(' strict', end='')              169             print(' strict', end='')
170     print('')                                     170     print('')
171                                                   171 
172 print('')                                         172 print('')
173 print('Workqueue CPU -> pool')                    173 print('Workqueue CPU -> pool')
174 print('=====================')                    174 print('=====================')
175                                                   175 
176 print(f'[{"workqueue":^{WQ_NAME_LEN-2}}\\ {"ty    176 print(f'[{"workqueue":^{WQ_NAME_LEN-2}}\\ {"type   CPU":{wq_type_len}}', end='')
177 for cpu in for_each_possible_cpu(prog):           177 for cpu in for_each_possible_cpu(prog):
178     print(f' {cpu:{max_pool_id_len}}', end='')    178     print(f' {cpu:{max_pool_id_len}}', end='')
179 print(' dfl]')                                    179 print(' dfl]')
180                                                   180 
181 for wq in list_for_each_entry('struct workqueu    181 for wq in list_for_each_entry('struct workqueue_struct', workqueues.address_of_(), 'list'):
182     print(f'{wq.name.string_().decode():{WQ_NA    182     print(f'{wq.name.string_().decode():{WQ_NAME_LEN}} {wq_type_str(wq):10}', end='')
183                                                   183 
184     for cpu in for_each_possible_cpu(prog):       184     for cpu in for_each_possible_cpu(prog):
185         pool_id = per_cpu_ptr(wq.cpu_pwq, cpu)    185         pool_id = per_cpu_ptr(wq.cpu_pwq, cpu)[0].pool.id.value_()
186         field_len = max(len(str(cpu)), max_poo    186         field_len = max(len(str(cpu)), max_pool_id_len)
187         print(f' {pool_id:{field_len}}', end='    187         print(f' {pool_id:{field_len}}', end='')
188                                                   188 
189     if wq.flags & WQ_UNBOUND:                     189     if wq.flags & WQ_UNBOUND:
190         print(f' {wq.dfl_pwq.pool.id.value_():    190         print(f' {wq.dfl_pwq.pool.id.value_():{max_pool_id_len}}', end='')
191     print('')                                     191     print('')
192                                                   192 
193 print('')                                         193 print('')
194 print('Workqueue -> rescuer')                     194 print('Workqueue -> rescuer')
195 print('====================')                     195 print('====================')
196                                                   196 
197 ucpus_len = max(cpumask_str_len, len("unbound_    197 ucpus_len = max(cpumask_str_len, len("unbound_cpus"))
198 rcpus_len = max(cpumask_str_len, len("rescuer_    198 rcpus_len = max(cpumask_str_len, len("rescuer_cpus"))
199                                                   199 
200 print(f'[{"workqueue":^{WQ_NAME_LEN-2}}\\ {"un    200 print(f'[{"workqueue":^{WQ_NAME_LEN-2}}\\ {"unbound_cpus":{ucpus_len}}    pid {"rescuer_cpus":{rcpus_len}} ]')
201                                                   201 
202 for wq in list_for_each_entry('struct workqueu    202 for wq in list_for_each_entry('struct workqueue_struct', workqueues.address_of_(), 'list'):
203     if not (wq.flags & WQ_MEM_RECLAIM):           203     if not (wq.flags & WQ_MEM_RECLAIM):
204         continue                                  204         continue
205                                                   205 
206     print(f'{wq.name.string_().decode():{WQ_NA    206     print(f'{wq.name.string_().decode():{WQ_NAME_LEN}}', end='')
207     if wq.unbound_attrs.value_() != 0:            207     if wq.unbound_attrs.value_() != 0:
208         print(f' {cpumask_str(wq.unbound_attrs    208         print(f' {cpumask_str(wq.unbound_attrs.cpumask):{ucpus_len}}', end='')
209     else:                                         209     else:
210         print(f' {"":{ucpus_len}}', end='')       210         print(f' {"":{ucpus_len}}', end='')
211                                                   211 
212     print(f' {wq.rescuer.task.pid.value_():6}'    212     print(f' {wq.rescuer.task.pid.value_():6}', end='')
213     print(f' {cpumask_str(wq.rescuer.task.cpus    213     print(f' {cpumask_str(wq.rescuer.task.cpus_ptr):{rcpus_len}}', end='')
214     print('')                                     214     print('')
215                                                   215 
216 print('')                                         216 print('')
217 print('Unbound workqueue -> node_nr/max_active    217 print('Unbound workqueue -> node_nr/max_active')
218 print('=======================================    218 print('=======================================')
219                                                   219 
220 if 'node_to_cpumask_map' in prog:                 220 if 'node_to_cpumask_map' in prog:
221     __cpu_online_mask = prog['__cpu_online_mas    221     __cpu_online_mask = prog['__cpu_online_mask']
222     node_to_cpumask_map = prog['node_to_cpumas    222     node_to_cpumask_map = prog['node_to_cpumask_map']
223     nr_node_ids = prog['nr_node_ids'].value_()    223     nr_node_ids = prog['nr_node_ids'].value_()
224                                                   224 
225     print(f'online_cpus={cpumask_str(__cpu_onl    225     print(f'online_cpus={cpumask_str(__cpu_online_mask.address_of_())}')
226     for node in for_each_node():                  226     for node in for_each_node():
227         print(f'NODE[{node:02}]={cpumask_str(n    227         print(f'NODE[{node:02}]={cpumask_str(node_to_cpumask_map[node])}')
228     print('')                                     228     print('')
229                                                   229 
230     print(f'[{"workqueue":^{WQ_NAME_LEN-2}}\\     230     print(f'[{"workqueue":^{WQ_NAME_LEN-2}}\\ min max', end='')
231     first = True                                  231     first = True
232     for node in for_each_node():                  232     for node in for_each_node():
233         if first:                                 233         if first:
234             print(f'  NODE {node}', end='')       234             print(f'  NODE {node}', end='')
235             first = False                         235             first = False
236         else:                                     236         else:
237             print(f' {node:7}', end='')           237             print(f' {node:7}', end='')
238     print(f' {"dfl":>7} ]')                       238     print(f' {"dfl":>7} ]')
239     print('')                                     239     print('')
240                                                   240 
241     for wq in list_for_each_entry('struct work    241     for wq in list_for_each_entry('struct workqueue_struct', workqueues.address_of_(), 'list'):
242         if not (wq.flags & WQ_UNBOUND):           242         if not (wq.flags & WQ_UNBOUND):
243             continue                              243             continue
244                                                   244 
245         print(f'{wq.name.string_().decode():{W    245         print(f'{wq.name.string_().decode():{WQ_NAME_LEN}} ', end='')
246         print(f'{wq.min_active.value_():3} {wq    246         print(f'{wq.min_active.value_():3} {wq.max_active.value_():3}', end='')
247         for node in for_each_node():              247         for node in for_each_node():
248             nna = wq.node_nr_active[node]         248             nna = wq.node_nr_active[node]
249             print(f' {nna.nr.counter.value_():    249             print(f' {nna.nr.counter.value_():3}/{nna.max.value_():3}', end='')
250         nna = wq.node_nr_active[nr_node_ids]      250         nna = wq.node_nr_active[nr_node_ids]
251         print(f' {nna.nr.counter.value_():3}/{    251         print(f' {nna.nr.counter.value_():3}/{nna.max.value_():3}')
252 else:                                             252 else:
253     printf(f'node_to_cpumask_map not present,     253     printf(f'node_to_cpumask_map not present, is NUMA enabled?')
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php