Skip to content

Commit

Permalink
hwloc-ps: split the code reading proc/thread info to a separate file
Browse files Browse the repository at this point in the history
Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
  • Loading branch information
bgoglin committed Feb 14, 2019
1 parent 77a1fc5 commit f6010a2
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 210 deletions.
8 changes: 6 additions & 2 deletions utils/hwloc/Makefile.am
@@ -1,4 +1,4 @@
# Copyright © 2009-2018 Inria. All rights reserved.
# Copyright © 2009-2019 Inria. All rights reserved.
# Copyright © 2009-2012, 2014, 2016 Université Bordeaux
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
#
Expand All @@ -20,7 +20,7 @@ EXTRA_DIST = \
test-hwloc-distrib.output \
test-hwloc-info.output

noinst_HEADERS = misc.h
noinst_HEADERS = misc.h common-ps.h

bin_PROGRAMS = \
hwloc-annotate \
Expand Down Expand Up @@ -57,6 +57,10 @@ hwloc_calc_SOURCES = \
hwloc-calc.h \
hwloc-calc.c

hwloc_ps_SOURCES = \
hwloc-ps.c \
common-ps.c

bin_SCRIPTS = hwloc-compress-dir
if HWLOC_HAVE_LINUX
bin_SCRIPTS += hwloc-gather-topology
Expand Down
199 changes: 199 additions & 0 deletions utils/hwloc/common-ps.c
@@ -0,0 +1,199 @@
/*
* Copyright © 2009-2019 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/

#include <private/autogen/config.h>
#include <hwloc.h>
#ifdef HWLOC_LINUX_SYS
#include <hwloc/linux.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#include <fcntl.h>

#include "common-ps.h"
#include "misc.h"

int hwloc_ps_read_process(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset,
struct hwloc_ps_process *proc,
unsigned long flags, char *pidcmd)
{
#ifdef HAVE_DIRENT_H
unsigned i;
hwloc_bitmap_t cpuset;
unsigned pathlen;
char *path;
char *end;
int fd;

cpuset = hwloc_bitmap_alloc();
if (!cpuset)
return -1;

pathlen = 6 + 21 + 1 + 7 + 1;
path = malloc(pathlen);
snprintf(path, pathlen, "/proc/%ld/cmdline", proc->pid);
fd = open(path, O_RDONLY);
free(path);

if (fd >= 0) {
ssize_t n = read(fd, proc->name, sizeof(proc->name) - 1);
close(fd);

if (n <= 0)
/* Ignore kernel threads and errors */
goto out;

proc->name[n] = 0;
}

proc->string[0] = '\0';
if (pidcmd) {
char *cmd;
FILE *file;
cmd = malloc(strlen(pidcmd)+1+5+2+1);
sprintf(cmd, "%s %u", pidcmd, (unsigned) proc->pid);
file = popen(cmd, "r");
if (file) {
if (fgets(proc->string, sizeof(proc->string), file)) {
end = strchr(proc->string, '\n');
if (end)
*end = '\0';
}
pclose(file);
}
free(cmd);
}

if (flags & HWLOC_PS_FLAG_THREADS) {
#ifdef HWLOC_LINUX_SYS
/* check if some threads must be displayed */
DIR *taskdir;

pathlen = 6 + 21 + 1 + 4 + 1;
path = malloc(pathlen);
snprintf(path, pathlen, "/proc/%ld/task", proc->pid);
taskdir = opendir(path);
if (taskdir) {
struct dirent *taskdirent;
long tid;
unsigned n = 0;
/* count threads */
while ((taskdirent = readdir(taskdir))) {
tid = strtol(taskdirent->d_name, &end, 10);
if (*end)
/* Not a number */
continue;
n++;
}
if (n > 1) {
/* if there's more than one thread, see if some are bound */
proc->threads = calloc(n, sizeof(*proc->threads));
if (proc->threads) {
/* reread the directory but gather info now */
rewinddir(taskdir);
i = 0;
while ((taskdirent = readdir(taskdir))) {
char *path2;
unsigned path2len;

tid = strtol(taskdirent->d_name, &end, 10);
if (*end)
/* Not a number */
continue;

proc->threads[i].tid = tid;

path2len = pathlen + 1 + 21 + 1 + 4 + 1;
path2 = malloc(path2len);
if (path2) {
int commfd;
snprintf(path2, path2len, "%s/%ld/comm", path, tid);
commfd = open(path2, O_RDWR);
if (commfd >= 0) {
read(commfd, proc->threads[i].name, sizeof(proc->threads[i].name));
close(commfd);
proc->threads[i].name[sizeof(proc->threads[i].name)-1] = '\0';
end = strchr(proc->threads[i].name, '\n');
if (end)
*end = '\0';
}
free(path2);
}

if (flags & HWLOC_PS_FLAG_LASTCPULOCATION) {
if (hwloc_linux_get_tid_last_cpu_location(topology, tid, cpuset))
goto next;
} else {
if (hwloc_linux_get_tid_cpubind(topology, tid, cpuset))
goto next;
}
hwloc_bitmap_and(cpuset, cpuset, topocpuset);
if (hwloc_bitmap_iszero(cpuset))
goto next;

proc->threads[i].cpuset = hwloc_bitmap_dup(cpuset);
if (!hwloc_bitmap_isequal(cpuset, topocpuset)) {
proc->threads[i].bound = 1;
proc->nboundthreads++;
}

next:
i++;
proc->nthreads++;
if (i == n)
/* ignore the lastly created threads, I'm too lazy to reallocate */
break;
}
} else {
/* failed to alloc, behave as if there were no threads */
}
}
closedir(taskdir);
}
free(path);
#endif /* HWLOC_LINUX_SYS */
}

if (flags & HWLOC_PS_FLAG_LASTCPULOCATION) {
if (hwloc_get_proc_last_cpu_location(topology, proc->pid, cpuset, 0))
goto out;
} else {
if (hwloc_get_proc_cpubind(topology, proc->pid, cpuset, 0))
goto out;
}

hwloc_bitmap_and(cpuset, cpuset, topocpuset);
if (hwloc_bitmap_iszero(cpuset))
goto out;

proc->bound = !hwloc_bitmap_isequal(cpuset, topocpuset);
proc->cpuset = cpuset;
return 0;

out:
hwloc_bitmap_free(cpuset);
#endif /* HAVE_DIRENT_H */
return -1;
}

void hwloc_ps_free_process(struct hwloc_ps_process *proc)
{
unsigned i;

if (proc->nthreads)
for(i=0; i<proc->nthreads; i++)
if (proc->threads[i].cpuset)
hwloc_bitmap_free(proc->threads[i].cpuset);
free(proc->threads);

hwloc_bitmap_free(proc->cpuset);
}
41 changes: 41 additions & 0 deletions utils/hwloc/common-ps.h
@@ -0,0 +1,41 @@
/*
* Copyright © 2009-2019 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/

#ifndef UTILS_HWLOC_PS_H
#define UTILS_HWLOC_PS_H

#include <private/autogen/config.h>
#include <hwloc.h>

#define HWLOC_PS_TIDNAME_MAX 16 /* specified in pthread_setname_np.3 */

struct hwloc_ps_process {
long pid;
char string[1024];
char name[64];
hwloc_bitmap_t cpuset;
int bound;
unsigned nthreads;
unsigned nboundthreads;
struct hwloc_ps_thread {
long tid;
hwloc_bitmap_t cpuset;
int bound;
char name[HWLOC_PS_TIDNAME_MAX];
} *threads;
};

#define HWLOC_PS_FLAG_THREADS (1UL<<0)
#define HWLOC_PS_FLAG_LASTCPULOCATION (1UL<<1)

int hwloc_ps_read_process(hwloc_topology_t topology, hwloc_const_bitmap_t topocpuset,
struct hwloc_ps_process *proc,
unsigned long flags, char *pidcmd);

void hwloc_ps_free_process(struct hwloc_ps_process *proc);

#endif /* UTILS_HWLOC_PS_H */

0 comments on commit f6010a2

Please sign in to comment.