Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2727)

Side by Side Diff: Modules/posixmodule.c

Issue 12655: Expose sched.h functions
Patch Set: Created 9 months, 2 weeks ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/test/test_posix.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 5701 matching lines...) Expand 10 before | Expand all | Expand 10 after
5712 5712
5713 static PyObject * 5713 static PyObject *
5714 posix_sched_yield(PyObject *self, PyObject *noargs) 5714 posix_sched_yield(PyObject *self, PyObject *noargs)
5715 { 5715 {
5716 if (sched_yield()) 5716 if (sched_yield())
5717 return posix_error(); 5717 return posix_error();
5718 Py_RETURN_NONE; 5718 Py_RETURN_NONE;
5719 } 5719 }
5720 5720
5721 #ifdef HAVE_SCHED_SETAFFINITY 5721 #ifdef HAVE_SCHED_SETAFFINITY
5722
5723 typedef struct {
5724 PyObject_HEAD;
5725 Py_ssize_t size;
5726 int ncpus;
5727 cpu_set_t *set;
5728 } Py_cpu_set;
5729
5730 static PyTypeObject cpu_set_type;
5731
5732 static void
5733 cpu_set_dealloc(Py_cpu_set *set)
5734 {
5735 assert(set->set);
5736 CPU_FREE(set->set);
5737 Py_TYPE(set)->tp_free(set);
5738 }
5739
5740 static Py_cpu_set *
5741 make_new_cpu_set(PyTypeObject *type, Py_ssize_t size)
5742 {
5743 Py_cpu_set *set;
5744
5745 if (size < 0) {
5746 PyErr_SetString(PyExc_ValueError, "negative size");
5747 return NULL;
5748 }
5749 set = (Py_cpu_set *)type->tp_alloc(type, 0);
5750 if (!set)
5751 return NULL;
5752 set->ncpus = size;
5753 set->size = CPU_ALLOC_SIZE(size);
5754 set->set = CPU_ALLOC(size);
5755 if (!set->set) {
5756 type->tp_free(set);
5757 PyErr_NoMemory();
5758 return NULL;
5759 }
5760 CPU_ZERO_S(set->size, set->set);
5761 return set;
5762 }
5763
5764 static PyObject *
5765 cpu_set_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
5766 {
5767 int size;
5768
5769 if (!_PyArg_NoKeywords("cpu_set()", kwargs) ||
5770 !PyArg_ParseTuple(args, "i:cpu_set", &size))
5771 return NULL;
5772 return (PyObject *)make_new_cpu_set(type, size);
5773 }
5774
5775 PyDoc_STRVAR(cpu_set_sizeof_doc,
5776 "cpu_set.__sizeof__() -> int\n\n\
5777 Returns size in memory, in bytes.");
5778
5779 static PyObject *
5780 cpu_set_sizeof(Py_cpu_set *set, PyObject *noargs)
5781 {
5782 Py_ssize_t res = 0;
5783
5784 res = sizeof(Py_cpu_set);
5785 res += set->size;
5786 return PyLong_FromSsize_t(res);
5787 }
5788
5789 static PyObject *
5790 cpu_set_repr(Py_cpu_set *set)
5791 {
5792 return PyUnicode_FromFormat("<cpu_set with %li entries>", set->ncpus);
5793 }
5794
5795 static Py_ssize_t
5796 cpu_set_len(Py_cpu_set *set)
5797 {
5798 return set->ncpus;
5799 }
5800
5801 static int
5802 _get_cpu(Py_cpu_set *set, const char *requester, PyObject *args)
5803 {
5804 int cpu;
5805 if (!PyArg_ParseTuple(args, requester, &cpu))
5806 return -1;
5807 if (cpu < 0) {
5808 PyErr_SetString(PyExc_ValueError, "cpu < 0 not valid");
5809 return -1;
5810 }
5811 if (cpu >= set->ncpus) {
5812 PyErr_SetString(PyExc_ValueError, "cpu too large for set");
5813 return -1;
5814 }
5815 return cpu;
5816 }
5817
5818 PyDoc_STRVAR(cpu_set_set_doc,
5819 "cpu_set.set(i)\n\n\
5820 Add CPU *i* to the set.");
5821
5822 static PyObject *
5823 cpu_set_set(Py_cpu_set *set, PyObject *args)
5824 {
5825 int cpu = _get_cpu(set, "i|set", args);
5826 if (cpu == -1)
5827 return NULL;
5828 CPU_SET_S(cpu, set->size, set->set);
5829 Py_RETURN_NONE;
5830 }
5831
5832 PyDoc_STRVAR(cpu_set_count_doc,
5833 "cpu_set.count() -> int\n\n\
5834 Return the number of CPUs active in the set.");
5835
5836 static PyObject *
5837 cpu_set_count(Py_cpu_set *set, PyObject *noargs)
5838 {
5839 return PyLong_FromLong(CPU_COUNT_S(set->size, set->set));
5840 }
5841
5842 PyDoc_STRVAR(cpu_set_clear_doc,
5843 "cpu_set.clear(i)\n\n\
5844 Remove CPU *i* from the set.");
5845
5846 static PyObject *
5847 cpu_set_clear(Py_cpu_set *set, PyObject *args)
5848 {
5849 int cpu = _get_cpu(set, "i|clear", args);
5850 if (cpu == -1)
5851 return NULL;
5852 CPU_CLR_S(cpu, set->size, set->set);
5853 Py_RETURN_NONE;
5854 }
5855
5856 PyDoc_STRVAR(cpu_set_isset_doc,
5857 "cpu_set.isset(i) -> bool\n\n\
5858 Test if CPU *i* is in the set.");
5859
5860 static PyObject *
5861 cpu_set_isset(Py_cpu_set *set, PyObject *args)
5862 {
5863 int cpu = _get_cpu(set, "i|isset", args);
5864 if (cpu == -1)
5865 return NULL;
5866 if (CPU_ISSET_S(cpu, set->size, set->set))
5867 Py_RETURN_TRUE;
5868 Py_RETURN_FALSE;
5869 }
5870
5871 PyDoc_STRVAR(cpu_set_zero_doc,
5872 "cpu_set.zero()\n\n\
5873 Clear the cpu_set.");
5874
5875 static PyObject *
5876 cpu_set_zero(Py_cpu_set *set, PyObject *noargs)
5877 {
5878 CPU_ZERO_S(set->size, set->set);
5879 Py_RETURN_NONE;
5880 }
5881
5882 static PyObject *
5883 cpu_set_richcompare(Py_cpu_set *set, Py_cpu_set *other, int op)
5884 {
5885 int eq;
5886
5887 if ((op != Py_EQ && op != Py_NE) || Py_TYPE(other) != &cpu_set_type)
5888 Py_RETURN_NOTIMPLEMENTED;
5889
5890 eq = set->ncpus == other->ncpus && CPU_EQUAL_S(set->size, set->set, other->s et);
5891 if ((op == Py_EQ) ? eq : !eq)
5892 Py_RETURN_TRUE;
5893 else
5894 Py_RETURN_FALSE;
5895 }
5896
5897 #define CPU_SET_BINOP(name, op) \
5898 static PyObject * \
5899 do_cpu_set_##name(Py_cpu_set *left, Py_cpu_set *right, Py_cpu_set *res) { \
5900 if (res) { \
5901 Py_INCREF(res); \
5902 } \
5903 else { \
5904 res = make_new_cpu_set(&cpu_set_type, left->ncpus); \
5905 if (!res) \
5906 return NULL; \
5907 } \
5908 if (Py_TYPE(right) != &cpu_set_type || left->ncpus != right->ncpus) { \
5909 Py_DECREF(res); \
5910 Py_RETURN_NOTIMPLEMENTED; \
5911 } \
5912 assert(left->size == right->size && right->size == res->size); \
5913 op(res->size, res->set, left->set, right->set); \
5914 return (PyObject *)res; \
5915 } \
5916 static PyObject * \
5917 cpu_set_##name(Py_cpu_set *left, Py_cpu_set *right) { \
5918 return do_cpu_set_##name(left, right, NULL); \
5919 } \
5920 static PyObject * \
5921 cpu_set_i##name(Py_cpu_set *left, Py_cpu_set *right) { \
5922 return do_cpu_set_##name(left, right, left); \
5923 } \
5924
5925 CPU_SET_BINOP(and, CPU_AND_S)
5926 CPU_SET_BINOP(or, CPU_OR_S)
5927 CPU_SET_BINOP(xor, CPU_XOR_S)
5928 #undef CPU_SET_BINOP
5929
5930 PyDoc_STRVAR(cpu_set_doc,
5931 "cpu_set(size)\n\n\
5932 Create an empty mask of CPUs.");
5933
5934 static PyNumberMethods cpu_set_as_number = {
5935 0, /*nb_add*/
5936 0, /*nb_subtract*/
5937 0, /*nb_multiply*/
5938 0, /*nb_remainder*/
5939 0, /*nb_divmod*/
5940 0, /*nb_power*/
5941 0, /*nb_negative*/
5942 0, /*nb_positive*/
5943 0, /*nb_absolute*/
5944 0, /*nb_bool*/
5945 0, /*nb_invert*/
5946 0, /*nb_lshift*/
5947 0, /*nb_rshift*/
5948 (binaryfunc)cpu_set_and, /*nb_and*/
5949 (binaryfunc)cpu_set_xor, /*nb_xor*/
5950 (binaryfunc)cpu_set_or, /*nb_or*/
5951 0, /*nb_int*/
5952 0, /*nb_reserved*/
5953 0, /*nb_float*/
5954 0, /*nb_inplace_add*/
5955 0, /*nb_inplace_subtract*/
5956 0, /*nb_inplace_multiply*/
5957 0, /*nb_inplace_remainder*/
5958 0, /*nb_inplace_power*/
5959 0, /*nb_inplace_lshift*/
5960 0, /*nb_inplace_rshift*/
5961 (binaryfunc)cpu_set_iand, /*nb_inplace_and*/
5962 (binaryfunc)cpu_set_ixor, /*nb_inplace_xor*/
5963 (binaryfunc)cpu_set_ior, /*nb_inplace_or*/
5964 };
5965
5966 static PySequenceMethods cpu_set_as_sequence = {
5967 (lenfunc)cpu_set_len, /* sq_length */
5968 };
5969
5970 static PyMethodDef cpu_set_methods[] = {
5971 {"clear", (PyCFunction)cpu_set_clear, METH_VARARGS, cpu_set_clear_doc},
5972 {"count", (PyCFunction)cpu_set_count, METH_NOARGS, cpu_set_count_doc},
5973 {"isset", (PyCFunction)cpu_set_isset, METH_VARARGS, cpu_set_isset_doc},
5974 {"set", (PyCFunction)cpu_set_set, METH_VARARGS, cpu_set_set_doc},
5975 {"zero", (PyCFunction)cpu_set_zero, METH_NOARGS, cpu_set_zero_doc},
5976 {"__sizeof__", (PyCFunction)cpu_set_sizeof, METH_NOARGS, cpu_set_sizeof_doc} ,
5977 {NULL, NULL} /* sentinel */
5978 };
5979
5980 static PyTypeObject cpu_set_type = {
5981 PyVarObject_HEAD_INIT(&PyType_Type, 0)
5982 "posix.cpu_set", /* tp_name */
5983 sizeof(Py_cpu_set), /* tp_basicsize */
5984 0, /* tp_itemsize */
5985 /* methods */
5986 (destructor)cpu_set_dealloc, /* tp_dealloc */
5987 0, /* tp_print */
5988 0, /* tp_getattr */
5989 0, /* tp_setattr */
5990 0, /* tp_reserved */
5991 (reprfunc)cpu_set_repr, /* tp_repr */
5992 &cpu_set_as_number, /* tp_as_number */
5993 &cpu_set_as_sequence, /* tp_as_sequence */
5994 0, /* tp_as_mapping */
5995 PyObject_HashNotImplemented, /* tp_hash */
5996 0, /* tp_call */
5997 0, /* tp_str */
5998 PyObject_GenericGetAttr, /* tp_getattro */
5999 0, /* tp_setattro */
6000 0, /* tp_as_buffer */
6001 Py_TPFLAGS_DEFAULT, /* tp_flags */
6002 cpu_set_doc, /* tp_doc */
6003 0, /* tp_traverse */
6004 0, /* tp_clear */
6005 (richcmpfunc)cpu_set_richcompare, /* tp_richcompare */
6006 0, /* tp_weaklistoffset */
6007 0, /* tp_iter */
6008 0, /* tp_iternext */
6009 cpu_set_methods, /* tp_methods */
6010 0, /* tp_members */
6011 0, /* tp_getset */
6012 0, /* tp_base */
6013 0, /* tp_dict */
6014 0, /* tp_descr_get */
6015 0, /* tp_descr_set */
6016 0, /* tp_dictoffset */
6017 0, /* tp_init */
6018 PyType_GenericAlloc, /* tp_alloc */
6019 cpu_set_new, /* tp_new */
6020 PyObject_Del, /* tp_free */
6021 };
6022 5722
6023 PyDoc_STRVAR(posix_sched_setaffinity__doc__, 5723 PyDoc_STRVAR(posix_sched_setaffinity__doc__,
6024 "sched_setaffinity(pid, cpu_set)\n\n\ 5724 "sched_setaffinity(pid, cpu_set)\n\n\
6025 Set the affinity of the process with PID *pid* to *cpu_set*."); 5725 Set the affinity of the process with PID *pid* to *cpu_set*.");
6026 5726
6027 static PyObject * 5727 static PyObject *
6028 posix_sched_setaffinity(PyObject *self, PyObject *args) 5728 posix_sched_setaffinity(PyObject *self, PyObject *args)
6029 { 5729 {
6030 pid_t pid; 5730 pid_t pid;
6031 Py_cpu_set *cpu_set; 5731 int ncpus;
5732 size_t setsize;
5733 cpu_set_t *mask = NULL;
5734 PyObject *iterable, *iterator = NULL, *item;
6032 5735
6033 if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O!:sched_setaffinity", 5736 if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O:sched_setaffinity",
6034 &pid, &cpu_set_type, &cpu_set)) 5737 &pid, &iterable))
6035 return NULL; 5738 return NULL;
6036 if (sched_setaffinity(pid, cpu_set->size, cpu_set->set)) 5739
6037 return posix_error(); 5740 iterator = PyObject_GetIter(iterable);
5741 if (iterator == NULL)
5742 return NULL;
5743
5744 ncpus = 1;
5745 setsize = CPU_ALLOC_SIZE(ncpus);
5746 mask = CPU_ALLOC(ncpus);
5747 if (mask == NULL) {
5748 PyErr_NoMemory();
5749 goto error;
5750 }
5751 CPU_ZERO_S(setsize, mask);
5752
5753 while ((item = PyIter_Next(iterator))) {
5754 long cpu;
5755 if (!PyLong_Check(item)) {
5756 PyErr_Format(PyExc_TypeError,
5757 "expected an iterator of ints, "
5758 "but iterator yielded %R",
5759 Py_TYPE(item));
5760 Py_DECREF(item);
5761 goto error;
5762 }
5763 cpu = PyLong_AsLong(item);
5764 Py_DECREF(item);
5765 if (cpu < 0) {
5766 if (!PyErr_Occurred())
5767 PyErr_SetString(PyExc_ValueError, "negative CPU number");
5768 goto error;
5769 }
5770 if (cpu > INT_MAX - 1) {
5771 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
5772 goto error;
5773 }
5774 if (cpu >= ncpus) {
5775 /* Grow CPU mask to fit the CPU number */
5776 int newncpus = ncpus;
5777 cpu_set_t *newmask;
5778 size_t newsetsize;
5779 while (newncpus <= cpu) {
5780 if (newncpus > INT_MAX / 2)
5781 newncpus = cpu + 1;
5782 else
5783 newncpus = newncpus * 2;
5784 }
5785 newmask = CPU_ALLOC(newncpus);
5786 if (newmask == NULL) {
5787 PyErr_NoMemory();
5788 goto error;
5789 }
5790 newsetsize = CPU_ALLOC_SIZE(newncpus);
5791 CPU_ZERO_S(newsetsize, newmask);
5792 memcpy(newmask, mask, setsize);
5793 CPU_FREE(mask);
5794 setsize = newsetsize;
5795 mask = newmask;
5796 ncpus = newncpus;
5797 }
5798 CPU_SET_S(cpu, setsize, mask);
5799 }
5800 Py_CLEAR(iterator);
5801
5802 if (sched_setaffinity(pid, setsize, mask)) {
5803 posix_error();
5804 goto error;
5805 }
5806 CPU_FREE(mask);
6038 Py_RETURN_NONE; 5807 Py_RETURN_NONE;
5808
5809 error:
5810 if (mask)
5811 CPU_FREE(mask);
5812 Py_XDECREF(iterator);
5813 return NULL;
6039 } 5814 }
6040 5815
6041 PyDoc_STRVAR(posix_sched_getaffinity__doc__, 5816 PyDoc_STRVAR(posix_sched_getaffinity__doc__,
6042 "sched_getaffinity(pid, ncpus) -> cpu_set\n\n\ 5817 "sched_getaffinity(pid, ncpus) -> cpu_set\n\n\
6043 Return the affinity of the process with PID *pid*.\n\ 5818 Return the affinity of the process with PID *pid*.\n\
6044 The returned cpu_set will be of size *ncpus*."); 5819 The returned cpu_set will be of size *ncpus*.");
6045 5820
6046 static PyObject * 5821 static PyObject *
6047 posix_sched_getaffinity(PyObject *self, PyObject *args) 5822 posix_sched_getaffinity(PyObject *self, PyObject *args)
6048 { 5823 {
6049 pid_t pid; 5824 pid_t pid;
6050 int ncpus; 5825 int cpu, ncpus, count;
6051 Py_cpu_set *res; 5826 size_t setsize;
5827 cpu_set_t *mask = NULL;
5828 PyObject *res = NULL;
6052 5829
6053 if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:sched_getaffinity", 5830 if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getaffinity",
6054 &pid, &ncpus)) 5831 &pid))
6055 return NULL; 5832 return NULL;
6056 res = make_new_cpu_set(&cpu_set_type, ncpus); 5833
6057 if (!res) 5834 ncpus = 16;
6058 return NULL; 5835 while (1) {
6059 if (sched_getaffinity(pid, res->size, res->set)) { 5836 setsize = CPU_ALLOC_SIZE(ncpus);
6060 Py_DECREF(res); 5837 mask = CPU_ALLOC(ncpus);
6061 return posix_error(); 5838 if (mask == NULL)
5839 return PyErr_NoMemory();
5840 if (sched_getaffinity(pid, setsize, mask) == 0)
5841 break;
5842 CPU_FREE(mask);
5843 if (errno != EINVAL)
5844 return posix_error();
5845 if (ncpus > INT_MAX / 2) {
5846 PyErr_SetString(PyExc_OverflowError, "could not allocate "
5847 "a large enough CPU set");
5848 return NULL;
5849 }
5850 ncpus = ncpus * 2;
6062 } 5851 }
6063 return (PyObject *)res; 5852
5853 res = PySet_New(NULL);
5854 if (res == NULL)
5855 goto error;
5856 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
5857 if (CPU_ISSET_S(cpu, setsize, mask)) {
5858 PyObject *cpu_num = PyLong_FromLong(cpu);
5859 --count;
5860 if (cpu_num == NULL)
5861 goto error;
5862 if (PySet_Add(res, cpu_num)) {
5863 Py_DECREF(cpu_num);
5864 goto error;
5865 }
5866 Py_DECREF(cpu_num);
5867 }
5868 }
5869 CPU_FREE(mask);
5870 return res;
5871
5872 error:
5873 if (mask)
5874 CPU_FREE(mask);
5875 Py_XDECREF(res);
5876 return NULL;
6064 } 5877 }
6065 5878
6066 #endif /* HAVE_SCHED_SETAFFINITY */ 5879 #endif /* HAVE_SCHED_SETAFFINITY */
6067 5880
6068 #endif /* HAVE_SCHED_H */ 5881 #endif /* HAVE_SCHED_H */
6069 5882
6070 /* 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 */
6071 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ 5884 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
6072 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) 5885 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
6073 #define DEV_PTY_FILE "/dev/ptc" 5886 #define DEV_PTY_FILE "/dev/ptc"
(...skipping 5915 matching lines...) Expand 10 before | Expand all | Expand 10 after
11989 Py_DECREF(v); 11802 Py_DECREF(v);
11990 11803
11991 if (all_ins(m)) 11804 if (all_ins(m))
11992 return NULL; 11805 return NULL;
11993 11806
11994 if (setup_confname_tables(m)) 11807 if (setup_confname_tables(m))
11995 return NULL; 11808 return NULL;
11996 11809
11997 Py_INCREF(PyExc_OSError); 11810 Py_INCREF(PyExc_OSError);
11998 PyModule_AddObject(m, "error", PyExc_OSError); 11811 PyModule_AddObject(m, "error", PyExc_OSError);
11999
12000 #ifdef HAVE_SCHED_SETAFFINITY
12001 if (PyType_Ready(&cpu_set_type) < 0)
12002 return NULL;
12003 Py_INCREF(&cpu_set_type);
12004 PyModule_AddObject(m, "cpu_set", (PyObject *)&cpu_set_type);
12005 #endif
12006 11812
12007 #ifdef HAVE_PUTENV 11813 #ifdef HAVE_PUTENV
12008 if (posix_putenv_garbage == NULL) 11814 if (posix_putenv_garbage == NULL)
12009 posix_putenv_garbage = PyDict_New(); 11815 posix_putenv_garbage = PyDict_New();
12010 #endif 11816 #endif
12011 11817
12012 if (!initialized) { 11818 if (!initialized) {
12013 #if defined(HAVE_WAITID) && !defined(__APPLE__) 11819 #if defined(HAVE_WAITID) && !defined(__APPLE__)
12014 waitid_result_desc.name = MODNAME ".waitid_result"; 11820 waitid_result_desc.name = MODNAME ".waitid_result";
12015 PyStructSequence_InitType(&WaitidResultType, &waitid_result_desc); 11821 PyStructSequence_InitType(&WaitidResultType, &waitid_result_desc);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
12141 11947
12142 initialized = 1; 11948 initialized = 1;
12143 11949
12144 return m; 11950 return m;
12145 11951
12146 } 11952 }
12147 11953
12148 #ifdef __cplusplus 11954 #ifdef __cplusplus
12149 } 11955 }
12150 #endif 11956 #endif
OLDNEW
« no previous file with comments | « Lib/test/test_posix.py ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7