From f2205d01fe589057d14b5b311599d651bdd84836 Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Sat, 9 Aug 2014 13:30:06 -0400 Subject: [PATCH 01/10] Fix get_affinity for linux --- psutil/_pslinux.py | 4 +--- psutil/_psutil_linux.c | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index 66fea9126..daf8464d5 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -1058,9 +1058,7 @@ def nice_set(self, value): @wrap_exceptions def cpu_affinity_get(self): - from_bitmask = lambda x: [i for i in xrange(64) if (1 << i) & x] - bitmask = cext.proc_cpu_affinity_get(self.pid) - return from_bitmask(bitmask) + return cext.proc_cpu_affinity_get(self.pid) @wrap_exceptions def cpu_affinity_set(self, cpus): diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index 1f17ae75c..04b7b4f01 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -255,17 +255,31 @@ psutil_linux_sysinfo(PyObject *self, PyObject *args) static PyObject * psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { - unsigned long mask; - unsigned int len = sizeof(mask); + cpu_set_t cpuset; + unsigned int len = sizeof(cpu_set_t); long pid; if (!PyArg_ParseTuple(args, "i", &pid)) { return NULL; } - if (sched_getaffinity(pid, len, (cpu_set_t *)&mask) < 0) { + + if (sched_getaffinity(pid, len, (cpu_set_t *)&cpuset) < 0) { return PyErr_SetFromErrno(PyExc_OSError); } - return Py_BuildValue("l", mask); + + int cpu_count = CPU_COUNT(&cpuset); + PyObject* ret_list = PyList_New(0); + + int i; + for (i = 0; i < cpu_count; ++i) + { + if (CPU_ISSET(i, &cpuset)) + { + PyList_Append(ret_list, Py_BuildValue("i", i)); + } + } + + return ret_list; } From aaac9b8680558ce65c1526f3e9e29a321bd479ac Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Sun, 10 Aug 2014 14:29:53 -0400 Subject: [PATCH 02/10] CPU_COUNT returns the number of active CPUs in the set. Do not use its return value to base the CPU counting loop on --- psutil/_psutil_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index 04b7b4f01..5dbecbbe2 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -256,6 +256,7 @@ static PyObject * psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { cpu_set_t cpuset; + CPU_ZERO(&cpuset); unsigned int len = sizeof(cpu_set_t); long pid; @@ -267,11 +268,10 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) return PyErr_SetFromErrno(PyExc_OSError); } - int cpu_count = CPU_COUNT(&cpuset); PyObject* ret_list = PyList_New(0); int i; - for (i = 0; i < cpu_count; ++i) + for (i = 0; i < CPU_SETSIZE; ++i) { if (CPU_ISSET(i, &cpuset)) { From cdfc73380aa19f5f863de2978b9a91a6dae4fc0c Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Sun, 10 Aug 2014 14:42:24 -0400 Subject: [PATCH 03/10] Move declarations for C90 support and cleanup --- psutil/_psutil_linux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index 5dbecbbe2..e8c789643 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -256,15 +256,15 @@ static PyObject * psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { cpu_set_t cpuset; - CPU_ZERO(&cpuset); unsigned int len = sizeof(cpu_set_t); long pid; - + if (!PyArg_ParseTuple(args, "i", &pid)) { return NULL; } - if (sched_getaffinity(pid, len, (cpu_set_t *)&cpuset) < 0) { + CPU_ZERO(&cpuset); + if (sched_getaffinity(pid, len, &cpuset) < 0) { return PyErr_SetFromErrno(PyExc_OSError); } From 545a8226ad3d017ae46541271002631d5571b822 Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Sun, 10 Aug 2014 14:48:19 -0400 Subject: [PATCH 04/10] Also move the declaration of 'i' to the top for C90 --- psutil/_psutil_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index e8c789643..cf820cfc4 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -258,7 +258,8 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) cpu_set_t cpuset; unsigned int len = sizeof(cpu_set_t); long pid; - + int i; + if (!PyArg_ParseTuple(args, "i", &pid)) { return NULL; } @@ -270,7 +271,6 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) PyObject* ret_list = PyList_New(0); - int i; for (i = 0; i < CPU_SETSIZE; ++i) { if (CPU_ISSET(i, &cpuset)) From 57f1422e1f934adbde495075354a88c4b18f7dc0 Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Sun, 10 Aug 2014 14:53:07 -0400 Subject: [PATCH 05/10] Move declaration of the return list to the top of the function for C90 --- psutil/_psutil_linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index cf820cfc4..df59d4e6a 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -259,6 +259,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) unsigned int len = sizeof(cpu_set_t); long pid; int i; + PyObject* ret_list; if (!PyArg_ParseTuple(args, "i", &pid)) { return NULL; @@ -269,7 +270,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) return PyErr_SetFromErrno(PyExc_OSError); } - PyObject* ret_list = PyList_New(0); + ret_list = PyList_New(0); for (i = 0; i < CPU_SETSIZE; ++i) { From 309631ffab71a29d12c36344a6d7af624646959a Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Sun, 10 Aug 2014 14:57:28 -0400 Subject: [PATCH 06/10] Remove import of xrange which is no longer used --- psutil/_pslinux.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index daf8464d5..9660e799c 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -20,7 +20,7 @@ from psutil import _common from psutil import _psposix from psutil._common import (isfile_strict, usage_percent, deprecated) -from psutil._compat import PY3, xrange, namedtuple, wraps, b, defaultdict +from psutil._compat import PY3, namedtuple, wraps, b, defaultdict import _psutil_linux as cext import _psutil_posix From 1d1d8fcde336c09be5cc3d4031fe8b8550197e47 Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Mon, 11 Aug 2014 15:54:39 -0400 Subject: [PATCH 07/10] Commit dynamically allocating version of psutil_proc_cpu_affinity_get based on the os_sched_getaffinity_impl in newer versions of python. However, this one returns a list of integers instead of a set of longs, and has an optimization in the CPU list building loop --- psutil/_psutil_linux.c | 63 +++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index df59d4e6a..f13149f32 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -22,6 +22,8 @@ #include "_psutil_linux.h" +/* The minimum number of CPUs allocated in a cpu_set_t */ +static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; // Linux >= 2.6.13 #define PSUTIL_HAVE_IOPRIO defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -255,32 +257,61 @@ psutil_linux_sysinfo(PyObject *self, PyObject *args) static PyObject * psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { - cpu_set_t cpuset; - unsigned int len = sizeof(cpu_set_t); + int cpu, ncpus, count; long pid; - int i; - PyObject* ret_list; - + size_t setsize; + cpu_set_t *mask = NULL; + PyObject *res = NULL; + if (!PyArg_ParseTuple(args, "i", &pid)) { return NULL; } - CPU_ZERO(&cpuset); - if (sched_getaffinity(pid, len, &cpuset) < 0) { - return PyErr_SetFromErrno(PyExc_OSError); + ncpus = NCPUS_START; + while (1) { + setsize = CPU_ALLOC_SIZE(ncpus); + mask = CPU_ALLOC(ncpus); + if (mask == NULL) + return PyErr_NoMemory(); + if (sched_getaffinity(pid, setsize, mask) == 0) + break; + CPU_FREE(mask); + if (errno != EINVAL) + return PyErr_SetFromErrno(PyExc_OSError); + if (ncpus > INT_MAX / 2) { + PyErr_SetString(PyExc_OverflowError, "could not allocate " + "a large enough CPU set"); + return NULL; + } + ncpus = ncpus * 2; } - ret_list = PyList_New(0); - - for (i = 0; i < CPU_SETSIZE; ++i) - { - if (CPU_ISSET(i, &cpuset)) - { - PyList_Append(ret_list, Py_BuildValue("i", i)); + res = PyList_New(0); + if (res == NULL) + goto error; + + int cpucount_s = CPU_COUNT_S(setsize, mask); + for (cpu = 0, count = cpucount_s; count; cpu++) { + if (CPU_ISSET_S(cpu, setsize, mask)) { + PyObject *cpu_num = PyInt_FromLong(cpu); + --count; + if (cpu_num == NULL) + goto error; + if (PyList_Append(res, cpu_num)) { + Py_DECREF(cpu_num); + goto error; + } + Py_DECREF(cpu_num); } } + CPU_FREE(mask); + return res; - return ret_list; +error: + if (mask) + CPU_FREE(mask); + Py_XDECREF(res); + return NULL; } From e34c60bd9eeaf296156b01fceaabb31385ed66ef Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Mon, 11 Aug 2014 16:06:46 -0400 Subject: [PATCH 08/10] Fix python 3.3 incompatibility --- psutil/_psutil_linux.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index f13149f32..bbc6771cd 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -293,7 +293,12 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) int cpucount_s = CPU_COUNT_S(setsize, mask); for (cpu = 0, count = cpucount_s; count; cpu++) { if (CPU_ISSET_S(cpu, setsize, mask)) { - PyObject *cpu_num = PyInt_FromLong(cpu); + PyObject *cpu_num; +#if PY_MAJOR_VERSION >= 3 + cpu_num = PyLong_FromLong(cpu); +#else + cpu_num = PyInt_FromLong(cpu); +#endif --count; if (cpu_num == NULL) goto error; From 772021ce8bb7cdf0183bd6d6f81373d12c672c47 Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Mon, 11 Aug 2014 16:12:15 -0400 Subject: [PATCH 09/10] Fix C90 compilation issue --- psutil/_psutil_linux.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index bbc6771cd..56e481780 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -293,11 +293,10 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) int cpucount_s = CPU_COUNT_S(setsize, mask); for (cpu = 0, count = cpucount_s; count; cpu++) { if (CPU_ISSET_S(cpu, setsize, mask)) { - PyObject *cpu_num; #if PY_MAJOR_VERSION >= 3 - cpu_num = PyLong_FromLong(cpu); + PyObject *cpu_num = PyLong_FromLong(cpu); #else - cpu_num = PyInt_FromLong(cpu); + PyObject *cpu_num = PyInt_FromLong(cpu); #endif --count; if (cpu_num == NULL) From 4be391d93bcde42aaf8fd2168d5aae8e6c3c9f87 Mon Sep 17 00:00:00 2001 From: David Daeschler Date: Mon, 11 Aug 2014 16:21:46 -0400 Subject: [PATCH 10/10] Fix C90 compilation issue --- psutil/_psutil_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index 56e481780..41d24d4e6 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -257,7 +257,7 @@ psutil_linux_sysinfo(PyObject *self, PyObject *args) static PyObject * psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { - int cpu, ncpus, count; + int cpu, ncpus, count, cpucount_s; long pid; size_t setsize; cpu_set_t *mask = NULL; @@ -290,7 +290,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) if (res == NULL) goto error; - int cpucount_s = CPU_COUNT_S(setsize, mask); + cpucount_s = CPU_COUNT_S(setsize, mask); for (cpu = 0, count = cpucount_s; count; cpu++) { if (CPU_ISSET_S(cpu, setsize, mask)) { #if PY_MAJOR_VERSION >= 3