/* htop - Affinity.c (C) 2004-2011 Hisham H. Muhammad (C) 2020 Red Hat, Inc. All Rights Reserved. Released under the GNU GPLv2+, see the COPYING file in the source distribution for its full text. */ #include "config.h" // IWYU pragma: keep #include "Affinity.h" #include #include #include "Process.h" #include "XUtils.h" #if defined(HAVE_LIBHWLOC) #include #include #ifdef __linux__ #define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_THREAD #else #define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_PROCESS #endif #elif defined(HAVE_AFFINITY) #include #endif Affinity* Affinity_new(Machine* host) { Affinity* this = xCalloc(1, sizeof(Affinity)); this->size = 8; this->cpus = xCalloc(this->size, sizeof(unsigned int)); this->host = host; return this; } void Affinity_delete(Affinity* this) { free(this->cpus); free(this); } void Affinity_add(Affinity* this, unsigned int id) { if (this->used == this->size) { this->size *= 2; this->cpus = xRealloc(this->cpus, sizeof(unsigned int) * this->size); } this->cpus[this->used] = id; this->used++; } #if defined(HAVE_LIBHWLOC) static Affinity* Affinity_get(const Process* p, Machine* host) { hwloc_cpuset_t cpuset = hwloc_bitmap_alloc(); bool ok = (hwloc_get_proc_cpubind(host->topology, Process_getPid(p), cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0); Affinity* affinity = NULL; if (ok) { affinity = Affinity_new(host); if (hwloc_bitmap_last(cpuset) == -1) { for (unsigned int i = 0; i < host->existingCPUs; i++) { Affinity_add(affinity, i); } } else { int id; hwloc_bitmap_foreach_begin(id, cpuset) Affinity_add(affinity, (unsigned)id); hwloc_bitmap_foreach_end(); } } hwloc_bitmap_free(cpuset); return affinity; } static bool Affinity_set(Process* p, Arg arg) { Affinity* this = arg.v; hwloc_cpuset_t cpuset = hwloc_bitmap_alloc(); for (unsigned int i = 0; i < this->used; i++) { hwloc_bitmap_set(cpuset, this->cpus[i]); } bool ok = (hwloc_set_proc_cpubind(this->host->topology, Process_getPid(p), cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0); hwloc_bitmap_free(cpuset); return ok; } #elif defined(HAVE_AFFINITY) static Affinity* Affinity_get(const Process* p, Machine* host) { cpu_set_t cpuset; bool ok = (sched_getaffinity(Process_getPid(p), sizeof(cpu_set_t), &cpuset) == 0); if (!ok) return NULL; Affinity* affinity = Affinity_new(host); for (unsigned int i = 0; i < host->existingCPUs; i++) { if (CPU_ISSET(i, &cpuset)) { Affinity_add(affinity, i); } } return affinity; } static bool Affinity_set(Process* p, Arg arg) { Affinity* this = arg.v; cpu_set_t cpuset; CPU_ZERO(&cpuset); for (unsigned int i = 0; i < this->used; i++) { CPU_SET(this->cpus[i], &cpuset); } bool ok = (sched_setaffinity(Process_getPid(p), sizeof(unsigned long), &cpuset) == 0); return ok; } #endif #if defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY) bool Affinity_rowSet(Row* row, Arg arg) { Process* p = (Process*) row; assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class)); return Affinity_set(p, arg); } Affinity* Affinity_rowGet(const Row* row, Machine* host) { const Process* p = (const Process*) row; assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class)); return Affinity_get(p, host); } #endif /* HAVE_LIBHWLOC || HAVE_AFFINITY */