1
1
/*
2
- * Copyright © 2009-2022 Inria. All rights reserved.
2
+ * Copyright © 2009-2023 Inria. All rights reserved.
3
3
* Copyright © 2009-2012 Université Bordeaux
4
4
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
5
5
* See COPYING in top-level directory.
@@ -35,18 +35,21 @@ static int logical = 1;
35
35
static int single_ancestor = 0 ;
36
36
#define NO_ONLY_PID -1
37
37
static long only_pid = NO_ONLY_PID ;
38
+ static long children_of_pid = NO_ONLY_PID ;
38
39
static long only_uid ;
39
40
static int json_server = 0 ;
40
41
static int json_port = JSON_PORT ;
41
42
static FILE * json_output = NULL ;
42
43
static int verbose = 0 ;
44
+ static FILE * lstopo_misc_output = NULL ;
43
45
44
46
void usage (const char * name , FILE * where )
45
47
{
46
48
fprintf (where , "Usage: %s [ options ] ...\n" , name );
47
49
fprintf (where , "Options:\n" );
48
50
fprintf (where , " -a Show all processes, including those that are not bound\n" );
49
51
fprintf (where , " --pid <pid> Only show process of pid number <pid>\n" );
52
+ fprintf (where , " --children-of-pid <pid> Only show process of pid number <pid> and its children\n" );
50
53
fprintf (where , " --name <name> Only show processes whose name contains <name>\n" );
51
54
#ifdef HWLOC_LINUX_SYS
52
55
fprintf (where , " --uid <uid> Only show processes of the user with the given uid\n" );
@@ -64,6 +67,7 @@ void usage(const char *name, FILE *where)
64
67
fprintf (where , " --pid-cmd <cmd> Append the output of <cmd> <pid> to each PID line\n" );
65
68
fprintf (where , " --short-name Show only the process short name instead of the path\n" );
66
69
fprintf (where , " --disallowed Include objects disallowed by administrative limitations\n" );
70
+ fprintf (where , " --lstopo-misc <file> Output Misc object to be given to lstopo --misc-from <file>\n" );
67
71
fprintf (where , " --json-server Run as a JSON server\n" );
68
72
fprintf (where , " --json-port <n> Use port <n> for JSON server (default is %d)\n" , JSON_PORT );
69
73
fprintf (where , " -v --verbose Increase verbosity\n" );
@@ -133,6 +137,45 @@ static void print_process(hwloc_topology_t topology,
133
137
print_task (topology , proc -> threads [i ].tid , proc -> threads [i ].name , proc -> threads [i ].cpuset , NULL , 1 );
134
138
}
135
139
140
+ static void print_process_lstopo_misc (hwloc_topology_t topology __hwloc_attribute_unused ,
141
+ struct hwloc_ps_process * proc )
142
+ {
143
+ /* sort of similar to foreach_process_cb() in lstopo.c */
144
+ char name [100 ];
145
+ char * s ;
146
+ unsigned i ;
147
+
148
+ snprintf (name , sizeof (name ), "%ld" , proc -> pid );
149
+ if (* proc -> name )
150
+ snprintf (name , sizeof (name ), "%ld %s" , proc -> pid , proc -> name );
151
+ hwloc_bitmap_asprintf (& s , proc -> cpuset );
152
+ fprintf (lstopo_misc_output ,
153
+ "name=%s\n"
154
+ "cpuset=%s\n"
155
+ "subtype=Process\n"
156
+ "\n" ,
157
+ name , s );
158
+ free (s );
159
+
160
+ if (proc -> nthreads )
161
+ for (i = 0 ; i < proc -> nthreads ; i ++ )
162
+ if (proc -> threads [i ].cpuset ) {
163
+ char task_name [150 ];
164
+ if (* proc -> threads [i ].name )
165
+ snprintf (task_name , sizeof (task_name ), "%s %li %s" , name , proc -> threads [i ].tid , proc -> threads [i ].name );
166
+ else
167
+ snprintf (task_name , sizeof (task_name ), "%s %li" , name , proc -> threads [i ].tid );
168
+ hwloc_bitmap_asprintf (& s , proc -> threads [i ].cpuset );
169
+ fprintf (lstopo_misc_output ,
170
+ "name=%s\n"
171
+ "cpuset=%s\n"
172
+ "subtype=Thread\n"
173
+ "\n" ,
174
+ task_name , s );
175
+ free (s );
176
+ }
177
+ }
178
+
136
179
static void print_process_json (hwloc_topology_t topology ,
137
180
struct hwloc_ps_process * proc )
138
181
{
@@ -197,22 +240,28 @@ static void foreach_process_cb(hwloc_topology_t topology,
197
240
const char * pidcmd = cbdata ;
198
241
199
242
/* don't print anything if the process isn't bound and if no threads are bound and if not showing all */
200
- if (!proc -> bound && (!proc -> nthreads || !proc -> nboundthreads ) && !show_all && !only_name )
243
+ if (!proc -> bound && (!proc -> nthreads || !proc -> nboundthreads ) && !show_all && !only_name && children_of_pid == NO_ONLY_PID )
201
244
return ;
202
245
203
246
if (pidcmd )
204
247
hwloc_ps_pidcmd (proc , pidcmd );
205
248
206
249
if (json_output )
207
250
print_process_json (topology , proc );
251
+ else if (lstopo_misc_output )
252
+ print_process_lstopo_misc (topology , proc );
208
253
else
209
254
print_process (topology , proc );
210
255
}
211
256
212
257
static int run (hwloc_topology_t topology , hwloc_const_bitmap_t topocpuset ,
213
258
unsigned long psflags , char * pidcmd )
214
259
{
215
- if (only_pid == NO_ONLY_PID ) {
260
+ if (children_of_pid != NO_ONLY_PID ) {
261
+ /* show children */
262
+ return hwloc_ps_foreach_child (topology , topocpuset , children_of_pid , foreach_process_cb , pidcmd , psflags , only_name , only_uid );
263
+
264
+ } else if (only_pid == NO_ONLY_PID ) {
216
265
/* show all */
217
266
return hwloc_ps_foreach_process (topology , topocpuset , foreach_process_cb , pidcmd , psflags , only_name , only_uid );
218
267
@@ -235,6 +284,8 @@ static int run(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset,
235
284
236
285
if (json_output )
237
286
print_process_json (topology , & proc );
287
+ else if (lstopo_misc_output )
288
+ print_process_lstopo_misc (topology , & proc );
238
289
else
239
290
print_process (topology , & proc );
240
291
}
@@ -317,6 +368,7 @@ run_json_server(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset)
317
368
318
369
only_name = NULL ;
319
370
only_pid = NO_ONLY_PID ;
371
+ children_of_pid = NO_ONLY_PID ;
320
372
current = req ;
321
373
while (* current ) {
322
374
if (!strncmp (current , "lastcpulocation " , 16 )) {
@@ -338,6 +390,10 @@ run_json_server(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset)
338
390
psflags |= HWLOC_PS_FLAG_THREADS ;
339
391
show_all = 1 ;
340
392
break ;
393
+ } else if (!strncmp (current , "childrenofpid=" , 14 )) {
394
+ children_of_pid = atoi (current + 14 );
395
+ show_all = 1 ;
396
+ break ;
341
397
} else if (!strncmp (current , "name=" , 5 )) {
342
398
only_name = current + 5 ;
343
399
show_all = 1 ;
@@ -418,6 +474,13 @@ int main(int argc, char *argv[])
418
474
}
419
475
only_pid = strtol (argv [1 ], NULL , 10 );
420
476
opt = 1 ;
477
+ } else if (!strcmp (argv [0 ], "--children-of-pid" )) {
478
+ if (argc < 2 ) {
479
+ usage (callname , stderr );
480
+ exit (EXIT_FAILURE );
481
+ }
482
+ children_of_pid = strtol (argv [1 ], NULL , 10 );
483
+ opt = 1 ;
421
484
} else if (!strcmp (argv [0 ], "--name" )) {
422
485
if (argc < 2 ) {
423
486
usage (callname , stderr );
@@ -449,6 +512,21 @@ int main(int argc, char *argv[])
449
512
pidcmd = argv [1 ];
450
513
opt = 1 ;
451
514
515
+ } else if (!strcmp (argv [0 ], "--lstopo-misc" )) {
516
+ if (argc < 2 ) {
517
+ usage (callname , stderr );
518
+ exit (EXIT_FAILURE );
519
+ }
520
+ if (!strcmp (argv [1 ], "-" ))
521
+ lstopo_misc_output = stdout ;
522
+ else
523
+ lstopo_misc_output = fopen (argv [1 ], "w" );
524
+ if (!lstopo_misc_output ) {
525
+ fprintf (stderr , "Failed to open --lstopo-misc output `%s' for writing (%s)\n" , argv [1 ], strerror (errno ));
526
+ exit (EXIT_FAILURE );
527
+ }
528
+ opt = 1 ;
529
+
452
530
} else if (!strcmp (argv [0 ], "--json-server" )) {
453
531
json_server = 1 ;
454
532
} else if (!strcmp (argv [0 ], "--json-port" )) {
@@ -522,5 +600,7 @@ int main(int argc, char *argv[])
522
600
out_with_topology :
523
601
hwloc_topology_destroy (topology );
524
602
out :
603
+ if (lstopo_misc_output && lstopo_misc_output != stdout )
604
+ fclose (lstopo_misc_output );
525
605
return err ;
526
606
}
0 commit comments