Author: Brian Kearns <bdkea...@gmail.com>
Branch: 
Changeset: r69289:d674245526d9
Date: 2014-02-23 14:01 -0500
http://bitbucket.org/pypy/pypy/changeset/d674245526d9/

Log:    merge heads

diff --git a/lib-python/2.7/threading.py b/lib-python/2.7/threading.py
--- a/lib-python/2.7/threading.py
+++ b/lib-python/2.7/threading.py
@@ -244,22 +244,11 @@
                 if __debug__:
                     self._note("%s.wait(): got it", self)
             else:
-                # Balancing act:  We can't afford a pure busy loop, so we
-                # have to sleep; but if we sleep the whole timeout time,
-                # we'll be unresponsive.  The scheme here sleeps very
-                # little at first, longer as time goes on, but never longer
-                # than 20 times per second (or the timeout time remaining).
-                endtime = _time() + timeout
-                delay = 0.0005 # 500 us -> initial delay of 1 ms
-                while True:
-                    gotit = waiter.acquire(0)
-                    if gotit:
-                        break
-                    remaining = endtime - _time()
-                    if remaining <= 0:
-                        break
-                    delay = min(delay * 2, remaining, .05)
-                    _sleep(delay)
+                # PyPy patch: use _py3k_acquire()
+                if timeout > 0:
+                    gotit = waiter._py3k_acquire(True, timeout)
+                else:
+                    gotit = waiter.acquire(False)
                 if not gotit:
                     if __debug__:
                         self._note("%s.wait(%s): timed out", self, timeout)
diff --git a/rpython/rlib/_stacklet_asmgcc.py b/rpython/rlib/_stacklet_asmgcc.py
--- a/rpython/rlib/_stacklet_asmgcc.py
+++ b/rpython/rlib/_stacklet_asmgcc.py
@@ -189,7 +189,7 @@
 pypy_asm_stackwalk2 = rffi.llexternal('pypy_asm_stackwalk',
                                       [FUNCNOARG_P,
                                        ASM_FRAMEDATA_HEAD_PTR],
-                                      _c.handle, sandboxsafe=True,
+                                      lltype.Signed, sandboxsafe=True,
                                       _nowrapper=True)
 
 
@@ -273,6 +273,7 @@
         #
         h = pypy_asm_stackwalk2(llhelper(FUNCNOARG_P, _new_callback),
                                 alternateanchor)
+        h = rffi.cast(_c.handle, h)
         #
         llop.gc_reattach_callback_pieces(lltype.Void, callback_pieces)
         return self.get_result_suspstack(h)
@@ -292,6 +293,7 @@
         #
         h = pypy_asm_stackwalk2(llhelper(FUNCNOARG_P, _switch_callback),
                                 alternateanchor)
+        h = rffi.cast(_c.handle, h)
         #
         llop.gc_reattach_callback_pieces(lltype.Void, callback_pieces)
         if not h:
diff --git a/rpython/rlib/rawstorage.py b/rpython/rlib/rawstorage.py
--- a/rpython/rlib/rawstorage.py
+++ b/rpython/rlib/rawstorage.py
@@ -18,17 +18,87 @@
 
 def raw_storage_getitem(TP, storage, index):
     "NOT_RPYTHON"
+    _check_alignment(TP, index)
     return rffi.cast(rffi.CArrayPtr(TP), rffi.ptradd(storage, index))[0]
 
 def raw_storage_setitem(storage, index, item):
     "NOT_RPYTHON"
-    TP = rffi.CArrayPtr(lltype.typeOf(item))
-    rffi.cast(TP, rffi.ptradd(storage, index))[0] = item
+    TP = lltype.typeOf(item)
+    _check_alignment(TP, index)
+    rffi.cast(rffi.CArrayPtr(TP), rffi.ptradd(storage, index))[0] = item
 
 @specialize.arg(1)
 def free_raw_storage(storage, track_allocation=True):
     lltype.free(storage, flavor='raw', track_allocation=track_allocation)
 
+# ____________________________________________________________
+#
+# Support for possibly-unaligned accesses
+
+from rpython.jit.backend import detect_cpu
+try:
+    misaligned_is_fine = detect_cpu.autodetect().startswith('x86')
+except detect_cpu.ProcessorAutodetectError:
+    misaligned_is_fine = False
+
+
+class AlignmentError(NotImplementedError):
+    "Means that raw_storage_{get,set}item was used on unaligned memory"
+
+# Tweak?  It seems a reasonable value for any system out there: requiring
+# an aligned access to be up to 8-bytes-aligned, even for 64-bit data
+# types on 32-bit systems.
+MAXIMUM_ALIGNMENT = 8
+
+@specialize.memo()
+def _get_alignment_mask(TP):
+    size = rffi.sizeof(TP)
+    alignment = 1
+    while (size & alignment) == 0 and alignment < MAXIMUM_ALIGNMENT:
+        alignment *= 2
+    return alignment - 1
+
+def _check_alignment(TP, index):
+    """Check that the 'index' does indeed have the maximum alignment
+    for the given type."""
+    mask = _get_alignment_mask(TP)
+    if (index & mask) != 0:
+        raise AlignmentError
+
+@specialize.ll()
+def raw_storage_getitem_unaligned(TP, storage, index):
+    if misaligned_is_fine:
+        return raw_storage_getitem(TP, storage, index)
+    mask = _get_alignment_mask(TP)
+    if (index & mask) == 0:
+        return raw_storage_getitem(TP, storage, index)
+    ptr = rffi.ptradd(storage, index)
+    with lltype.scoped_alloc(rffi.CArray(TP), 1) as s_array:
+        rffi.c_memcpy(rffi.cast(rffi.VOIDP, s_array),
+                      rffi.cast(rffi.VOIDP, ptr),
+                      rffi.sizeof(TP))
+        return rffi.cast(rffi.CArrayPtr(TP), s_array)[0]
+
+@specialize.ll()
+def raw_storage_setitem_unaligned(storage, index, item):
+    if misaligned_is_fine:
+        raw_storage_setitem(storage, index, item)
+        return
+    TP = lltype.typeOf(item)
+    mask = _get_alignment_mask(TP)
+    if (index & mask) == 0:
+        raw_storage_setitem(storage, index, item)
+        return
+    ptr = rffi.ptradd(storage, index)
+    with lltype.scoped_alloc(rffi.CArray(TP), 1) as s_array:
+        rffi.cast(rffi.CArrayPtr(TP), s_array)[0] = item
+        rffi.c_memcpy(rffi.cast(rffi.VOIDP, ptr),
+                      rffi.cast(rffi.VOIDP, s_array),
+                      rffi.sizeof(TP))
+
+# ____________________________________________________________
+
+
 class RawStorageGetitemEntry(ExtRegistryEntry):
     _about_ = raw_storage_getitem
 
diff --git a/rpython/rlib/test/test_rawstorage.py 
b/rpython/rlib/test/test_rawstorage.py
--- a/rpython/rlib/test/test_rawstorage.py
+++ b/rpython/rlib/test/test_rawstorage.py
@@ -1,23 +1,91 @@
+import py
+import sys
+from rpython.rtyper.lltypesystem import lltype
+from rpython.rlib import rawstorage
+from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage,\
+     raw_storage_setitem, raw_storage_getitem, AlignmentError,\
+     raw_storage_setitem_unaligned, raw_storage_getitem_unaligned
+from rpython.rtyper.test.tool import BaseRtypingTest
+from rpython.translator.c.test.test_genc import compile
 
-from rpython.rtyper.lltypesystem import lltype
-from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage,\
-     raw_storage_setitem, raw_storage_getitem
-from rpython.rtyper.test.tool import BaseRtypingTest
 
 def test_untranslated_storage():
+    r = alloc_raw_storage(37)
+    raw_storage_setitem(r, 8, 1<<30)
+    res = raw_storage_getitem(lltype.Signed, r, 8)
+    assert res == 1<<30
+    raw_storage_setitem(r, 8, 3.14)
+    res = raw_storage_getitem(lltype.Float, r, 8)
+    assert res == 3.14
+    py.test.raises(AlignmentError, raw_storage_getitem, lltype.Signed, r, 3)
+    py.test.raises(AlignmentError, raw_storage_setitem, r, 3, 42.5)
+    free_raw_storage(r)
+
+def test_untranslated_storage_unaligned(monkeypatch):
+    monkeypatch.setattr(rawstorage, 'misaligned_is_fine', False)
     r = alloc_raw_storage(15)
-    raw_storage_setitem(r, 3, 1<<30)
-    res = raw_storage_getitem(lltype.Signed, r, 3)
+    raw_storage_setitem_unaligned(r, 3, 1<<30)
+    res = raw_storage_getitem_unaligned(lltype.Signed, r, 3)
+    assert res == 1<<30
+    raw_storage_setitem_unaligned(r, 3, 3.14)
+    res = raw_storage_getitem_unaligned(lltype.Float, r, 3)
+    assert res == 3.14
     free_raw_storage(r)
-    assert res == 1<<30
+
 
 class TestRawStorage(BaseRtypingTest):
+
     def test_storage_int(self):
         def f(i):
             r = alloc_raw_storage(24)
-            raw_storage_setitem(r, 3, i)
-            res = raw_storage_getitem(lltype.Signed, r, 3)
+            raw_storage_setitem(r, 8, i)
+            res = raw_storage_getitem(lltype.Signed, r, 8)
             free_raw_storage(r)
             return res
+
         x = self.interpret(f, [1<<30])
         assert x == 1 << 30
+
+    def test_storage_float_unaligned(self, monkeypatch):
+        def f(v):
+            r = alloc_raw_storage(24)
+            raw_storage_setitem_unaligned(r, 3, v)
+            res = raw_storage_getitem_unaligned(lltype.Float, r, 3)
+            free_raw_storage(r)
+            return res
+
+        monkeypatch.setattr(rawstorage, 'misaligned_is_fine', False)
+        x = self.interpret(f, [3.14])
+        assert x == 3.14
+
+
+class TestCBackend(object):
+
+    def test_backend_int(self):
+        def f(i):
+            r = alloc_raw_storage(24)
+            raw_storage_setitem(r, 8, i)
+            res = raw_storage_getitem(lltype.Signed, r, 8)
+            free_raw_storage(r)
+            return res != i
+
+        fc = compile(f, [int])
+        x = fc(-sys.maxint // 3)
+        assert x == 0
+
+    def test_backend_float_unaligned(self, monkeypatch):
+        def f(v):
+            r = alloc_raw_storage(24)
+            raw_storage_setitem_unaligned(r, 3, v)
+            res = raw_storage_getitem_unaligned(lltype.Float, r, 3)
+            free_raw_storage(r)
+            return res != v
+
+        if monkeypatch is not None:
+            monkeypatch.setattr(rawstorage, 'misaligned_is_fine', False)
+        fc = compile(f, [float])
+        x = fc(-3.14)
+        assert x == 0
+
+    def test_backend_float_unaligned_allow_misalign(self):
+        self.test_backend_float_unaligned(monkeypatch=None)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to