Commits

Armin Rigo committed b4d3a59

Reads of 1, 2, 4, 8 bytes here too.

Comments (0)

Files changed (3)

pypy/translator/stm/src_stm/et.c

 
 #include <stdlib.h>
 #include <stdio.h>
-#include <assert.h>
 #include <string.h>
 
 #define USE_PTHREAD_MUTEX    /* optional */
 # define RPY_STM_ASSERT    1
 #endif
 
+#ifdef RPY_STM_ASSERT
+# include <assert.h>
+#else
+# undef assert
+# define assert /* nothing */
+#endif
+
 /************************************************************/
 
 /* This is the same as the object header structure HDR
 } orec_t;
 
 enum {
-  first_gcflag      = 1 << (PYPY_LONG_BIT / 2),
+  first_gcflag      = 1L << (PYPY_LONG_BIT / 2),
   GCFLAG_GLOBAL     = first_gcflag << 0,
   GCFLAG_WAS_COPIED = first_gcflag << 1
 };
 }
 
 /* lazy/lazy read instrumentation */
-long stm_read_word(void* addr, long offset)
-{
-  struct tx_descriptor *d = thread_descriptor;
-  volatile orec_t *o = get_orec(addr);
-  owner_version_t ovt;
+#define STM_READ_WORD(SIZE, TYPE)                                       \
+TYPE stm_read_int##SIZE(void* addr, long offset)                        \
+{                                                                       \
+  struct tx_descriptor *d = thread_descriptor;                          \
+  volatile orec_t *o = get_orec(addr);                                  \
+  owner_version_t ovt;                                                  \
+                                                                        \
+  assert(sizeof(TYPE) == SIZE);                                         \
+                                                                        \
+  if ((o->tid & GCFLAG_WAS_COPIED) != 0)                                \
+    {                                                                   \
+      /* Look up in the thread-local dictionary. */                     \
+      wlog_t *found;                                                    \
+      REDOLOG_FIND(d->redolog, addr, found, goto not_found);            \
+      orec_t *localobj = (orec_t *)found->val;                          \
+      assert((localobj->tid & GCFLAG_GLOBAL) == 0);                     \
+      return *(TYPE *)(((char *)localobj) + offset);                    \
+                                                                        \
+    not_found:;                                                         \
+    }                                                                   \
+                                                                        \
+  /* XXX try to remove this check from the main path */                 \
+  if (is_main_thread(d))                                                \
+    return *(TYPE *)(((char *)addr) + offset);                          \
+                                                                        \
+ retry:                                                                 \
+  /* read the orec BEFORE we read anything else */                      \
+  ovt = o->version;                                                     \
+  CFENCE;                                                               \
+                                                                        \
+  /* this tx doesn't hold any locks, so if the lock for this addr is    \
+     held, there is contention.  A lock is never hold for too long,     \
+     so spinloop until it is released. */                               \
+  if (IS_LOCKED_OR_NEWER(ovt, d->start_time))                           \
+    {                                                                   \
+      if (IS_LOCKED(ovt)) {                                             \
+        tx_spinloop(7);                                                 \
+        goto retry;                                                     \
+      }                                                                 \
+      /* else this location is too new, scale forward */                \
+      owner_version_t newts = get_global_timestamp(d) & ~1;             \
+      validate_fast(d, 1);                                              \
+      d->start_time = newts;                                            \
+    }                                                                   \
+                                                                        \
+  /* orec is unlocked, with ts <= start_time.  read the location */     \
+  TYPE tmp = *(TYPE *)(((char *)addr) + offset);                        \
+                                                                        \
+  /* postvalidate AFTER reading addr: */                                \
+  CFENCE;                                                               \
+  if (__builtin_expect(o->version != ovt, 0))                           \
+    goto retry;       /* oups, try again */                             \
+                                                                        \
+  oreclist_insert(&d->reads, (orec_t*)o);                               \
+                                                                        \
+  return tmp;                                                           \
+}
 
-  if ((o->tid & GCFLAG_WAS_COPIED) != 0)
-    {
-      /* Look up in the thread-local dictionary. */
-      wlog_t *found;
-      REDOLOG_FIND(d->redolog, addr, found, goto not_found);
-      orec_t *localobj = (orec_t *)found->val;
-#ifdef RPY_STM_ASSERT
-      assert((localobj->tid & GCFLAG_GLOBAL) == 0);
-#endif
-      return *(long *)(((char *)localobj) + offset);
-
-    not_found:;
-    }
-
-  // XXX try to remove this check from the main path
-  if (is_main_thread(d))
-    return *(long *)(((char *)addr) + offset);
-
- retry:
-  // read the orec BEFORE we read anything else
-  ovt = o->version;
-  CFENCE;
-
-  // this tx doesn't hold any locks, so if the lock for this addr is held,
-  // there is contention.  A lock is never hold for too long, so spinloop
-  // until it is released.
-  if (IS_LOCKED_OR_NEWER(ovt, d->start_time))
-    {
-      if (IS_LOCKED(ovt)) {
-        tx_spinloop(7);
-        goto retry;
-      }
-      // else this location is too new, scale forward
-      owner_version_t newts = get_global_timestamp(d) & ~1;
-      validate_fast(d, 1);
-      d->start_time = newts;
-    }
-
-  // orec is unlocked, with ts <= start_time.  read the location
-  long tmp = *(long *)(((char *)addr) + offset);
-
-  // postvalidate AFTER reading addr:
-  CFENCE;
-  if (__builtin_expect(o->version != ovt, 0))
-    goto retry;       /* oups, try again */
-
-  oreclist_insert(&d->reads, (orec_t*)o);
-
-  return tmp;
-}
+STM_READ_WORD(1, char)
+STM_READ_WORD(2, short)
+STM_READ_WORD(4, int)
+STM_READ_WORD(8, long long)
 
 
 static struct tx_descriptor *descriptor_init(_Bool is_main_thread)

pypy/translator/stm/stmgcintf.py

 from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.memory.gc.stmgc import PRIMITIVE_SIZES
 from pypy.translator.stm import _rffi_stm
 
 
                             lltype.Void)
     tldict_enum = smexternal('stm_tldict_enum', [CALLBACK], lltype.Void)
 
-    stm_read_word = smexternal('stm_read_word',
-                               [llmemory.Address, lltype.Signed],
-                               lltype.Signed)
+    for _size, _TYPE in PRIMITIVE_SIZES.items():
+        _name = 'stm_read_int%d' % _size
+        locals()[_name] = smexternal(_name, [llmemory.Address, lltype.Signed],
+                                     _TYPE)
 
     stm_copy_transactional_to_raw = smexternal('stm_copy_transactional_to_raw',
                                                [llmemory.Address,

pypy/translator/stm/test/test_stmgcintf.py

 from pypy.translator.stm.stmgcintf import StmOperations, CALLBACK, GETSIZE
 from pypy.rpython.memory.gc import stmgc
 
+WORD = stmgc.WORD
+
 stm_operations = StmOperations()
 
 DEFAULT_TLS = lltype.Struct('DEFAULT_TLS')
                          ('x', lltype.Signed),
                          ('y', lltype.Signed))
 
+# xxx a lot of casts to convince rffi to give us a regular integer :-(
+SIZEOFHDR = rffi.cast(lltype.Signed, rffi.cast(rffi.SHORT,
+                                               rffi.sizeof(S1.hdr)))
+
 
 def test_set_get_del():
     # assume that they are really thread-local; not checked here
 
     def test_tldict_large(self):
         content = {}
-        WORD = rffi.sizeof(lltype.Signed)
         for i in range(12000):
             key = random.randrange(1000, 2000) * WORD
             a1 = rffi.cast(llmemory.Address, key)
             a1 = llmemory.cast_ptr_to_adr(s1)
             a2 = llmemory.cast_ptr_to_adr(s2)
             stm_operations.tldict_add(a1, a2)
-        res = stm_operations.stm_read_word(llmemory.cast_ptr_to_adr(s1),
-                                           rffi.sizeof(S1.hdr))  # 'x'
+        reader = getattr(stm_operations, 'stm_read_int%d' % WORD)
+        res = reader(llmemory.cast_ptr_to_adr(s1), SIZEOFHDR)   # 'x'
         lltype.free(s1, flavor='raw')
         if copied:
             lltype.free(s2, flavor='raw')
         assert res == 84084
     test_stm_read_word_transactional_thread.in_main_thread = False
 
+    def test_stm_read_int1(self):
+        S2 = lltype.Struct('S2', ('hdr', stmgc.StmGC.HDR),
+                                 ('c1', lltype.Char),
+                                 ('c2', lltype.Char),
+                                 ('c3', lltype.Char))
+        s2 = lltype.malloc(S2, flavor='raw')
+        s2.hdr.tid = stmgc.GCFLAG_GLOBAL | stmgc.GCFLAG_WAS_COPIED
+        s2.hdr.version = llmemory.NULL
+        s2.c1 = 'A'
+        s2.c2 = 'B'
+        s2.c3 = 'C'
+        reader = stm_operations.stm_read_int1
+        r1 = reader(llmemory.cast_ptr_to_adr(s2), SIZEOFHDR + 0)  # c1
+        r2 = reader(llmemory.cast_ptr_to_adr(s2), SIZEOFHDR + 1)  # c2
+        r3 = reader(llmemory.cast_ptr_to_adr(s2), SIZEOFHDR + 2)  # c3
+        lltype.free(s2, flavor='raw')
+        assert r1 == 'A' and r2 == 'B' and r3 == 'C'
+
     def test_stm_size_getter(self):
         def getsize(addr):
             xxx