Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
hwloc-ps: split the code reading proc/thread info to a separate file
Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
- Loading branch information
Showing
4 changed files
with
251 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 */ |
Oops, something went wrong.