11/*
2- * Copyright © 2009-2022 Inria. All rights reserved.
2+ * Copyright © 2009-2023 Inria. All rights reserved.
33 * Copyright © 2009-2012 Université Bordeaux
44 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
55 * See COPYING in top-level directory.
@@ -35,18 +35,21 @@ static int logical = 1;
3535static int single_ancestor = 0 ;
3636#define NO_ONLY_PID -1
3737static long only_pid = NO_ONLY_PID ;
38+ static long children_of_pid = NO_ONLY_PID ;
3839static long only_uid ;
3940static int json_server = 0 ;
4041static int json_port = JSON_PORT ;
4142static FILE * json_output = NULL ;
4243static int verbose = 0 ;
44+ static FILE * lstopo_misc_output = NULL ;
4345
4446void usage (const char * name , FILE * where )
4547{
4648 fprintf (where , "Usage: %s [ options ] ...\n" , name );
4749 fprintf (where , "Options:\n" );
4850 fprintf (where , " -a Show all processes, including those that are not bound\n" );
4951 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" );
5053 fprintf (where , " --name <name> Only show processes whose name contains <name>\n" );
5154#ifdef HWLOC_LINUX_SYS
5255 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)
6467 fprintf (where , " --pid-cmd <cmd> Append the output of <cmd> <pid> to each PID line\n" );
6568 fprintf (where , " --short-name Show only the process short name instead of the path\n" );
6669 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" );
6771 fprintf (where , " --json-server Run as a JSON server\n" );
6872 fprintf (where , " --json-port <n> Use port <n> for JSON server (default is %d)\n" , JSON_PORT );
6973 fprintf (where , " -v --verbose Increase verbosity\n" );
@@ -133,6 +137,45 @@ static void print_process(hwloc_topology_t topology,
133137 print_task (topology , proc -> threads [i ].tid , proc -> threads [i ].name , proc -> threads [i ].cpuset , NULL , 1 );
134138}
135139
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+
136179static void print_process_json (hwloc_topology_t topology ,
137180 struct hwloc_ps_process * proc )
138181{
@@ -197,22 +240,28 @@ static void foreach_process_cb(hwloc_topology_t topology,
197240 const char * pidcmd = cbdata ;
198241
199242 /* 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 )
201244 return ;
202245
203246 if (pidcmd )
204247 hwloc_ps_pidcmd (proc , pidcmd );
205248
206249 if (json_output )
207250 print_process_json (topology , proc );
251+ else if (lstopo_misc_output )
252+ print_process_lstopo_misc (topology , proc );
208253 else
209254 print_process (topology , proc );
210255}
211256
212257static int run (hwloc_topology_t topology , hwloc_const_bitmap_t topocpuset ,
213258 unsigned long psflags , char * pidcmd )
214259{
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 ) {
216265 /* show all */
217266 return hwloc_ps_foreach_process (topology , topocpuset , foreach_process_cb , pidcmd , psflags , only_name , only_uid );
218267
@@ -235,6 +284,8 @@ static int run(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset,
235284
236285 if (json_output )
237286 print_process_json (topology , & proc );
287+ else if (lstopo_misc_output )
288+ print_process_lstopo_misc (topology , & proc );
238289 else
239290 print_process (topology , & proc );
240291 }
@@ -317,6 +368,7 @@ run_json_server(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset)
317368
318369 only_name = NULL ;
319370 only_pid = NO_ONLY_PID ;
371+ children_of_pid = NO_ONLY_PID ;
320372 current = req ;
321373 while (* current ) {
322374 if (!strncmp (current , "lastcpulocation " , 16 )) {
@@ -338,6 +390,10 @@ run_json_server(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset)
338390 psflags |= HWLOC_PS_FLAG_THREADS ;
339391 show_all = 1 ;
340392 break ;
393+ } else if (!strncmp (current , "childrenofpid=" , 14 )) {
394+ children_of_pid = atoi (current + 14 );
395+ show_all = 1 ;
396+ break ;
341397 } else if (!strncmp (current , "name=" , 5 )) {
342398 only_name = current + 5 ;
343399 show_all = 1 ;
@@ -418,6 +474,13 @@ int main(int argc, char *argv[])
418474 }
419475 only_pid = strtol (argv [1 ], NULL , 10 );
420476 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 ;
421484 } else if (!strcmp (argv [0 ], "--name" )) {
422485 if (argc < 2 ) {
423486 usage (callname , stderr );
@@ -449,6 +512,21 @@ int main(int argc, char *argv[])
449512 pidcmd = argv [1 ];
450513 opt = 1 ;
451514
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+
452530 } else if (!strcmp (argv [0 ], "--json-server" )) {
453531 json_server = 1 ;
454532 } else if (!strcmp (argv [0 ], "--json-port" )) {
@@ -522,5 +600,7 @@ int main(int argc, char *argv[])
522600 out_with_topology :
523601 hwloc_topology_destroy (topology );
524602 out :
603+ if (lstopo_misc_output && lstopo_misc_output != stdout )
604+ fclose (lstopo_misc_output );
525605 return err ;
526606}
0 commit comments