| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 | 1 |
| 2 /* POSIX module implementation */ | 2 /* POSIX module implementation */ |
| 3 | 3 |
| 4 /* This file is also used for Windows NT/MS-Win and OS/2. In that case the | 4 /* This file is also used for Windows NT/MS-Win and OS/2. In that case the |
| 5 module actually calls itself 'nt' or 'os2', not 'posix', and a few | 5 module actually calls itself 'nt' or 'os2', not 'posix', and a few |
| 6 functions are either unimplemented or implemented differently. The source | 6 functions are either unimplemented or implemented differently. The source |
| 7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent | 7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent |
| 8 of the compiler used. Different compilers define their own feature | 8 of the compiler used. Different compilers define their own feature |
| 9 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler | 9 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler |
| 10 independent macro PYOS_OS2 should be defined. On OS/2 the default | 10 independent macro PYOS_OS2 should be defined. On OS/2 the default |
| (...skipping 5723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5734 PyObject *iterable, *iterator = NULL, *item; | 5734 PyObject *iterable, *iterator = NULL, *item; |
| 5735 | 5735 |
| 5736 if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O:sched_setaffinity", | 5736 if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O:sched_setaffinity", |
| 5737 &pid, &iterable)) | 5737 &pid, &iterable)) |
| 5738 return NULL; | 5738 return NULL; |
| 5739 | 5739 |
| 5740 iterator = PyObject_GetIter(iterable); | 5740 iterator = PyObject_GetIter(iterable); |
| 5741 if (iterator == NULL) | 5741 if (iterator == NULL) |
| 5742 return NULL; | 5742 return NULL; |
| 5743 | 5743 |
| 5744 ncpus = 1; | 5744 ncpus = 16; |
|
storchaka
2012/08/04 15:09:05
"Since CPU sets are bitsets allocated in units of
AntoinePitrou
2012/08/04 15:14:15
Well, starting at 16 is a heuristic. I don't reall
storchaka
2012/08/04 15:36:25
There is no sense to start less than sizeof(unsign
| |
| 5745 setsize = CPU_ALLOC_SIZE(ncpus); | 5745 setsize = CPU_ALLOC_SIZE(ncpus); |
| 5746 mask = CPU_ALLOC(ncpus); | 5746 mask = CPU_ALLOC(ncpus); |
| 5747 if (mask == NULL) { | 5747 if (mask == NULL) { |
| 5748 PyErr_NoMemory(); | 5748 PyErr_NoMemory(); |
| 5749 goto error; | 5749 goto error; |
| 5750 } | 5750 } |
| 5751 CPU_ZERO_S(setsize, mask); | 5751 CPU_ZERO_S(setsize, mask); |
| 5752 | 5752 |
| 5753 while ((item = PyIter_Next(iterator))) { | 5753 while ((item = PyIter_Next(iterator))) { |
| 5754 long cpu; | 5754 long cpu; |
| 5755 if (!PyLong_Check(item)) { | 5755 if (!PyLong_Check(item)) { |
| 5756 PyErr_Format(PyExc_TypeError, | 5756 PyErr_Format(PyExc_TypeError, |
| 5757 "expected an iterator of ints, " | 5757 "expected an iterator of ints, " |
| 5758 "but iterator yielded %R", | 5758 "but iterator yielded %R", |
| 5759 Py_TYPE(item)); | 5759 Py_TYPE(item)); |
| 5760 Py_DECREF(item); | 5760 Py_DECREF(item); |
| 5761 goto error; | 5761 goto error; |
| 5762 } | 5762 } |
| 5763 cpu = PyLong_AsLong(item); | 5763 cpu = PyLong_AsLong(item); |
| 5764 Py_DECREF(item); | 5764 Py_DECREF(item); |
| 5765 if (cpu < 0) { | 5765 if (cpu < 0) { |
| 5766 if (!PyErr_Occurred()) | 5766 if (!PyErr_Occurred()) |
| 5767 PyErr_SetString(PyExc_ValueError, "negative CPU number"); | 5767 PyErr_SetString(PyExc_ValueError, "negative CPU number"); |
| 5768 goto error; | 5768 goto error; |
| 5769 } | 5769 } |
| 5770 if (cpu > INT_MAX - 1) { | 5770 if (cpu > INT_MAX - 1) { |
|
storchaka
2012/08/04 15:09:05
"The constant CPU_SETSIZE (currently 1024) specifi
AntoinePitrou
2012/08/04 15:14:15
You can store more than CPU_SETSIZE if you allocat
storchaka
2012/08/04 15:36:25
You're right. I'm wrong.
| |
| 5771 PyErr_SetString(PyExc_OverflowError, "CPU number too large"); | 5771 PyErr_SetString(PyExc_OverflowError, "CPU number too large"); |
| 5772 goto error; | 5772 goto error; |
| 5773 } | 5773 } |
| 5774 if (cpu >= ncpus) { | 5774 if (cpu >= ncpus) { |
| 5775 /* Grow CPU mask to fit the CPU number */ | 5775 /* Grow CPU mask to fit the CPU number */ |
| 5776 int newncpus = ncpus; | 5776 int newncpus = ncpus; |
|
storchaka
2012/08/04 15:09:05
I don't see usage of old ncpus in this block. Is n
AntoinePitrou
2012/08/04 15:14:15
I find it more readable.
| |
| 5777 cpu_set_t *newmask; | 5777 cpu_set_t *newmask; |
| 5778 size_t newsetsize; | 5778 size_t newsetsize; |
| 5779 while (newncpus <= cpu) { | 5779 while (newncpus <= cpu) { |
| 5780 if (newncpus > INT_MAX / 2) | 5780 if (newncpus > INT_MAX / 2) |
|
storchaka
2012/08/04 15:09:05
if (newncpus > CPU_SETSIZE / 2)
newncpus =
AntoinePitrou
2012/08/04 15:14:15
No, see above.
| |
| 5781 newncpus = cpu + 1; | 5781 newncpus = cpu + 1; |
| 5782 else | 5782 else |
| 5783 newncpus = newncpus * 2; | 5783 newncpus = newncpus * 2; |
| 5784 } | 5784 } |
| 5785 newmask = CPU_ALLOC(newncpus); | 5785 newmask = CPU_ALLOC(newncpus); |
| 5786 if (newmask == NULL) { | 5786 if (newmask == NULL) { |
| 5787 PyErr_NoMemory(); | 5787 PyErr_NoMemory(); |
| 5788 goto error; | 5788 goto error; |
| 5789 } | 5789 } |
| 5790 newsetsize = CPU_ALLOC_SIZE(newncpus); | 5790 newsetsize = CPU_ALLOC_SIZE(newncpus); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5824 pid_t pid; | 5824 pid_t pid; |
| 5825 int cpu, ncpus, count; | 5825 int cpu, ncpus, count; |
| 5826 size_t setsize; | 5826 size_t setsize; |
| 5827 cpu_set_t *mask = NULL; | 5827 cpu_set_t *mask = NULL; |
| 5828 PyObject *res = NULL; | 5828 PyObject *res = NULL; |
| 5829 | 5829 |
| 5830 if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getaffinity", | 5830 if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getaffinity", |
| 5831 &pid)) | 5831 &pid)) |
| 5832 return NULL; | 5832 return NULL; |
| 5833 | 5833 |
| 5834 ncpus = 16; | 5834 ncpus = 16; |
|
storchaka
2012/08/04 15:09:05
ncpus = sizeof(unsigned long) * CHAR_BIT;
| |
| 5835 while (1) { | 5835 while (1) { |
| 5836 setsize = CPU_ALLOC_SIZE(ncpus); | 5836 setsize = CPU_ALLOC_SIZE(ncpus); |
| 5837 mask = CPU_ALLOC(ncpus); | 5837 mask = CPU_ALLOC(ncpus); |
| 5838 if (mask == NULL) | 5838 if (mask == NULL) |
| 5839 return PyErr_NoMemory(); | 5839 return PyErr_NoMemory(); |
| 5840 if (sched_getaffinity(pid, setsize, mask) == 0) | 5840 if (sched_getaffinity(pid, setsize, mask) == 0) |
| 5841 break; | 5841 break; |
| 5842 CPU_FREE(mask); | 5842 CPU_FREE(mask); |
| 5843 if (errno != EINVAL) | 5843 if (errno != EINVAL) |
| 5844 return posix_error(); | 5844 return posix_error(); |
| 5845 if (ncpus > INT_MAX / 2) { | 5845 if (ncpus > INT_MAX / 2) { |
|
storchaka
2012/08/04 15:09:05
if (newncpus >= CPU_SETSIZE) {
PyErr_SetSt
AntoinePitrou
2012/08/04 15:14:15
Again, see above about dynamically-allocated cpu_s
| |
| 5846 PyErr_SetString(PyExc_OverflowError, "could not allocate " | 5846 PyErr_SetString(PyExc_OverflowError, "could not allocate " |
| 5847 "a large enough CPU set"); | 5847 "a large enough CPU set"); |
| 5848 return NULL; | 5848 return NULL; |
| 5849 } | 5849 } |
| 5850 ncpus = ncpus * 2; | 5850 ncpus = ncpus * 2; |
| 5851 } | 5851 } |
| 5852 | 5852 |
| 5853 res = PySet_New(NULL); | 5853 res = PySet_New(NULL); |
| 5854 if (res == NULL) | 5854 if (res == NULL) |
| 5855 goto error; | 5855 goto error; |
| 5856 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { | 5856 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { |
| 5857 if (CPU_ISSET_S(cpu, setsize, mask)) { | 5857 if (CPU_ISSET_S(cpu, setsize, mask)) { |
| 5858 PyObject *cpu_num = PyLong_FromLong(cpu); | 5858 PyObject *cpu_num = PyLong_FromLong(cpu); |
| 5859 --count; | 5859 --count; |
| 5860 if (cpu_num == NULL) | 5860 if (cpu_num == NULL) |
| 5861 goto error; | 5861 goto error; |
| 5862 if (PySet_Add(res, cpu_num)) { | 5862 if (PySet_Add(res, cpu_num)) { |
| 5863 Py_DECREF(cpu_num); | 5863 Py_DECREF(cpu_num); |
| 5864 goto error; | 5864 goto error; |
| 5865 } | 5865 } |
| 5866 Py_DECREF(cpu_num); | 5866 Py_DECREF(cpu_num); |
| 5867 } | 5867 } |
| 5868 } | 5868 } |
| 5869 CPU_FREE(mask); | 5869 CPU_FREE(mask); |
| 5870 return res; | 5870 return res; |
| 5871 | 5871 |
| 5872 error: | 5872 error: |
| 5873 if (mask) | 5873 if (mask) |
|
storchaka
2012/08/04 15:09:05
mask always is not NULL.
AntoinePitrou
2012/08/04 15:14:15
True.
| |
| 5874 CPU_FREE(mask); | 5874 CPU_FREE(mask); |
| 5875 Py_XDECREF(res); | 5875 Py_XDECREF(res); |
| 5876 return NULL; | 5876 return NULL; |
| 5877 } | 5877 } |
| 5878 | 5878 |
| 5879 #endif /* HAVE_SCHED_SETAFFINITY */ | 5879 #endif /* HAVE_SCHED_SETAFFINITY */ |
| 5880 | 5880 |
| 5881 #endif /* HAVE_SCHED_H */ | 5881 #endif /* HAVE_SCHED_H */ |
| 5882 | 5882 |
| 5883 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ | 5883 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ |
| (...skipping 6063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11947 | 11947 |
| 11948 initialized = 1; | 11948 initialized = 1; |
| 11949 | 11949 |
| 11950 return m; | 11950 return m; |
| 11951 | 11951 |
| 11952 } | 11952 } |
| 11953 | 11953 |
| 11954 #ifdef __cplusplus | 11954 #ifdef __cplusplus |
| 11955 } | 11955 } |
| 11956 #endif | 11956 #endif |
| LEFT | RIGHT |