Armin Rigo avatar Armin Rigo committed c1a57e0

Last missing piece in the C source: stm_copy_transactional_to_raw()

Comments (0)

Files changed (4)

pypy/rpython/memory/gc/stmgc.py

             # Initialize the copy by doing an stm raw copy of the bytes
             stm_operations.stm_copy_transactional_to_raw(obj, localobj, size)
             #
-            # The raw copy done above includes all header fields.
-            # Check at least the gc flags of the copy.
+            # The raw copy done above does not include the header fields.
             hdr = self.header(obj)
             localhdr = self.header(localobj)
             GCFLAGS = (GCFLAG_GLOBAL | GCFLAG_WAS_COPIED)
             ll_assert(hdr.tid & GCFLAGS == GCFLAGS,
                       "stm_write: bogus flags on source object")
-            ll_assert(localhdr.tid & GCFLAGS == GCFLAGS,
-                      "stm_write: flags not copied!")
             #
             # Remove the GCFLAG_GLOBAL from the copy
-            localhdr.tid &= ~GCFLAG_GLOBAL
+            localhdr.tid = hdr.tid & ~GCFLAG_GLOBAL
             #
             # Set the 'version' field of the local copy to be a pointer
             # to the global obj.  (The field is called 'version' because

pypy/rpython/memory/gc/test/test_stmgc.py

         locals()['stm_read_int%d' % _size] = _func
 
     def stm_copy_transactional_to_raw(self, srcobj, dstobj, size):
-        sizehdr = self._gc.gcheaderbuilder.size_gc_header
-        srchdr = srcobj - sizehdr
-        dsthdr = dstobj - sizehdr
-        llmemory.raw_memcopy(srchdr, dsthdr, sizehdr)
         llmemory.raw_memcopy(srcobj, dstobj, size)
         self._transactional_copies.append((srcobj, dstobj))
 

pypy/translator/stm/src_stm/et.c

 }
 
 /* lazy/lazy read instrumentation */
+#define STM_DO_READ(READ_OPERATION)                                     \
+ 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 */     \
+  READ_OPERATION;                                                       \
+                                                                        \
+  /* postvalidate AFTER reading addr: */                                \
+  CFENCE;                                                               \
+  if (__builtin_expect(o->version != ovt, 0))                           \
+    goto retry;       /* oups, try again */                             \
+                                                                        \
+  oreclist_insert(&d->reads, (orec_t*)o);
+
+
 #define STM_READ_WORD(SIZE, TYPE)                                       \
 TYPE stm_read_int##SIZE(void* addr, long offset)                        \
 {                                                                       \
   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);                               \
-                                                                        \
+  STM_DO_READ(TYPE tmp = *(TYPE *)(((char *)addr) + offset));           \
   return tmp;                                                           \
 }
 
 STM_READ_WORD(4, int)
 STM_READ_WORD(8, long long)
 
+void stm_copy_transactional_to_raw(void *src, void *dst, long size)
+{
+  struct tx_descriptor *d = thread_descriptor;
+  volatile orec_t *o = get_orec(src);
+  owner_version_t ovt;
+
+  assert(!is_main_thread(d));
+
+  /* don't copy the header */
+  src = ((char *)src) + sizeof(orec_t);
+  dst = ((char *)dst) + sizeof(orec_t);
+  size -= sizeof(orec_t);
+
+  STM_DO_READ(memcpy(dst, src, size));
+}
+
 
 static struct tx_descriptor *descriptor_init(_Bool is_main_thread)
 {

pypy/translator/stm/test/test_stmgcintf.py

 
     def test_stm_size_getter(self):
         def getsize(addr):
-            xxx
+            dont_call_me
         getter = llhelper(GETSIZE, getsize)
         stm_operations.setup_size_getter(getter)
-        # just tests that the function is really defined
+        # ^^^ just tests that the function is really defined
+
+    def test_stm_copy_transactional_to_raw(self):
+        # doesn't test STM behavior, but just that it appears to work
+        s1 = lltype.malloc(S1, flavor='raw')
+        s1.hdr.tid = stmgc.GCFLAG_GLOBAL
+        s1.hdr.version = llmemory.NULL
+        s1.x = 909
+        s1.y = 808
+        s2 = lltype.malloc(S1, flavor='raw')
+        s2.hdr.tid = -42    # non-initialized
+        s2.x = -42          # non-initialized
+        s2.y = -42          # non-initialized
+        #
+        s1_adr = llmemory.cast_ptr_to_adr(s1)
+        s2_adr = llmemory.cast_ptr_to_adr(s2)
+        size   = llmemory.sizeof(S1)
+        stm_operations.stm_copy_transactional_to_raw(s1_adr, s2_adr, size)
+        #
+        assert s2.hdr.tid == -42    # not touched
+        assert s2.x == 909
+        assert s2.y == 808
+        #
+        lltype.free(s2, flavor='raw')
+        lltype.free(s1, flavor='raw')
+    test_stm_copy_transactional_to_raw.in_main_thread = False
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.