Author: Matti Picus <matti.pi...@gmail.com> Branch: cpyext-add_newdoc Changeset: r91785:b2f03ffd8457 Date: 2017-07-07 10:53 +0300 http://bitbucket.org/pypy/pypy/changeset/b2f03ffd8457/
Log: merge default into branch diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -21,3 +21,7 @@ .. branch: issue-2592 CPyext PyListObject.pop must return the value + +.. branch: cpyext-hash_notimpl + +If ``tp_hash`` is ``PyObject_HashNotImplemented``, set ``obj.__dict__['__hash__']`` to None diff --git a/pypy/module/_cffi_backend/errorbox.py b/pypy/module/_cffi_backend/errorbox.py --- a/pypy/module/_cffi_backend/errorbox.py +++ b/pypy/module/_cffi_backend/errorbox.py @@ -86,8 +86,6 @@ return w_text = self.space.call_function(w_done) - # XXX Python 3: MessageBoxA() => MessageBoxW() - p = rffi.str2charp(self.space.bytes_w(w_text), track_allocation=False) if self.text_p: diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -456,13 +456,15 @@ return decorate def api_func_from_cdef(func, cdef, cts, - error=_NOT_SPECIFIED, header=DEFAULT_HEADER): + error=_NOT_SPECIFIED, header=DEFAULT_HEADER, + result_is_ll=False): func._always_inline_ = 'try' cdecl = cts.parse_func(cdef) RESULT = cdecl.get_llresult(cts) api_function = ApiFunction( cdecl.get_llargs(cts), RESULT, func, - error=_compute_error(error, RESULT), cdecl=cdecl) + error=_compute_error(error, RESULT), cdecl=cdecl, + result_is_ll=result_is_ll) FUNCTIONS_BY_HEADER[header][cdecl.name] = api_function unwrapper = api_function.get_unwrapper() unwrapper.func = func @@ -656,10 +658,12 @@ class CpyextTypeSpace(CTypeSpace): - def decl(self, cdef, error=_NOT_SPECIFIED, header=DEFAULT_HEADER): + def decl(self, cdef, error=_NOT_SPECIFIED, header=DEFAULT_HEADER, + result_is_ll=False): def decorate(func): return api_func_from_cdef( - func, cdef, self, error=error, header=header) + func, cdef, self, error=error, header=header, + result_is_ll=result_is_ll) return decorate diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py --- a/pypy/module/cpyext/buffer.py +++ b/pypy/module/cpyext/buffer.py @@ -1,10 +1,171 @@ from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import rgc # Force registration of gc.collect +from rpython.rlib.buffer import RawBuffer from pypy.interpreter.error import oefmt +from pypy.interpreter.buffer import BufferView from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, cts, Py_buffer, - Py_ssize_t, Py_ssize_tP, generic_cpy_call, + cpython_api, Py_buffer, Py_ssize_t, Py_ssize_tP, CONST_STRINGP, cts, + generic_cpy_call, PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES) -from pypy.module.cpyext.pyobject import PyObject, Py_IncRef +from pypy.module.cpyext.typeobjectdefs import releasebufferproc +from pypy.module.cpyext.pyobject import PyObject, incref, decref, as_pyobj + +class CBuffer(RawBuffer): + _immutable_ = True + def __init__(self, view): + self.view = view + self.readonly = view.readonly + + def getlength(self): + return self.view.getlength() + + def getitem(self, index): + return self.view.ptr[index] + + def getslice(self, start, stop, step, size): + assert step == 1 + assert stop - start == size + ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), start) + return rffi.charpsize2str(ptr, size) + + def setitem(self, index, char): + self.view.ptr[index] = char + + def setslice(self, index, s): + assert s is not None + ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), index) + rffi.str2chararray(s, ptr, len(s)) + + def get_raw_address(self): + return cts.cast('char *', self.view.ptr) + +class CPyBuffer(BufferView): + # Similar to Py_buffer + _immutable_ = True + + def __init__(self, space, ptr, size, w_obj, format='B', shape=None, + strides=None, ndim=1, itemsize=1, readonly=True, + needs_decref=False, + releasebufferproc=rffi.cast(rffi.VOIDP, 0)): + self.space = space + self.ptr = ptr + self.size = size + self.w_obj = w_obj # kept alive + self.pyobj = as_pyobj(space, w_obj) + self.format = format + self.ndim = ndim + self.itemsize = itemsize + + if not shape: + self.shape = [size] + else: + self.shape = shape + if not strides: + self.strides = [1] + else: + self.strides = strides + self.readonly = readonly + self.needs_decref = needs_decref + self.releasebufferproc = releasebufferproc + + def releasebuffer(self): + if self.pyobj: + if self.needs_decref: + if self.releasebufferproc: + func_target = rffi.cast(releasebufferproc, self.releasebufferproc) + with lltype.scoped_alloc(Py_buffer) as pybuf: + pybuf.c_buf = self.ptr + pybuf.c_len = self.size + pybuf.c_ndim = cts.cast('int', self.ndim) + pybuf.c_shape = cts.cast('Py_ssize_t*', pybuf.c__shape) + pybuf.c_strides = cts.cast('Py_ssize_t*', pybuf.c__strides) + for i in range(self.ndim): + pybuf.c_shape[i] = self.shape[i] + pybuf.c_strides[i] = self.strides[i] + if self.format: + pybuf.c_format = rffi.str2charp(self.format) + else: + pybuf.c_format = rffi.str2charp("B") + generic_cpy_call(self.space, func_target, self.pyobj, pybuf) + decref(self.space, self.pyobj) + self.pyobj = lltype.nullptr(PyObject.TO) + else: + #do not call twice + return + + def getlength(self): + return self.size + + def getbytes(self, start, size): + return ''.join([self.ptr[i] for i in range(start, start + size)]) + + def setbytes(self, start, string): + # absolutely no safety checks, what could go wrong? + for i in range(len(string)): + self.ptr[start + i] = string[i] + + def as_str(self): + return CBuffer(self).as_str() + + def as_readbuf(self): + return CBuffer(self) + + def as_writebuf(self): + assert not self.readonly + return CBuffer(self) + + def get_raw_address(self): + return rffi.cast(rffi.CCHARP, self.ptr) + + def getformat(self): + return self.format + + def getshape(self): + return self.shape + + def getstrides(self): + return self.strides + + def getitemsize(self): + return self.itemsize + + def getndim(self): + return self.ndim + +class FQ(rgc.FinalizerQueue): + Class = CPyBuffer + def finalizer_trigger(self): + while 1: + buf = self.next_dead() + if not buf: + break + buf.releasebuffer() + +fq = FQ() + + +@cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1) +def PyObject_AsCharBuffer(space, obj, bufferp, sizep): + """Returns a pointer to a read-only memory location usable as + character-based input. The obj argument must support the single-segment + character buffer interface. On success, returns 0, sets buffer to the + memory location and size to the buffer length. Returns -1 and sets a + TypeError on error. + """ + pto = obj.c_ob_type + pb = pto.c_tp_as_buffer + if not (pb and pb.c_bf_getreadbuffer and pb.c_bf_getsegcount): + raise oefmt(space.w_TypeError, "expected a character buffer object") + if generic_cpy_call(space, pb.c_bf_getsegcount, + obj, lltype.nullptr(Py_ssize_tP.TO)) != 1: + raise oefmt(space.w_TypeError, + "expected a single-segment buffer object") + size = generic_cpy_call(space, pb.c_bf_getcharbuffer, + obj, 0, bufferp) + if size < 0: + return -1 + sizep[0] = size + return 0 @cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t, lltype.Signed, lltype.Signed], rffi.INT, error=-1) @@ -20,7 +181,7 @@ view.c_len = length view.c_obj = obj if obj: - Py_IncRef(space, obj) + incref(space, obj) view.c_itemsize = 1 rffi.setintfield(view, 'c_readonly', readonly) rffi.setintfield(view, 'c_ndim', 1) diff --git a/pypy/module/cpyext/include/memoryobject.h b/pypy/module/cpyext/include/memoryobject.h --- a/pypy/module/cpyext/include/memoryobject.h +++ b/pypy/module/cpyext/include/memoryobject.h @@ -5,14 +5,7 @@ extern "C" { #endif -/* The struct is declared here but it shouldn't - be considered public. Don't access those fields directly, - use the functions instead! */ -typedef struct { - PyObject_HEAD - Py_buffer view; -} PyMemoryViewObject; - +#include "cpyext_memoryobject.h" /* Get a pointer to the memoryview's private copy of the exporter's buffer. */ #define PyMemoryView_GET_BUFFER(op) (&((PyMemoryViewObject *)(op))->view) diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py --- a/pypy/module/cpyext/memoryobject.py +++ b/pypy/module/cpyext/memoryobject.py @@ -1,29 +1,22 @@ -from rpython.rlib.objectmodel import keepalive_until_here -from pypy.interpreter.error import oefmt from pypy.module.cpyext.api import ( - cpython_api, Py_buffer, CANNOT_FAIL, Py_MAX_FMT, Py_MAX_NDIMS, - build_type_checkers, Py_ssize_tP, PyObjectFields, cpython_struct, - bootstrap_function, Py_bufferP, slot_function, generic_cpy_call) + cpython_api, CANNOT_FAIL, Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers, + Py_ssize_tP, cts, parse_dir, bootstrap_function, Py_bufferP, slot_function) from pypy.module.cpyext.pyobject import ( - PyObject, make_ref, as_pyobj, decref, from_ref, make_typedescr, + PyObject, make_ref, decref, from_ref, make_typedescr, get_typedescr, track_reference) from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.rarithmetic import widen from pypy.objspace.std.memoryobject import W_MemoryView from pypy.module.cpyext.object import _dealloc from pypy.module.cpyext.import_ import PyImport_Import +from pypy.module.cpyext.buffer import CPyBuffer, fq + +cts.parse_header(parse_dir / 'cpyext_memoryobject.h') +PyMemoryViewObject = cts.gettype('PyMemoryViewObject*') PyMemoryView_Check, PyMemoryView_CheckExact = build_type_checkers("MemoryView") -PyMemoryViewObjectStruct = lltype.ForwardReference() -PyMemoryViewObject = lltype.Ptr(PyMemoryViewObjectStruct) -PyMemoryViewObjectFields = PyObjectFields + \ - (("view", Py_buffer),) -cpython_struct( - "PyMemoryViewObject", PyMemoryViewObjectFields, PyMemoryViewObjectStruct, - level=2) - @bootstrap_function def init_memoryobject(space): "Type description of PyDictObject" @@ -32,7 +25,7 @@ attach=memory_attach, dealloc=memory_dealloc, realize=memory_realize, - ) + ) def memory_attach(space, py_obj, w_obj, w_userdata=None): """ @@ -61,7 +54,6 @@ """ Creates the memory object in the interpreter """ - from pypy.module.cpyext.slotdefs import CPyBuffer, fq py_mem = rffi.cast(PyMemoryViewObject, obj) view = py_mem.c_view ndim = widen(view.c_ndim) diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py --- a/pypy/module/cpyext/object.py +++ b/pypy/module/cpyext/object.py @@ -3,7 +3,7 @@ cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, PyVarObject, size_t, slot_function, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, - Py_GE, CONST_STRING, CONST_STRINGP, FILEP, fwrite) + Py_GE, CONST_STRING, FILEP, fwrite) from pypy.module.cpyext.pyobject import ( PyObject, PyObjectP, from_ref, Py_IncRef, Py_DecRef, get_typedescr) @@ -432,30 +432,6 @@ is active then NULL is returned but PyErr_Occurred() will return false.""" return space.call_function(space.builtin.get('dir'), w_o) -@cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1) -def PyObject_AsCharBuffer(space, obj, bufferp, sizep): - """Returns a pointer to a read-only memory location usable as - character-based input. The obj argument must support the single-segment - character buffer interface. On success, returns 0, sets buffer to the - memory location and size to the buffer length. Returns -1 and sets a - TypeError on error. - """ - pto = obj.c_ob_type - - pb = pto.c_tp_as_buffer - if not (pb and pb.c_bf_getreadbuffer and pb.c_bf_getsegcount): - raise oefmt(space.w_TypeError, "expected a character buffer object") - if generic_cpy_call(space, pb.c_bf_getsegcount, - obj, lltype.nullptr(Py_ssize_tP.TO)) != 1: - raise oefmt(space.w_TypeError, - "expected a single-segment buffer object") - size = generic_cpy_call(space, pb.c_bf_getcharbuffer, - obj, 0, bufferp) - if size < 0: - return -1 - sizep[0] = size - return 0 - # Also in include/object.h Py_PRINT_RAW = 1 # No string quotes etc. diff --git a/pypy/module/cpyext/parse/cpyext_memoryobject.h b/pypy/module/cpyext/parse/cpyext_memoryobject.h new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/parse/cpyext_memoryobject.h @@ -0,0 +1,7 @@ +/* The struct is declared here but it shouldn't + be considered public. Don't access those fields directly, + use the functions instead! */ +typedef struct { + PyObject_HEAD + Py_buffer view; +} PyMemoryViewObject; diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -4,7 +4,6 @@ from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.rarithmetic import widen -from rpython.rlib import rgc # Force registration of gc.collect from pypy.module.cpyext.api import ( slot_function, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES, Py_buffer, Py_bufferP, PyTypeObjectPtr, cts) @@ -13,22 +12,20 @@ getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry, ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc, cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc, - readbufferproc, getbufferproc, releasebufferproc, ssizessizeobjargproc) -from pypy.module.cpyext.pyobject import make_ref, decref, as_pyobj, from_ref + readbufferproc, getbufferproc, ssizessizeobjargproc) +from pypy.module.cpyext.pyobject import make_ref, decref, from_ref from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.memoryobject import fill_Py_buffer from pypy.module.cpyext.state import State from pypy.module.cpyext import userslot -from pypy.interpreter.buffer import BufferView +from pypy.module.cpyext.buffer import CBuffer, CPyBuffer, fq from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.argument import Arguments -from rpython.rlib.buffer import RawBuffer from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.objectmodel import specialize, not_rpython from rpython.tool.sourcetools import func_renamer from rpython.flowspace.model import Constant from rpython.flowspace.specialcase import register_flow_sc -from rpython.rtyper.annlowlevel import llhelper from pypy.module.sys.version import CPYTHON_VERSION PY3 = CPYTHON_VERSION[0] == 3 @@ -324,141 +321,6 @@ space.fromcache(State).check_and_raise_exception(always=True) return space.newint(res) -class CPyBuffer(BufferView): - # Similar to Py_buffer - _immutable_ = True - - def __init__(self, space, ptr, size, w_obj, format='B', shape=None, - strides=None, ndim=1, itemsize=1, readonly=True, - needs_decref=False, - releasebufferproc=rffi.cast(rffi.VOIDP, 0)): - self.space = space - self.ptr = ptr - self.size = size - self.w_obj = w_obj # kept alive - self.pyobj = as_pyobj(space, w_obj) - self.format = format - self.ndim = ndim - self.itemsize = itemsize - - if not shape: - self.shape = [size] - else: - self.shape = shape - if not strides: - self.strides = [1] - else: - self.strides = strides - self.readonly = readonly - self.needs_decref = needs_decref - self.releasebufferproc = releasebufferproc - - def releasebuffer(self): - if self.pyobj: - if self.needs_decref: - if self.releasebufferproc: - func_target = rffi.cast(releasebufferproc, self.releasebufferproc) - with lltype.scoped_alloc(Py_buffer) as pybuf: - pybuf.c_buf = self.ptr - pybuf.c_len = self.size - pybuf.c_ndim = cts.cast('int', self.ndim) - pybuf.c_shape = cts.cast('Py_ssize_t*', pybuf.c__shape) - pybuf.c_strides = cts.cast('Py_ssize_t*', pybuf.c__strides) - for i in range(self.ndim): - pybuf.c_shape[i] = self.shape[i] - pybuf.c_strides[i] = self.strides[i] - if self.format: - pybuf.c_format = rffi.str2charp(self.format) - else: - pybuf.c_format = rffi.str2charp("B") - generic_cpy_call(self.space, func_target, self.pyobj, pybuf) - decref(self.space, self.pyobj) - self.pyobj = lltype.nullptr(PyObject.TO) - else: - #do not call twice - return - - def getlength(self): - return self.size - - def getbytes(self, start, size): - return ''.join([self.ptr[i] for i in range(start, start + size)]) - - def setbytes(self, start, string): - # absolutely no safety checks, what could go wrong? - for i in range(len(string)): - self.ptr[start + i] = string[i] - - def as_str(self): - return CBuffer(self).as_str() - - def as_readbuf(self): - return CBuffer(self) - - def as_writebuf(self): - assert not self.readonly - return CBuffer(self) - - def get_raw_address(self): - return rffi.cast(rffi.CCHARP, self.ptr) - - def getformat(self): - return self.format - - def getshape(self): - return self.shape - - def getstrides(self): - return self.strides - - def getitemsize(self): - return self.itemsize - - def getndim(self): - return self.ndim - -class FQ(rgc.FinalizerQueue): - Class = CPyBuffer - def finalizer_trigger(self): - while 1: - buf = self.next_dead() - if not buf: - break - buf.releasebuffer() - -fq = FQ() - - -class CBuffer(RawBuffer): - _immutable_ = True - def __init__(self, view): - self.view = view - self.readonly = view.readonly - - def getlength(self): - return self.view.getlength() - - def getitem(self, index): - return self.view.ptr[index] - - def getslice(self, start, stop, step, size): - assert step == 1 - assert stop - start == size - ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), start) - return rffi.charpsize2str(ptr, size) - - def setitem(self, index, char): - self.view.ptr[index] = char - - def setslice(self, index, s): - assert s is not None - ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), index) - rffi.str2chararray(s, ptr, len(s)) - - def get_raw_address(self): - return cts.cast('char *', self.view.ptr) - - def wrap_getreadbuffer(space, w_self, w_args, func): func_target = rffi.cast(readbufferproc, func) py_obj = make_ref(space, w_self) diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py --- a/pypy/module/cpyext/test/test_bytesobject.py +++ b/pypy/module/cpyext/test/test_bytesobject.py @@ -11,7 +11,7 @@ _PyString_Join) from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP, generic_cpy_call from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref -from pypy.module.cpyext.object import PyObject_AsCharBuffer +from pypy.module.cpyext.buffer import PyObject_AsCharBuffer from pypy.module.cpyext.api import PyTypeObjectPtr diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -1425,3 +1425,31 @@ module.add_doc_string_method(a.foo_43) assert a.foo_43.__doc__ == "A docstring" +class AppTestHashable(AppTestCpythonExtensionBase): + def test_unhashable(self): + if not self.runappdirect: + skip('pointer to function equality available' + ' only after translation') + module = self.import_extension('foo', [ + ("new_obj", "METH_NOARGS", + ''' + PyObject *obj; + obj = PyObject_New(PyObject, &Foo_Type); + return obj; + ''' + )], prologue=''' + static PyTypeObject Foo_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "foo.foo", + }; + ''', more_init = ''' + Foo_Type.tp_flags = Py_TPFLAGS_DEFAULT; + Foo_Type.tp_hash = PyObject_HashNotImplemented; + if (PyType_Ready(&Foo_Type) < 0) INITERROR; + ''') + obj = module.new_obj() + raises(TypeError, hash, obj) + assert type(obj).__dict__['__hash__'] is None + # this is equivalent to + from collections import Hashable + assert not isinstance(obj, Hashable) diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -345,13 +345,19 @@ setattr(struct, slot_names[1], slot_func_helper) def add_operators(space, dict_w, pto): - # XXX support PyObject_HashNotImplemented + from pypy.module.cpyext.object import PyObject_HashNotImplemented + hash_not_impl = PyObject_HashNotImplemented.api_func.get_llhelper(space) for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers: if method_name in dict_w: continue offset = [rffi.offsetof(lltype.typeOf(pto).TO, slot_names[0])] if len(slot_names) == 1: func = getattr(pto, slot_names[0]) + if slot_names[0] == 'c_tp_hash': + if hash_not_impl == func: + # special case for tp_hash == PyObject_HashNotImplemented + dict_w[method_name] = space.w_None + continue else: assert len(slot_names) == 2 struct = getattr(pto, slot_names[0]) diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py --- a/rpython/rlib/rvmprof/cintf.py +++ b/rpython/rlib/rvmprof/cintf.py @@ -58,6 +58,7 @@ SHARED.join('compat.c'), SHARED.join('machine.c'), SHARED.join('vmp_stack.c'), + SHARED.join('vmprof_main.c'), # symbol table already in separate_module_files ] + separate_module_files, post_include_bits=[], diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_main.c b/rpython/rlib/rvmprof/src/shared/vmprof_main.c new file mode 100644 --- /dev/null +++ b/rpython/rlib/rvmprof/src/shared/vmprof_main.c @@ -0,0 +1,30 @@ +#ifdef VMPROF_UNIX + +#include <unistd.h> +/* value: LSB bit is 1 if signals must be ignored; all other bits + are a counter for how many threads are currently in a signal handler */ +static long volatile signal_handler_value = 1; + +void vmprof_ignore_signals(int ignored) +{ + if (!ignored) { + __sync_fetch_and_and(&signal_handler_value, ~1L); + } else { + /* set the last bit, and wait until concurrently-running signal + handlers finish */ + while (__sync_or_and_fetch(&signal_handler_value, 1L) != 1L) { + usleep(1); + } + } +} + +long vmprof_enter_signal(void) +{ + return __sync_fetch_and_add(&signal_handler_value, 2L); +} + +long vmprof_exit_signal(void) +{ + return __sync_sub_and_fetch(&signal_handler_value, 2L); +} +#endif diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_main.h b/rpython/rlib/rvmprof/src/shared/vmprof_main.h --- a/rpython/rlib/rvmprof/src/shared/vmprof_main.h +++ b/rpython/rlib/rvmprof/src/shared/vmprof_main.h @@ -60,25 +60,9 @@ /************************************************************/ -/* value: last bit is 1 if signals must be ignored; all other bits - are a counter for how many threads are currently in a signal handler */ -static long volatile signal_handler_value = 1; - -RPY_EXTERN -void vmprof_ignore_signals(int ignored) -{ - if (!ignored) { - __sync_fetch_and_and(&signal_handler_value, ~1L); - } - else { - /* set the last bit, and wait until concurrently-running signal - handlers finish */ - while (__sync_or_and_fetch(&signal_handler_value, 1L) != 1L) { - usleep(1); - } - } -} - +RPY_EXTERN void vmprof_ignore_signals(int ignored); +RPY_EXTERN long vmprof_enter_signal(void); +RPY_EXTERN long vmprof_exit_signal(void); /* ************************************************************* * functions to write a profile file compatible with gperftools @@ -276,7 +260,7 @@ __sync_lock_release(&spinlock); #endif - long val = __sync_fetch_and_add(&signal_handler_value, 2L); + long val = vmprof_enter_signal(); if ((val & 1) == 0) { int saved_errno = errno; @@ -307,7 +291,7 @@ errno = saved_errno; } - __sync_sub_and_fetch(&signal_handler_value, 2L); + vmprof_exit_signal(); } _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit